Search code examples
asp.net-coremicrosoft-graph-apimicrosoft-graph-sdks

Microsoft Graph access token refresh


I am writing an application that uses the "OAuth 2.0 client credentials grant flow" to get an access token for calling the Microsoft Graph API. The application authenticates as itself, not on behalf of a signed in user.

I based my code off of this example from Microsoft.

This is how I initialize the GraphServiceClient:

    // Read application settings from appsettings.json (tenant ID, app ID, client secret, etc.)
    AppSettings config = AppSettingsFile.ReadFromJsonFile();

    // Initialize the client credential auth provider
    var scopes = new[] { "https://graph.microsoft.com/.default" };
    var clientSecretCredential = new ClientSecretCredential(config.TenantId, config.AppId, config.ClientSecret);
    var graphClient = new GraphServiceClient(clientSecretCredential, scopes);

And this is how I later use it (for example):

var users = await graphClient.Users.Request().GetAsync();

My application is an API. It is not an application that runs once and done. It will be continuously running for a long time. So I am concerned about what will happen when the access token expires. How do I make sure that when I need to use the graphClient the access token will not be expired?


Solution

  • According to your code snippet above, I think you are using the graph SDK and using the client credential flow as the authentication.

    So we are no need to generate access token here but just using the graphClient to call the graph api and gather the information you needed. And due to this mode, it won't appear the token expired situation as each time you call an api you will new clientSecretCredential before it.

    And let's come back to the refresh, azure ad provide refresh token for refreshing the access token when it expired as refresh token has much longer expire time than access token, when we try to get the refresh token, we need to append offline_access to the scope when generate the access. But using client credential flow means your app requests a new token with it's own credentials, so it's no need to using refresh token to avoid making signed-in user sign in again. Using credential flow shouldn't return refresh token.

    enter image description here

    Then you may have some ideas that you insist on using refresh the expired token process, then what you only can do is generate an access token first and save the token with its expired time in some place, and using the access token as the http request header and calling graph api. Then the code should like this, but I don't think you're willing to using this kind of code, you may also refer to this document for more details:

    var scopes = new[] { "https://graph.microsoft.com/.default" };
    var tenantId = "tenant_name.onmicrosoft.com";
    var clientId = "your_azuread_clientid";
    var clientSecret = "corresponding_client_secret";
    var clientSecretCredential = new ClientSecretCredential(
        tenantId, clientId, clientSecret);
    var tokenRequestContext = new TokenRequestContext(scopes);
    var token = clientSecretCredential.GetTokenAsync(tokenRequestContext).Result.Token;
    
    //using http sender with the token
    httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token );
    // Call the web API.
    HttpResponseMessage response = await _httpClient.GetAsync(apiUri);
    ...
    }