locked
Adding a custom claimtype to AAD security token in OWIN web client using AAD library? RRS feed

  • Question

  • Hello,

    I've created a WebApi OData service using VS2013, which is fully updated.  The WebApi template built the service using the OWIN stack.  The WebApi OData service is working well, so I am adding Azure Active Directory authentication to a test web client and to the service.  I've followed Vittorio Bertocci's online tutorials and things are working properly, but...

    We will save a accountId and userId in each AD user's AAD profile using the Graph api.  After a user has been authenticated, we need to add these two items as custom claimtypes to the security token that will be sent with requests to the WebApi.  The WebApi will use these items for queries and other tasks.

    I do not know how to add these custom claimtypes to a security token from Azure AD, and haven't been able to find any examples online.  So, I hope that someone can give me a nudge in the correct direction.  The following code gets the AAD access token:

    string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
                    
    AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
                    
    ClientCredential credential = new ClientCredential(clientId, appKey);
                    
    result = authContext.AcquireTokenSilent(todoListResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

    Okay, at this point we have an access token from AAD.  How do I add the following custom claimtypes to it?

    new Claim("http://schemas.aboh/identity/claims/accountid", "123"));
    new Claim("http://schemas.aboh/identity/claims/userid", "1234"));

    I appreciate your help and thank you for your time and suggestions,

    Mike
    Saturday, August 2, 2014 7:06 PM

Answers

  • Adding Claims in the SecurityTokenValidated notification is fine. This will result in the claims being added to the 'cookie'.

    Brent Schmaltz - MSFT

    Monday, August 4, 2014 3:56 PM

