【发布时间】:2018-05-07 06:27:53
【问题描述】:
我正在查看 MSAL,并试图了解在客户端应用程序中使用它的正确方法是什么。就我而言,我想对用户进行身份验证,然后将 id 令牌用于“私有”Web api 应用程序。
现在,我的印象是 AcquireTokenSilentAsync 将重用缓存中的现有令牌(如果可用),如果令牌仍然有效并且可以满足请求范围(这是我的解释,它可能是错误的)。然而,情况似乎并非如此。我在提琴手上看到的是这种方法将始终访问授权端点。
最初,我认为我的客户端服务包装器应始终调用此方法以获取 id 令牌,然后通过身份验证承载标头将其传递到后端网站。这是我的意思的一个例子:
public async Task<string> GetAllWorkers() {
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await GetToken());
var request = new HttpRequestMessage(HttpMethod.Get, _url);
var resposta = await _httpClient.SendAsync(request);
var content = await resposta.Content.ReadAsStringAsync();
return content;
}
GetToken 是一种包装用于验证用户身份的典型代码的方法(使用 try/catch 块包装 AcquireTokenSilentAsync 并在失败时将用户重定向到 AcquireTokenAsync 方法以显示登录 UI)。
问题:在我的所有后端服务之前进行这个额外的调用真的可行吗?或者我应该缓存令牌并在所有内部 Web 服务调用中重用它,直到我得到 401(然后才应该调用 GetToken 方法来刷新我的 id 令牌?)
编辑以提供更多信息
_clientApp = new PublicClientApplication(ClientId,
Authority,
TokenCacheHelper.GetUserCache());
TokenCacheHelper 是大多数 Azure AD 示例附带的令牌缓存帮助程序。返回身份验证标头的GetToken 方法是与封装了上面显示的 _clientApp 字段的助手交互的单个衬里:
return (await _helper.AuthenticateUser()).IdToken
这里是 AuthenticateUser 方法:
public async Task<AuthenticationResult> AuthenticateUser() {
try {
return await _clientApp.AcquireTokenSilentAsync(_scopes, _clientApp.Users.FirstOrDefault());
}
catch (MsalUiRequiredException ex) {
return await RetryWithGraphicalUI();
}
}
现在,令牌缓存助手正在被命中。我不明白的是为什么 AcquireTokenSilentAsync 方法最终总是调用 oauth2 端点 (https://login.microsoftonline.com/{azure ad guid}/oauth2/v2.0/token)...
同时,我更改了代码,使我的助手类缓存 AuthenticationResult。现在,AcquireTokenSilentAsync 只会在“内部”应用的 Web api 方法之一返回 401 以响应使用不记名授权标头执行的调用时调用。
【问题讨论】:
-
你能告诉我们更多关于你初始化应用程序的权限吗?我们想了解为什么没有命中缓存。
-
你好让-马克。缓存被命中是因为 UI 未显示,但acquiretokensilentasync 将始终调用授权端点来获取令牌。要我显示更多代码吗?
-
只是 PublicClientApplication 的构造函数(我假设这是一个公共客户端应用程序)。你到达共同的终点了吗?您使用的身份是 MSA(Microsoft 个人帐户)吗?还是 AAD 的?
-
我已尝试添加有关此问题的更多信息...
-
@LuisAbreu 您是否尝试过将令牌缓存序列化到会话或内存中,例如参见github.com/Azure-Samples/…
标签: authentication asp.net-web-api azure-active-directory msal