[英]ADAL - AcquireTokenSilentAsync fails (Azure Active Directory Authentication Libraries)
I write a new application to access office data through the rest API, therefore i would like to use the new Authentication Model (V2.0 Endpoint) 我编写了一个新的应用程序来通过其余的API访问办公室数据,因此我想使用新的身份验证模型(V2.0端点)
What's different about the v2.0 endpoit v2.0 endpoit有什么不同
I can get a token with a call to 我可以通过电话获得令牌
private static string[] scopes = { "https://outlook.office.com/mail.read", "https://outlook.office.com/calendars.read" };
public async Task<ActionResult> SignIn()
{
... SNIP
Uri authUri = await authContext.GetAuthorizationRequestUrlAsync(scopes, null, clientId, redirectUri, new UserIdentifier("contoso@foo", UserIdentifierType.RequiredDisplayableId), null);
return Redirect(authUri.ToString());
}
authContext.AcquireTokenByAuthorizationCodeAsync(authCode, redirectUri, credential, scopes)
The Problem is the second call to 问题是第二次调用
public async Task<ActionResult> SignIn()
{
... SNIP
var authResult = authContext.AcquireTokenSilentAsync(scopes, clientId, new UserIdentifier("contoso@foo.ch", UserIdentifierType.RequiredDisplayableId))
}
The Returned token does contain the UniqueId, but this information is not stored in the Token object. 返回令牌确实包含UniqueId,但此信息不存储在令牌对象中。 The UserInfo of the Token is always null.
令牌的UserInfo始终为null。 Because this field is null, the Token cache cannot find the token.
由于此字段为空,因此令牌缓存无法找到令牌。
Thank you for your Hints and Ideas 感谢您的提示和想法
Returned Token 返回令牌
{
"aud":"https://outlook.office.com",
"iss":"https://sts.windows.net/f2ac6f3f-3df0-4068-a677-e4dfdf924b2/",
"iat":146 dfdf21,
"nbf":146 dfdf4621,
"exp":1463 dfdf38521,
"acr":"1",
"amr":[
"pwd"
],
"appid":"b13dfdf9-0561-4dfdff5-945c-778dfdf0de5cd",
"appidacr":"1",
"family_name":"Pan",
"given_name":"Peter",
"ipaddr":"12.12.12.17",
"name":"Peter Pan",
"oid":"4b83dfdfdb-f6db-433e-b70a-2f9a6dbbeb48",
"puid":"100dfdfdfF5FBC",
"scp":"Calendars.Read Mail.Read Mail.ReadWrite",
"sub":"Z-chdfdsfnWqduUkCGZpsIdp-fdhpMMqqtwcHGs",
"tid":"f2ac6f3f-3560-4068-a677-e4bfe0c924b2",
"unique_name":"foo@contoso",
"upn":"foo@contoso",
"ver":"1.0"
}
Microsoft has removed the profile_info as you can read here: Important Updates to ADV2 Microsoft已删除了profile_info,您可以在此处阅读: ADV2的重要更新
At the moment the library has a bug, because it still check it, and if it's null, it won't return the userinformations. 目前库有一个bug,因为它仍然检查它,如果它是null,它将不会返回用户信息。
The correct informations are in token_id... 正确的信息在token_id中......
Class: TokenResponse 类:TokenResponse
private AuthenticationResultEx GetResult(string token, string scope, long expiresIn)
{
DateTimeOffset expiresOn = (DateTimeOffset) (DateTime.UtcNow + TimeSpan.FromSeconds((double) expiresIn));
AuthenticationResult authenticationResult = new AuthenticationResult(this.TokenType, token, expiresOn);
ProfileInfo profileInfo = ProfileInfo.Parse(this.ProfileInfoString);
if (profileInfo != null)
{
string tenantId = profileInfo.TenantId;
string str1 = (string) null;
string str2 = (string) null;
if (!string.IsNullOrWhiteSpace(profileInfo.Subject))
str1 = profileInfo.Subject;
if (!string.IsNullOrWhiteSpace(profileInfo.PreferredUsername))
str2 = profileInfo.PreferredUsername;
authenticationResult.UpdateTenantAndUserInfo(tenantId, this.ProfileInfoString, new UserInfo()
{
UniqueId = str1,
DisplayableId = str2,
Name = profileInfo.Name,
Version = profileInfo.Version
});
}
return new AuthenticationResultEx()
{
Result = authenticationResult,
RefreshToken = this.RefreshToken,
ScopeInResponse = AdalStringHelper.CreateArrayFromSingleString(scope)
};
}
I hope they will fix it soon, I'm also waiting :-) 我希望他们能尽快解决,我也在等待:-)
Edit: 编辑:
I found something interesting here: Dev Outlook get started 我发现了一些有趣的东西: Dev Outlook开始了
As I already said, all informations stored in token_id, in the link above you can read: 正如我已经说过的,存储在token_id中的所有信息,在上面的链接中你可以读到:
The prerelease version of ADAL v4 doesn't return the ID token directly, but it is accessible.
ADAL v4的预发布版本不会直接返回ID令牌,但可以访问它。 The method included here is intended to work around this issue until ADAL is updated.
此处包含的方法旨在解决此问题,直到更新ADAL。
They explain a way to access the Token: 他们解释了访问令牌的方法:
private string GetUserEmail(AuthenticationContext context, string clientId)
{
// ADAL caches the ID token in its token cache by the client ID
foreach (TokenCacheItem item in context.TokenCache.ReadItems())
{
if (item.Scope.Contains(clientId))
{
return GetEmailFromIdToken(item.Token);
}
}
return string.Empty;
}
private string GetEmailFromIdToken(string token)
{
// JWT is made of three parts, separated by a '.'
// First part is the header
// Second part is the token
// Third part is the signature
string[] tokenParts = token.Split('.');
if (tokenParts.Length < 3)
{
// Invalid token, return empty
}
// Token content is in the second part, in urlsafe base64
string encodedToken = tokenParts[1];
// Convert from urlsafe and add padding if needed
int leftovers = encodedToken.Length % 4;
if (leftovers == 2)
{
encodedToken += "==";
}
else if (leftovers == 3)
{
encodedToken += "=";
}
encodedToken = encodedToken.Replace('-', '+').Replace('_', '/');
// Decode the string
var base64EncodedBytes = System.Convert.FromBase64String(encodedToken);
string decodedToken = System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
// Load the decoded JSON into a dynamic object
dynamic jwt = Newtonsoft.Json.JsonConvert.DeserializeObject(decodedToken);
// User's email is in the preferred_username field
return jwt.preferred_username;
}
I don't tested this yet, but I will update this post when I have tested it, or another one will please make a comment, if he's faster :-) 我还没有对此进行测试,但是当我测试它时我会更新这篇文章,或者如果他的速度更快,我会另外发表评论:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.