All replies

  • Hello,

    The following link should be helpful with Custom ClaimTypes:

    http://msdn.microsoft.com/en-us/library/ee517261.aspx

    Regards,

    Neelesh

    Saturday, August 2, 2014 7:37 PM
  • Hi Neelesh,

    Thank you very much for your response.  In the past, I've used a custom token handler to do claim transformation, but the new web app template in VS2013 is built on OWIN and we have the Azure Active Directory Library available (AADL), so I am wondering whether there is a simpler way to accomplish this task in the client web app.  For example, the following method, "TransformPrincipal", gets the Azure Active Directory authenticated principal, adds my claims to it, and saves it to the current thread. 

    I don't know where I should insert a call to invoke this method... 

    Would the transformation have to be invoked multiple times?

    I don't know whether these claims will be passed along in a WebAPI request that includes an access token from Azure Active Directory, which is obtained from the code fragment at the bottom of this posting.

    In short, I am trying to figure out how to inject two custom claim types into the default Azure Active Directory authentication flow in a webapp.  I'd appreciate learning anything about how to accomplish this task... I am still scouring the Internet, but most of the information is out of date with respect to OWIN.

            private void TransformPrincipal()
            {
                // Get the existing claims for the authenticated user.
                var cp = System.Threading.Thread.CurrentPrincipal as ClaimsPrincipal;
                List<Claim> claims = new List<Claim>(cp.Claims);

                // Add our custom claim types...
                claims.Add(new Claim("http://schemas.aboh/identity/claims/accountid", "123"));
                claims.Add(new Claim("http://schemas.aboh/identity/claims/userid", "1234"));

                // Create a new identity using our claims...
                var claimsid = new ClaimsIdentity(cp.Identity, claims);

                // Create a new claims principal...
                var newcp = new ClaimsPrincipal(claimsid);

                // Set the new claim principal on the current thread...
                System.Threading.Thread.CurrentPrincipal = newcp;
            }

    // Get Azure Active Directory's access token...
    AuthenticationContext ac =
        new AuthenticationContext("https://login.windows.net/cloudidentity.net");
    AuthenticationResult ar =
        ac.AcquireToken("https://cloudidentity.net/WindowsAzureADWebAPITest",
                        "a4836f83-0f69-48ed-aa2b-88d0aed69652",
                        new Uri("https://cloudidentity.net/myWebAPItestclient"));

    // Prepare and send the request to WebApi
    string authHeader = ar.CreateAuthorizationHeader();
     HttpClient client = new HttpClient();
     HttpRequestMessage request =
         new HttpRequestMessage(HttpMethod.Get, "https://localhost:44353/api/Values");
     request.Headers.TryAddWithoutValidation("Authorization", authHeader);
     HttpResponseMessage response = await client.SendAsync(request);
     string responseString = await response.Content.ReadAsStringAsync();

    Thanks,
    Mike

    Sunday, August 3, 2014 2:10 AM
  • OWIN is definitely a different kind of animal...  It seems that rather than using a custom token handler, we can add claims in Startup.Auth.cs, in ConfigureAuth.  The only issue that I have is that I cannot find a Provider that is defined for WsFederationAuthenticationOptions, which is used by Azure Active Directory authentication.  Any ideas?

    Thanks!

    Mike

            public void ConfigureAuth(IAppBuilder app)
            {
                app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);

                app.UseCookieAuthentication(
                    new CookieAuthenticationOptions
                    {
                        AuthenticationType =
                           WsFederationAuthenticationDefaults.AuthenticationType
                    });
                
                app.UseWsFederationAuthentication(
                    new WsFederationAuthenticationOptions
                    {
                        MetadataAddress = "https://login.windows.net/expirationtrax.com/federationmetadata/2007-06/federationmetadata.xml",
                        Wtrealm = "http://localhost:63191/",

                        Provider = new ??????????????????Provider // WHAT SHOULD WE USE HERE FOR AZURE ACTIVE DIRECTORY'S PROVIDER?
                        {
                            OnAuthenticated = (context) =>
                            {
                                context.Identity.AddClaim(new Claim("http://schemas.aboh/identity/claims/accountid", "123", "ET"));
                                context.Identity.AddClaim(new Claim("http://schemas.aboh/identity/claims/userid", "1234", "ET"));
                            }
                        }

                });
            }

    Sunday, August 3, 2014 3:11 AM
  • After a lot of searching and research, I've cobbled together the following code and it seems to work.  I'd appreciate a sanity check as to its correctness.

    Thanks,

    Mike

            public void ConfigureAuth(IAppBuilder app)
            {
                app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);

                app.UseCookieAuthentication(
                    new CookieAuthenticationOptions
                    {
                        AuthenticationType =
                           WsFederationAuthenticationDefaults.AuthenticationType // Okay, or should it be CookieAuthenticationDefaults.AuthenticationType
                    });

                app.UseWsFederationAuthentication(
                    new WsFederationAuthenticationOptions
                    {
                        MetadataAddress = "https://login.windows.net/abcd.com/federationmetadata/2007-06/federationmetadata.xml",
                        Wtrealm = "http://localhost:63191/",
                        //SignOutWreply = ConfigurationManager.AppSettings["owin:SignOutWreply"],

                        Notifications = new WsFederationAuthenticationNotifications()
                        {
                            SecurityTokenValidated = notification =>
                            {
                                notification.AuthenticationTicket.Identity.AddClaim(new Claim("http://schemas.aboh/identity/claims/accountid", "123", "ET"));
                                notification.AuthenticationTicket.Identity.AddClaim(new Claim("http://schemas.aboh/identity/claims/userid", "321", "ET"));

                                return Task.FromResult(0);
                            }
                        }

                    });
            }
    Sunday, August 3, 2014 3:53 AM
  • Adding Claims in the SecurityTokenValidated notification is fine. This will result in the claims being added to the 'cookie'.

    Brent Schmaltz - MSFT

    Monday, August 4, 2014 3:56 PM
  • Hello,

    The above mentioned scenario(s) require specialised Root Cause Analysis, hence we would request you to open a new Service Request for us to assist you on the same. The link below should be helpful for you to open a new Service Request.

    http://azure.microsoft.com/en-us/support/options/

    Regards,

    Neelesh.

    Wednesday, August 13, 2014 5:12 PM