Microsoft Graph 访问令牌刷新

Microsoft Graph access token refresh

我正在编写一个应用程序,该应用程序使用“OAuth 2.0 客户端凭据授予流程”来获取用于调用 Microsoft Graph 的访问令牌 API。应用程序以自身身份进行身份验证,而不代表登录用户。

我的代码基于此 example from Microsoft

这是我初始化 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);

这就是我后来使用它的方式(例如):

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

我的申请是 API。它不是一个运行一次就完成的应用程序。会持续运行很长一段时间。所以我担心访问令牌过期时会发生什么。如何确保在我需要使用 graphClient 时访问令牌不会过期?

根据您上面的代码片段,我认为您正在使用 graph SDK 并使用客户端凭据流作为身份验证。

所以我们不需要在这里生成访问令牌,只需使用 graphClient 调用图 api 并收集您需要的信息。由于这种模式,它不会出现 token expired 的情况,因为每次调用 api 都会在它之前 new clientSecretCredential

让我们回到 refresh,当我们尝试获取刷新令牌时,Azure 广告提供刷新令牌以在访问令牌过期时刷新访问令牌,因为刷新令牌的过期时间比访问令牌长得多, 我们需要将 offline_access 附加到范围 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.

然后你可能有一些想法坚持使用refresh the expired token过程,那么你只能先生成一个访问令牌并保存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以获取更多详细信息:

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);
...
}