How to refresh an access token for Microsoft Graph API

Adrien Ruffie 1 Reputation point
2022-12-30T08:27:42.027+00:00

Dear all,

I need to use Graph API of Microsoft, For that before I used this following C# code for getting an access and refresh token:

public const string TOKEN_ENDPOINT_URL = "https://login.microsoftonline.com/{0}/oauth2/v2.0/token";  
public const string ALL_SCOPE_AUTHORIZATIONS = "user.read calendars.readwrite calendars.readwrite.shared offline_access openid place.read.all";  
      

 string url = string.Format(TOKEN_ENDPOINT_URL, tenantId);  
  
            Dictionary<string, string> values = new Dictionary<string, string>  
            {  
                { "client_id", clientId },  
                { "scope", ALL_SCOPE_AUTHORIZATIONS },  
                { "client_secret", clientSecret },  
                { "grant_type", "authorization_code" },  
                { "code", authorizationCode }  
            };  
  
            if (!string.IsNullOrEmpty(redirectUri))  
            {  
                values.Add("redirect_uri", redirectUri);  
            }  
  
            FormUrlEncodedContent data = new FormUrlEncodedContent(values);  
  
            HttpClient client = new HttpClient();  
  
            HttpResponseMessage response = client.PostAsync(url, data).Result;  
  
            if (response.IsSuccessStatusCode)  
            {  
                string jsonToken = await response.Content.ReadAsStringAsync();  
                TokenModel tokenModel = await ExtractToken(jsonToken);  
                tokenModel.RedirectUri = redirectUri;  
                return tokenModel;  
            }  

With

private static async Task<TokenModel> ExtractToken(string jsonToken)  
    {  
        JObject jsonData = JObject.Parse(jsonToken);  
        TokenModel tokenModel = new TokenModel();  
        tokenModel.AccessToken = jsonData.SelectToken("access_token").ToString();  
        tokenModel.RefreshToken = jsonData.SelectToken("refresh_token").ToString();  
        tokenModel.Scope = jsonData.SelectToken("scope").ToString().Split(' ').ToList<string>();  
        int duration = jsonData.SelectToken("expires_in").Value<int>();  
        if (duration > 0)  
        {  
            tokenModel.ExpirationDate = DateTime.Now.AddSeconds(duration);  
        }  
        tokenModel.TokenType = jsonData.SelectToken("token_type").ToString();  
        return tokenModel;  
    }  

And I refresh it by:

string url = string.Format(TOKEN_ENDPOINT_URL, tenantId);  
  
            Dictionary<string, string> values = new Dictionary<string, string>  
            {  
                { "client_id", clientId },  
                { "scope", ALL_SCOPE_AUTHORIZATIONS },  
                { "client_secret", clientSecret },  
                { "grant_type", "refresh_token" },  
                { "refresh_token", refreshToken }  
            };  
  
            if (!string.IsNullOrEmpty(redirectUri))  
            {  
                values.Add("redirect_uri", redirectUri);  
            }  
  
            FormUrlEncodedContent data = new FormUrlEncodedContent(values);  
  
            HttpClient client = new HttpClient();  
  
            HttpResponseMessage response = client.PostAsync(url, data).Result;  
            if (response.IsSuccessStatusCode)  
            {  
                string jsonToken = await response.Content.ReadAsStringAsync();  
                TokenModel tokenModel = await ExtractToken(jsonToken);  
                tokenModel.RedirectUri = redirectUri;  
                return tokenModel;  
            }  

And now I refactored my code and use:

 ConfidentialClientApplicationBuilder builder = ConfidentialClientApplicationBuilder.Create(clientId)  
        .WithRedirectUri(redirectUri)  
        .WithTenantId(tenantId)  
        .WithClientSecret(clientSecret);  
        IConfidentialClientApplication confidentialClientApp = builder.Build();  
  
        AcquireTokenByAuthorizationCodeParameterBuilder acquireTokenBuilder =  
            confidentialClientApp.AcquireTokenByAuthorizationCode(ALL_SCOPE_AUTHORIZATIONS.Split(' '), authorizationCode);  
  
        AuthenticationResult result = await acquireTokenBuilder.ExecuteAsync();  
        // NO string refreshToken = result.RefreshToken  
        return new TokenModel()  
        {  
            AccessToken = result.AccessToken,  
            ExpirationDate = result.ExpiresOn,  
            Scope = result.Scopes.ToList(),  
            TokenType = result.TokenType,  
            RedirectUri = redirectUri  
        };  

And I saw that the refresh token isn't provided yet ...
Now how I can refresh my access token plz when it expire ?

Take in accound that I don't keep the confidentialClientApp and the autorization code previous generated by a client (sign-in) at the method ending.

Plz anyone can help plz ?

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
13,263 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bhanu Kiran 3,611 Reputation points
    2022-12-30T21:18:07.363+00:00

    Hello @Adrien Ruffie ,

    There is no refresh token for client credentials.

    The issuance of a refresh token with the client credential grant has no benefit. That is why the RFC6749 section 4.4.3 indicates A refresh token SHOULD NOT be included. Thus, its issuance is at the discretion of the authorization server.

    The client can make the same call again to obtain a new access token. By the way, you can extend the lifetime of the access token by configuring the access token lifetime policy, but the maximum lifetime of the token still cannot exceed 24 hours.

    So if you want to get refresh token the only way is to use auth code flow or ROPC flow.

    Hope this helps.

    If the answer is helpful, please click Accept Answer and kindly upvote. If you have any further questions about this answer, please click Comment.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.