Search code examples
asp.net-coreazure-active-directoryclaims-based-identityclaims

Getting access to "employeeId" or "jobTitle" Claim via Asp.Net Core 2.2 with AzureAd


I'm trying to extend the claims I get back from AzureAd. I know there's more available, but I have no idea where to start. The documentation is all over the place.

I basically have an ASP .Net Core 2.2 web application configured as follows:

            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
                .AddAzureAD(options => Configuration.Bind("AzureAd", options));

            services.AddMvc(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

When trying to access the claims via code below, I don't get but the standard ones, whilst there are more loaded in AzureAd & Graph.

            var claimsIdentity = User.Identity as ClaimsIdentity;
            ClaimsDetected = claimsIdentity?.Claims.ToList();   

I already adapted the manifest file with various options, but nothing seems to work. I googled my *ss off - but all documentation is over the place and not consistent or out of date.

Has anyone a working example or tutorial or could anyone tell me how I can enrich my claim set with specific types I found in the graph?

Thanks


Solution

  • For accessing jobTitle from Azure AD to Claims, you will need to get the accesstoken to get jobTitle by Graph API.

    Detail steps.

    1. For getting accesstoken, you need to provide the ClientSecret in Azure App registrations
    2. App Registrations->Your application->Settings->Keys->ClientSecret or any string for Key Description-> Expires for your own scenario-> Copy the generated ClientSecret
    3. Startup.cs

      public void ConfigureServices(IServiceCollection services)
      {
          services.Configure<CookiePolicyOptions>(options =>
          {
              // This lambda determines whether user consent for non-essential cookies is needed for a given request.
              options.CheckConsentNeeded = context => true;
              options.MinimumSameSitePolicy = SameSiteMode.None;
          });
      
          services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
              .AddAzureAD(options => Configuration.Bind("AzureAd", options));
          services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
          {
              options.ResponseType = "id_token code";
              options.ClientSecret = "ClientSecret in Azure";
              options.Events = new OpenIdConnectEvents
              {
                  OnAuthorizationCodeReceived = async context => {
                      // Acquire a Token for the Graph API and cache it using ADAL. In the TodoListController, we'll use the cache to acquire a token for the Todo List API
                      string userObjectId = (context.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
                      var authContext = new AuthenticationContext(context.Options.Authority);
                      var credential = new ClientCredential(context.Options.ClientId, context.Options.ClientSecret);
      
                      var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code,
                          new Uri(context.TokenEndpointRequest.RedirectUri, UriKind.RelativeOrAbsolute), credential, "https://graph.microsoft.com");
      
                      // Notify the OIDC middleware that we already took care of code redemption.
                      context.HandleCodeRedemption(authResult.AccessToken, context.ProtocolMessage.IdToken);
                      HttpClient client = new HttpClient();
                      HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
                      request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
                      HttpResponseMessage response = await client.SendAsync(request);
                      var result = await response.Content.ReadAsStringAsync();
                      // Parse your Result to an Array
                      var jArray = JObject.Parse(result);
                      // Index the Array and select your jobTitle
                      var obj = jArray["jobTitle"].Value<string>();
                      var identity = context.Principal.Identity as ClaimsIdentity;
                      identity.AddClaim(new Claim("jobTitle", obj));
                      await Task.Yield();
                  },
              };
          });
          services.AddMvc(options =>
          {
              var policy = new AuthorizationPolicyBuilder()
                  .RequireAuthenticatedUser()
                  .Build();
              options.Filters.Add(new AuthorizeFilter(policy));
          })
          .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
      }