当我已经将用户的刷新令牌存储在数据库中时,使用 Microsoft.Graph SDK 的最佳方式?
Best way to use Microsoft.Graph SDK when I already have users' refresh tokens stored in database?
我正在构建一个多用户、多租户的应用程序,它将代表许多离线用户访问 Microsoft Graph API。
由于应用程序使用Microsoft Identity 进行外部OIDC 身份验证,在用户首次登录时,我已经请求了相应的scopes/consents 并收到了Microsoft 颁发的access/refresh 令牌。令牌保存在数据库中。
现在我想使用 Microsoft.Graph
这使得访问图形 API 变得容易得多,但似乎这个 SDK 的很大一部分是为了检索令牌而编写的,我不需要它,因为我已经有代币了。
但是,我希望 SDK 客户端自动使用存储的刷新令牌来获取新的访问令牌,而不是必须自己手动处理刷新逻辑(如果可能的话)。
经过研究,我发现我可以在构造GraphServiceClient
时为AuthenticationProvider
传入一个null
,然后像这样手动将不记名令牌附加到客户端:
var graphClient = new GraphServiceClient(authenticationProvider: null);
var requestHeaders = new List<HeaderOption>()
{ new HeaderOption("Authorization", "Bearer " + myToken) };
var me = await graphClient.Me.Request(requestHeaders).GetAsync();
这确实有效并绕过了客户端的令牌检索逻辑,但现在的问题是它不会处理访问令牌expiration/renewal。所以我必须使用单独的代码来确保我始终传入未过期的访问令牌,并在必要时使用刷新令牌自己更新令牌。
我想知道是否有一种方法可以自定义 GraphServiceClient
,这样它就不会尝试使用单独的 OAuth2/OIDC 流程获取令牌,而是知道如何找到存储在中的现有刷新令牌我的数据库,并使用该刷新令牌来管理其 renewal/expiration 逻辑,就像它对其通过常规流接收的令牌所做的那样。
理想的流程是这样的:
传入一个参数(我数据库中的用户ID)创建一个GraphServiceClient
.
客户端使用此用户 ID 查找我的数据库 (EF Core) 中存储的令牌。
如果存储的访问令牌已经过期,使用存储的刷新令牌获取新的,并更新数据库中的令牌。
SDK 可以吗?
非常感谢您的建议。
您可以在自己的自定义class中实现IAuthenticationProvider
接口,然后在AuthenticateRequestAsync
函数中做必要的标记checking/refresh。有关示例,请参阅 https://github.com/microsoftgraph/msgraph-training-dotnet-core/blob/main/demo/GraphTutorial/Authentication/DeviceCodeAuthProvider.cs。
我建议查看 MSAL library 来为您处理所有令牌逻辑。您可以连接到它的令牌缓存以按照您想要的方式对其进行序列化(例如,将其存储在您的数据库中)。在我链接的示例中,我使用的是 MSAL,您可以看到我不需要对过期令牌进行任何检查,一切都已为我处理。
我正在构建一个多用户、多租户的应用程序,它将代表许多离线用户访问 Microsoft Graph API。
由于应用程序使用Microsoft Identity 进行外部OIDC 身份验证,在用户首次登录时,我已经请求了相应的scopes/consents 并收到了Microsoft 颁发的access/refresh 令牌。令牌保存在数据库中。
现在我想使用 Microsoft.Graph
这使得访问图形 API 变得容易得多,但似乎这个 SDK 的很大一部分是为了检索令牌而编写的,我不需要它,因为我已经有代币了。
但是,我希望 SDK 客户端自动使用存储的刷新令牌来获取新的访问令牌,而不是必须自己手动处理刷新逻辑(如果可能的话)。
经过研究,我发现我可以在构造GraphServiceClient
时为AuthenticationProvider
传入一个null
,然后像这样手动将不记名令牌附加到客户端:
var graphClient = new GraphServiceClient(authenticationProvider: null);
var requestHeaders = new List<HeaderOption>()
{ new HeaderOption("Authorization", "Bearer " + myToken) };
var me = await graphClient.Me.Request(requestHeaders).GetAsync();
这确实有效并绕过了客户端的令牌检索逻辑,但现在的问题是它不会处理访问令牌expiration/renewal。所以我必须使用单独的代码来确保我始终传入未过期的访问令牌,并在必要时使用刷新令牌自己更新令牌。
我想知道是否有一种方法可以自定义 GraphServiceClient
,这样它就不会尝试使用单独的 OAuth2/OIDC 流程获取令牌,而是知道如何找到存储在中的现有刷新令牌我的数据库,并使用该刷新令牌来管理其 renewal/expiration 逻辑,就像它对其通过常规流接收的令牌所做的那样。
理想的流程是这样的:
传入一个参数(我数据库中的用户ID)创建一个
GraphServiceClient
.客户端使用此用户 ID 查找我的数据库 (EF Core) 中存储的令牌。
如果存储的访问令牌已经过期,使用存储的刷新令牌获取新的,并更新数据库中的令牌。
SDK 可以吗?
非常感谢您的建议。
您可以在自己的自定义class中实现IAuthenticationProvider
接口,然后在AuthenticateRequestAsync
函数中做必要的标记checking/refresh。有关示例,请参阅 https://github.com/microsoftgraph/msgraph-training-dotnet-core/blob/main/demo/GraphTutorial/Authentication/DeviceCodeAuthProvider.cs。
我建议查看 MSAL library 来为您处理所有令牌逻辑。您可以连接到它的令牌缓存以按照您想要的方式对其进行序列化(例如,将其存储在您的数据库中)。在我链接的示例中,我使用的是 MSAL,您可以看到我不需要对过期令牌进行任何检查,一切都已为我处理。