从身份验证上下文收到的令牌不起作用
Token received from authentication context not working
我正在设置多租户应用程序,但在创建 GraphServiceClient 时遇到问题。
我必须遵循 AuthorizationCodeReceived:
AuthorizationCodeReceived = async context =>
{
var tenantId =
context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/"+ tenantId);
await authenticationContext.AcquireTokenByAuthorizationCodeAsync(
context.Code,
new Uri("http://localhost:21925"),
new ClientCredential(ClientId, ClientSecret),
"https://graph.microsoft.com");
}
这非常适合对用户进行身份验证。我正在使用 fiddler,我看到 login.microsoftonline.com/{tenantid}/oauth2/token
给出了一个新的承载令牌
在创建新的图形服务客户端时,我使用了以下工厂方法:
public IGraphServiceClient CreateGraphServiceClient()
{
var client = new GraphServiceClient(
new DelegateAuthenticationProvider(
async requestMessage =>
{
string token;
var currentUserId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var currentUserHomeTenantId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/" + currentUserHomeTenantId + "/");
var clientCredential = new ClientCredential(_configuration.ClientId, _configuration.ClientSecret);
try
{
var authenticationResult = await authenticationContext.AcquireTokenSilentAsync(
GraphResourceId,
clientCredential,
new UserIdentifier(currentUserId, UserIdentifierType.UniqueId));
token = authenticationResult.AccessToken;
}
catch (AdalSilentTokenAcquisitionException e)
{
var result = await authenticationContext.AcquireTokenAsync(GraphResourceId, clientCredential);
token = result.AccessToken;
}
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
}));
return client;
}
此方法始终抛出 AdalSilentAcquisitionException 并且 AcquireTokenAsync 检索新令牌。
使用此令牌,我无法在图表上请求 'Me'。
我收到以下异常:消息=资源 'some guid' 不存在或其查询的 reference-property objects 之一不存在。
但是,如果我正在调试并且我在将令牌传递给 header 之前更改了令牌,其值为我之前在登录后立即获得的值(从 login.microsoftonline.com/ 收到{tenantid}/oauth2/token ) 然后 API 呼叫工作。
有谁知道我做错了什么?他能让获取令牌默默地工作吗?
更新: 我已经更新了代码示例。我已经删除了自定义缓存,现在一切似乎都正常了。
如何根据 http 会话创建自定义缓存,确保 AcquireTokenSilently 正常工作。
不工作的令牌缓存预览:
public class WebTokenCache : TokenCache
{
private readonly HttpContext _httpContext;
private readonly string _cacheKey;
public WebTokenCache()
{
_httpContext = HttpContext.Current;
var claimsPrincipal = (ClaimsPrincipal) HttpContext.Current.User;
_cacheKey = BuildCacheKey(claimsPrincipal);
AfterAccess = AfterAccessNotification;
LoadFromCache();
}
private string BuildCacheKey(ClaimsPrincipal claimsPrincipal)
{
var clientId = claimsPrincipal.FindFirst("aud").Value;
return $"{claimsPrincipal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value}_TokenCache";
}
private void LoadFromCache()
{
var token = _httpContext.Cache[_cacheKey];
if (token == null) return;
Deserialize((byte[]) token);
}
private void AfterAccessNotification(TokenCacheNotificationArgs args)
{
if (!HasStateChanged) return;
if (Count > 0)
{
_httpContext.Cache[_cacheKey] = Serialize();
}
else
{
_httpContext.Cache.Remove(_cacheKey);
}
HasStateChanged = false;
}
}
我正在尝试使用上面的代码,它对我来说效果很好。
请确保 GraphResourceId
是 https://graph.microsoft.com
(在您的启动 class 中首次请求此资源)因为方法 AcquireTokenSilentAsync
将尝试检索令牌基于资源的缓存。
我正在设置多租户应用程序,但在创建 GraphServiceClient 时遇到问题。
我必须遵循 AuthorizationCodeReceived:
AuthorizationCodeReceived = async context =>
{
var tenantId =
context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/"+ tenantId);
await authenticationContext.AcquireTokenByAuthorizationCodeAsync(
context.Code,
new Uri("http://localhost:21925"),
new ClientCredential(ClientId, ClientSecret),
"https://graph.microsoft.com");
}
这非常适合对用户进行身份验证。我正在使用 fiddler,我看到 login.microsoftonline.com/{tenantid}/oauth2/token
给出了一个新的承载令牌在创建新的图形服务客户端时,我使用了以下工厂方法:
public IGraphServiceClient CreateGraphServiceClient()
{
var client = new GraphServiceClient(
new DelegateAuthenticationProvider(
async requestMessage =>
{
string token;
var currentUserId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var currentUserHomeTenantId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/" + currentUserHomeTenantId + "/");
var clientCredential = new ClientCredential(_configuration.ClientId, _configuration.ClientSecret);
try
{
var authenticationResult = await authenticationContext.AcquireTokenSilentAsync(
GraphResourceId,
clientCredential,
new UserIdentifier(currentUserId, UserIdentifierType.UniqueId));
token = authenticationResult.AccessToken;
}
catch (AdalSilentTokenAcquisitionException e)
{
var result = await authenticationContext.AcquireTokenAsync(GraphResourceId, clientCredential);
token = result.AccessToken;
}
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
}));
return client;
}
此方法始终抛出 AdalSilentAcquisitionException 并且 AcquireTokenAsync 检索新令牌。
使用此令牌,我无法在图表上请求 'Me'。 我收到以下异常:消息=资源 'some guid' 不存在或其查询的 reference-property objects 之一不存在。
但是,如果我正在调试并且我在将令牌传递给 header 之前更改了令牌,其值为我之前在登录后立即获得的值(从 login.microsoftonline.com/ 收到{tenantid}/oauth2/token ) 然后 API 呼叫工作。
有谁知道我做错了什么?他能让获取令牌默默地工作吗?
更新: 我已经更新了代码示例。我已经删除了自定义缓存,现在一切似乎都正常了。
如何根据 http 会话创建自定义缓存,确保 AcquireTokenSilently 正常工作。
不工作的令牌缓存预览:
public class WebTokenCache : TokenCache
{
private readonly HttpContext _httpContext;
private readonly string _cacheKey;
public WebTokenCache()
{
_httpContext = HttpContext.Current;
var claimsPrincipal = (ClaimsPrincipal) HttpContext.Current.User;
_cacheKey = BuildCacheKey(claimsPrincipal);
AfterAccess = AfterAccessNotification;
LoadFromCache();
}
private string BuildCacheKey(ClaimsPrincipal claimsPrincipal)
{
var clientId = claimsPrincipal.FindFirst("aud").Value;
return $"{claimsPrincipal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value}_TokenCache";
}
private void LoadFromCache()
{
var token = _httpContext.Cache[_cacheKey];
if (token == null) return;
Deserialize((byte[]) token);
}
private void AfterAccessNotification(TokenCacheNotificationArgs args)
{
if (!HasStateChanged) return;
if (Count > 0)
{
_httpContext.Cache[_cacheKey] = Serialize();
}
else
{
_httpContext.Cache.Remove(_cacheKey);
}
HasStateChanged = false;
}
}
我正在尝试使用上面的代码,它对我来说效果很好。
请确保 GraphResourceId
是 https://graph.microsoft.com
(在您的启动 class 中首次请求此资源)因为方法 AcquireTokenSilentAsync
将尝试检索令牌基于资源的缓存。