2016-05-13 56 views
3

我写了一个新的应用程序访问办公室数据通过REST API,所以我想用新的 认证模型(V2.0端点)ADAL - AcquireTokenSilentAsync失败(Azure的Active Directory验证库)

What's different about the v2.0 endpoit

我可以得到令牌通过调用

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("[email protected]", UserIdentifierType.RequiredDisplayableId), null);   
     return Redirect(authUri.ToString()); 
    } 
authContext.AcquireTokenByAuthorizationCodeAsync(authCode, redirectUri, credential, scopes) 

问题是

第二个电话3210
public async Task<ActionResult> SignIn() 
    { 
    ... SNIP 
    var authResult = authContext.AcquireTokenSilentAsync(scopes, clientId, new UserIdentifier("[email protected]", UserIdentifierType.RequiredDisplayableId)) 
    } 

返回的标记包含UniqueId,但该信息未存储在令牌对象中。令牌的UserInfo始终为空。由于此字段为空,令牌缓存无法找到该令牌。

谢谢你的提示和想法

enter image description here

返回的标记

{ 
    "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":"[email protected]", 
    "upn":"[email protected]", 
    "ver":"1.0" 
} 

类似的问题: Here

回答

3

微软已经删除了profile_info,你可以在这里阅读: Important Updates to ADV2

目前该库有一个错误,因为它仍然检查它,如果它为空,它将不会返回用户信息。

正确的信息在token_id ...

类: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) 
    }; 
} 

我希望他们尽快修复它,我还等着:-)

编辑:

我在这里发现了一些有趣的东西: Dev Outlook get started

正如我已经说过,存储在token_id所有信息,在上面的链接,你可以阅读:

ADAL V4的预发布版本不令牌直接返回的ID,但它是可访问。此处包含的方法旨在解决此问题,直到更新ADAL。

他们解释的方式来访问令牌:

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; 
} 

我没有测试过,但是我会更新这个帖子的时候我已经测试过它,或者其他人会请一个评论,如果他的速度更快:-)

+1

目前,我已经使用此解决方法,但是这种方式不能使用内置于ADAL库的令牌缓存 –

相关问题