12

I am following the below GitHub sample for implementing Authentication mechanism across WebApp and WebApi.

https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet

I am using a single App registration for both WebApp and WebApi, get a access token for "https://abc.onmicrosoft.com/App" and pass it on to WebApi. I am attaching the token to the HTTPS headers with the name "Bearer". I have the below in the WebApi Owin Startup class to validate the token for the Audience and Tenant, but does not actually validate the token for these as expected.

A couple of questions: 1. What triggers the below handler to validate the token for the tenant and audience? Is it the [Authorize] attribute on the Controller class? 2. How does it where to find the token to execute the handler? 3. Setting the SaveSigninToken to true saves the token. How can I retrieve the token and also Acquire access token for Graph API from this token?

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
              new WindowsAzureActiveDirectoryBearerAuthenticationOptions
              {
                  Tenant = "abc.onmicrosoft.com",

                  TokenValidationParameters = new TokenValidationParameters
                  {
                      ValidAudience = "https://abc.onmicrosoft.com/App",
                      SaveSigninToken = true,
                  }
              });

Please advise. Thanks in advance!

SteelBird82
  • 759
  • 3
  • 10
  • 23

2 Answers2

6

What triggers the below handler to validate the token for the tenant and audience?

The middleware runs in Active mode by default, so it will attempt to find a token in every request. If it finds one, it will attempt to validate it. If it finds that it is valid, a ClaimsPrincipal is created which is accessible in further OWIN middleware and Web API components.

It also downloads the public keys with which it checks the token signature on app startup from Azure AD. You can see this if you use a tool like Fiddler.

How does it where to find the token to execute the handler?

I'm not sure if I am understanding this question, I hope my answer above clarified the process.

Setting the SaveSigninToken to true saves the token. How can I retrieve the token and also Acquire access token for Graph API from this token?

What you are trying to do is call an API using the on-behalf-of flow. You can find an example app here: https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof. More specifically this part should be of interest to you: https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof/blob/master/TodoListService/Controllers/TodoListController.cs#L133.

        ClientCredential clientCred = new ClientCredential(clientId, appKey);
        var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
        string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
        string userAccessToken = bootstrapContext.Token;
        UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);

        string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
        string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        AuthenticationContext authContext = new AuthenticationContext(authority, new DbTokenCache(userId));

        // In the case of a transient error, retry once after 1 second, then abandon.
        // Retrying is optional.  It may be better, for your application, to return an error immediately to the user and have the user initiate the retry.
        bool retry = false;
        int retryCount = 0;

        do
        {
            retry = false;
            try
            {
                result = await authContext.AcquireTokenAsync(graphResourceId, clientCred, userAssertion);
                accessToken = result.AccessToken;
            }
            catch (AdalException ex)
            {
                if (ex.ErrorCode == "temporarily_unavailable")
                {
                    // Transient error, OK to retry.
                    retry = true;
                    retryCount++;
                    Thread.Sleep(1000);
                }
            }
        } while ((retry == true) && (retryCount < 1));
juunas
  • 54,244
  • 13
  • 113
  • 149
-1

The [Authorize] decoration in the controller or whichever method we specify triggers the Owin security handler to validate the token and generates the claims.

SteelBird82
  • 759
  • 3
  • 10
  • 23
  • Does it connect to azure each time to validate token? – Jaanus Apr 06 '16 at 12:04
  • 1
    I have the same question that Jaanus does – Carlos Rodriguez Aug 05 '16 at 17:09
  • 1
    @Jaanus The token contains the information required to validate it. – Alexander Jan 30 '17 at 07:22
  • 2
    This answer is not correct. The authentication middleware runs on every request. The middleware component downloads the public keys from Azure AD on startup at least, and uses that info to validate incoming tokens. If it finds a valid token in the request, it constructs a ClaimsPrincipal from it to identify the user. `AuthorizeAttribute` just checks the user's identity, which will be there if authentication was done successfully. – juunas Apr 12 '17 at 07:55
  • 1
    Downvoting, since this is not correct. See juunas's answer instead. – AzureMinotaur Oct 05 '17 at 17:42