我正在设置一个多租户应用程序,并且在创建GraphServiceClient时遇到问题。
我必须遵循authorizationcoderreceived:
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;
}
这个方法总是抛出一个adalsilentacquiretokenasync获取一个新的令牌。
使用此令牌,我无法请求图上的"我"。我得到以下异常:message=资源'some guid'不存在,或者它查询的引用属性对象之一不存在。
但是,如果我正在调试,并且在将令牌传递给标头之前更改令牌,在登录后(从login.microsoftonline.com/{tenantid}/oauth2/token收到)之前获得的值,则API调用工作。
有人知道我做错了什么吗?我能让被收购的代币默默地工作吗?
Update:我已经更新了代码示例。我已经删除了自定义缓存,现在一切似乎都工作。
如何根据http会话制作自定义缓存,确保acquiretokensilent工作
令牌缓存不工作预览:
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
(此资源是在您的startUp类中第一次请求的),因为方法AcquireTokenSilentAsync
将尝试根据资源从缓存中检索令牌。