gpt4 book ai didi

oauth-2.0 - MSAL.NET OBO 刷新 token 问题

转载 作者:行者123 更新时间:2023-12-05 03:29:09 35 4
gpt4 key购买 nike

我正在尝试使用 MSAL.NET 在中间层 API (.NET 5.0) 上实现一个 OBO 流到图形 API。我遇到了两个令人沮丧的问题,而且我找不到任何人有类似的问题,所以我想我误会了什么!

问题 1:每当我调用 MSAL 的 GetAccountAsync 时,它总是在应该加载帐户时返回 null。

问题 2:每当我调用 MSAL 的 AcquireTokenSilent 时,我总是收到错误“在缓存中找不到刷新 token ”。尽管我有一个。

这是我所拥有的:

一旦 Web 应用通过身份验证,它就会通过 token 传递到 API 上的图形身份验证端点:

            var authenticationResult = await ClaimHelper.ClientApplication.AcquireTokenByAuthorizationCode(GraphHelpers.BasicGraphScopes, context.Code).ExecuteAsync();

var apiUserSession = await CouncilWiseAPIHelper.APIClient.Graph.AuthoriseUserAsync(authenticationResult.AccessToken);

这似乎工作正常,并通过 JWT 传递到 API 身份验证端点。该 API 实现 MSAL secret 客户端应用程序并使用 SetBeforeAccess/SetAfterAccess token 缓存方法将缓存保存到数据库。

         _msalClient = ConfidentialClientApplicationBuilder.Create(_graphConfig.ClientId)
.WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
.WithClientSecret(_graphConfig.ClientSecret)
.Build();

SetSerialiser(serialiser);
        public void SetSerialiser(MSALTokenCacheSerialiser serialiser)
{
_msalClient.UserTokenCache.SetBeforeAccessAsync(serialiser.BeforeAccessCallbackAsync);
_msalClient.UserTokenCache.SetAfterAccessAsync(serialiser.AfterAccessCallbackAsync);
}

序列化器方法如下所示:

public async Task BeforeAccessCallbackAsync(TokenCacheNotificationArgs notification)
{
GraphUserTokenCache tokenCache = await _graphUserTokenCacheRepository.GetByUserIdentifier(notification.SuggestedCacheKey);
if (tokenCache == null)
{
tokenCache = await _graphUserTokenCacheRepository.Get(notification.SuggestedCacheKey);
}

if (tokenCache != null)
{
notification.TokenCache.DeserializeMsalV3(tokenCache.Value);
}
}

public async Task AfterAccessCallbackAsync(TokenCacheNotificationArgs notification)
{
if (!notification.HasTokens)
{
// Delete from the cache
await _graphUserTokenCacheRepository.Delete(notification.SuggestedCacheKey);
}

if (!notification.HasStateChanged)
{
return;
}
GraphUserTokenCache tokenCache;
if (notification.SuggestedCacheKey == notification.Account.HomeAccountId.Identifier)
{
tokenCache = await _graphUserTokenCacheRepository.GetByUserIdentifier(notification.SuggestedCacheKey);
}
else
{
tokenCache = await _graphUserTokenCacheRepository.Get(notification.SuggestedCacheKey);
}
if (tokenCache == null)
{
var cache = notification.TokenCache.SerializeMsalV3();
tokenCache = new GraphUserTokenCache
{
Id = notification.SuggestedCacheKey,
AccountIdentifier = notification.Account.HomeAccountId.ToString(),
Value = cache
};

await _graphUserTokenCacheRepository.Add(tokenCache);
}
else
{
await _graphUserTokenCacheRepository.Update(tokenCache.Id, notification.TokenCache.SerializeMsalV3());
}
}

我可以看到正在调用 token BeforeAccess 和 AfterAccess 方法,并且我可以看到正在数据库中创建缓存(在我试图追踪此问题时加密已被删除)。如果我检查正在保存的序列化 token 缓存,它永远不会填充刷新 token ,但如果我使用 fiddler 检查请求,我可以看到确实提供了刷新 token 。最后,这是用于检索访问 token 的代码,无论何时发出图形请求都会调用该代码:

public async Task<AuthenticationResult> GetAccessToken(string accountId, string jwtBearerToken)
{
try
{
IAccount account = null;
if (accountId.IsNotNullOrEmpty())
{
account = await _msalClient.GetAccountAsync(accountId);
}

var scope = _graphConfig.Scopes.Split(' ');

if (account == null)
{
var result = await _msalClient.AcquireTokenOnBehalfOf(scope,
new UserAssertion(jwtBearerToken))
.ExecuteAsync();

return result;
}
else
{
var result = await _msalClient.AcquireTokenSilent(scope, account)
.ExecuteAsync();

return result;
}
}
catch (MsalClientException ex)
{
ex.CwApiLog();
return null;
}
catch(Exception ex)
{
ex.CwApiLog();
return null;
}
}

当使用 jwtBearerToken 调用时,它将成功调用 AcquireTokenOnBehalfOf() 并缓存 token 并返回结果,但是当我返回通过 GetAccountAsync() 检索帐户时 它始终返回 null,即使我可以看到 token 缓存已加载到 BeforeAccessCallbackAsync() 中。

此外,即使我在使用刚刚返回的帐户获取 obo token 后立即调用 AcquireTokenSilent(),我也会收到一个异常,提示缓存中没有刷新 token 。

我完全不知道我在这里做错了什么,非常感谢任何帮助。

最佳答案

我最近在运行长时间运行的 OBO 流时遇到了同样的问题,MSAL 最近为这些用例实现了一个接口(interface) ILongRunningWebApi 你可以去看看这个 new documentation

摘录如下:

One OBO scenario is when a web API runs long running processes onbehalf of the user (for example, OneDrive which creates albums foryou). Starting with MSAL.NET 4.38.0, this can be implemented as such:

Before you start a long running process, call:

string sessionKey = // custom key or null
var authResult = await ((ILongRunningWebApi)confidentialClientApp)
.InitiateLongRunningProcessInWebApi(
scopes,
userToken,
ref sessionKey)
.ExecuteAsync();

userToken is a user token used to call this web API. sessionKey willbe used as a key when caching and retrieving the OBO token. If set tonull, MSAL will set it to the assertion hash of the passed-in usertoken. It can also be set by the developer to something thatidentifies a specific user session, like the optional sid claim fromthe user token (for more information, see Provide optional claims toyour app). If the cache already contains a valid OBO token with thissessionKey, InitiateLongRunningProcessInWebApi will return it.Otherwise, the user token will be used to acquire a new OBO token fromAAD, which will then be cached and returned.

In the long-running process, whenever OBO token is needed, call:

var authResult = await ((ILongRunningWebApi)confidentialClientApp)
.AcquireTokenInLongRunningProcess(
scopes,
sessionKey)
.ExecuteAsync();

Pass the sessionKey which is associated with the current user'ssession and will be used to retrieve the related OBO token. If thetoken is expired, MSAL will use the cached refresh token to acquire anew OBO access token from AAD and cache it. If no token is found withthis sessionKey, MSAL will throw a MsalClientException. Make sure tocall InitiateLongRunningProcessInWebApi first.

希望这有帮助:)

关于oauth-2.0 - MSAL.NET OBO 刷新 token 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71058699/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com