locked
Best practice retrieving Azure AD JWT Tokens to authorize against a custom web API RRS feed

  • Question

  • User-1004235376 posted

    Dear readers,

    I want to authenticate my .NET Core 3.1 Blazor Server (Client) against my custom .NET Core 3.1 Web API. 
    For this I use the practice of JTW Bearer. To retrieve a valid token my client sends a request to Azure AD including a client secret (showing
    the client is allowed to retrieve a token). Onces the token is received this is added to the HTTP request to the web API.

    I have some questions about best practices.

    1. Where do I implement the retrieval of a token, is that in startup.cs or program.cs or elsewhere?
    2. How often to I retrieve a token? Because I use aquiretokenforclient the token is bound to the client and not the user.
    3. If I aquire a token for a client instead of a user does this mean that every user uses the same token or when they use the client
      the client makes sure tokens are refreshed?
    4. They way I implement token retrieval, am I sure tokens are refreshed?

    In fact, I got it working and was able to retrieve data from my web API authorised using the token. My code looks as follows using MSAL.

    startup.cs

    private async Task<AuthenticationResult> RunAsync()
            {
                IConfidentialClientApplication app;
                app = ConfidentialClientApplicationBuilder.Create("clientID")
                                                          .WithClientSecret("clientSecret")
                                                          .WithAuthority(new Uri("https://login.microsoftonline.com/79e14469-174a-4e55-add7-eb32eccb14d1/oauth2/v2.0/authorize"))
                                                          .Build();
    
                string[] scopes = new string[] { "resourceID" };
                try
                {
                    AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
                    return result;
                }
                catch (System.Exception)
                {
                    return null;
                }
            }

    The above is a method I created in the startup.cs. It retrieves a token async.
    Then in startup.cs 

    AuthenticationResult token = RunAsync().GetAwaiter().GetResult();
                
                services.AddHttpClient<IRelationService, RelationService>(client =>
                { 
                    client.DefaultRequestHeaders.Authorization
                             = new AuthenticationHeaderValue("Bearer", token.AccessToken);
                });

    Don't mind the clientsecret being hardcoded because in production this is managed by the azure key vault.

    Thanks in advance! 

    Saturday, July 25, 2020 1:31 PM

All replies