C# ADAL-AcquireTokenSilentAsync失败(Azure Active Directory身份验证库)
我编写了一个新的应用程序,通过RESTAPI访问office数据,因此我想使用新的 身份验证模型(V2.0端点) 我可以通过打电话到C# ADAL-AcquireTokenSilentAsync失败(Azure Active Directory身份验证库),c#,azure,oauth-2.0,office365,adal,C#,Azure,Oauth 2.0,Office365,Adal,我编写了一个新的应用程序,通过RESTAPI访问office数据,因此我想使用新的 身份验证模型(V2.0端点) 我可以通过打电话到 private static string[] scopes = { "https://outlook.office.com/mail.read", "https://outlook.office.com/calendars.read" }; public async Task<ActionResult> SignIn() {
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)
类似问题:
Microsoft已删除配置文件信息,您可以在此处阅读: 目前库有一个bug,因为它仍然检查它,如果为null,它将不会返回用户信息 正确的信息在令牌\u id中 Class: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)
};
}
我希望他们能尽快修复,我也在等待:-)
编辑:
我在这里发现了一些有趣的东西:
正如我已经说过的,所有存储在token_id中的信息,在上面的链接中,您可以阅读:
ADALV4的预发布版本不直接返回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;
}
private string GetUserEmail(AuthenticationContext,string clientId)
{
//ADAL通过客户端ID在其令牌缓存中缓存ID令牌
foreach(context.TokenCache.ReadItems()中的TokenCacheItem项)
{
if(item.Scope.Contains(clientId))
{
返回GetEmailFromIdToken(item.Token);
}
}
返回字符串。空;
}
私有字符串GetEmailFromIdToken(字符串标记)
{
//JWT由三部分组成,由“.”分隔
//第一部分是标题
//第二部分是代币
//第三部分是签名
字符串[]tokenParts=token.Split('.');
如果(长度<3)
{
//无效令牌,返回空
}
//令牌内容在urlsafe base64的第二部分中
字符串encodedToken=tokenParts[1];
//从urlsafe转换并在需要时添加填充
int leftovers=encodedToken.Length%4;
如果(剩余=2)
{
encodedToken+=“=”;
}
else if(剩余=3)
{
encodedToken+=“=”;
}
encodedToken=encodedToken.Replace('-','+').Replace('''.'和'/');
//解码字符串
var base64EncodedBytes=System.Convert.FromBase64String(encodedToken);
string decodedToken=System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
//将解码后的JSON加载到动态对象中
动态jwt=Newtonsoft.Json.JsonConvert.DeserializeObject(decodedToken);
//用户的电子邮件位于首选用户名字段中
返回jwt.preferred\u用户名;
}
我还没有对此进行测试,但我会在测试后更新此帖子,或者另一个帖子会发表评论,如果他更快的话:-)目前,我已经使用了此解决方案,但这样无法使用ADAL库的内置令牌缓存
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)
};
}
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;
}