我使用MSAL获取ID令牌,然后用于访问Web API应用。我有几个问题,我想知道是否有人可以帮我理解发生了什么。
让我先从客户端的身份验证过程开始。在这种情况下,我正在构建一个使用以下代码的Windows窗体应用程序,以便对当前用户进行身份验证(即,为了获取将在用户尝试访问时用于验证用户的ID令牌一个Web API应用程序):
//constructor code
_clientApp = new PublicClientApplication(ClientId,
Authority, //which url here?
TokenCacheHelper.GetUserCache());
_scopes = new []{ "user.read" }; //what to put here?
//inside a helper method
try {
return await _clientApp.AcquireTokenSilentAsync(_scopes, _clientApp.Users.FirstOrDefault());
}
catch (MsalUiRequiredException ex) {
try {
return await _clientApp.AcquireTokenAsync(_scopes);
}
catch (MsalException ex) {
return null;
}
}
我想要清除的第一件事是应该用于权限参数的值。在这种情况下,我使用表单上的URL:
https://login.microsoftonline.com/{Tenant}/oauth2/v2.0/token
然而,我的印象是我还可以逃避这样的事情:
https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
似乎一个端点特定于我的Azure AD,而另一个端点看起来像一般(全部捕获)URL ...我在哪里可以找到有关这些端点的更多信息以及每个端点的用途。 ..
我无法理解的另一件事是范围。我对查询MS Graph(或任何其他Azure相关服务)不感兴趣。在以前版本的MSAL库中,可以引用其中一个默认范围。但是,这似乎已经不再可能了(至少,我试过并且有一个例外,说我不应该通过默认范围......)。
传递空集合(例如:new List<string>()
)或null
也会导致错误。所以,在这种情况下,我已经结束了user.read
范围的传递(如果我没有弄错的话,MS Graph API会使用它。这显然不是必需的,但这是唯一的方法我设法让身份验证过程正常工作。当你需要获取ID令牌时,有关如何执行调用的任何线索吗?我应该调用不同的方法吗?
转到服务器端,我有一个Web API应用程序,其访问权限仅限于在身份验证标头(bearer)中传递ID令牌的调用。根据这个sample,我应该使用这样的东西:
private void ConfigureAuth(IAppBuilder app) {
var authority = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
app.UseOAuthBearerAuthentication(
new OAuthBearerAuthenticationOptions {
AccessTokenFormat = new JwtFormat(GetTokenValidationParameters(),
new OpenIdConnectCachingSecurityTokenProvider(authority)),
Provider = new OAuthBearerAuthenticationProvider {
OnValidateIdentity = ValidateIdentity
}
});
}
现在,这确实有效,并且对于没有有效ID令牌的所有请求,它将返回401。但有一个问题:有没有办法从Ticket的标识中指定应该用于识别用户名(控制器的User.Identity.Name
)的声明?在这种情况下,我已经结束了对OnValidateIdentity
的处理,以便使用如下代码执行此操作:
private Task ValidateIdentity(OAuthValidateIdentityContext arg) {
//username not getting correctly filled
//so, i'm handling this event in order to set it up
//from the preferred_username claim
if (!arg.HasError && arg.IsValidated) {
var identity = arg.Ticket.Identity;
var username = identity.Claims.FirstOrDefault(c => c.Type == "preferred_username")?.Value ?? "";
if (!string.IsNullOrEmpty(username)) {
identity.AddClaim(new Claim(ClaimTypes.Name, username));
}
}
return Task.CompletedTask;
}
如您所见,我正在从ID令牌(由客户端获取)中搜索preferred_username声明并使用其值来设置Name声明。有没有让我自动执行此操作的选项?我在OAuthBearerAuthenticationMiddleware
答案 0 :(得分:1)
关于第一次查询 - 我在哪里可以找到有关这些端点的更多信息以及每个端点的用途...
回答 - https://login.microsoftonline.com/的 {租户} 强> /v2.0/.well-known/openid-configuration
{租户} 可以采用以下四种值之一:
常见 - 拥有个人Microsoft帐户和Azure Active Directory(Azure AD)中的工作或学校帐户的用户可以登录该应用程序。
组织 - 只有拥有Azure AD中的工作或学校帐户的用户才能登录该应用程序。
消费者 - 只有拥有个人Microsoft帐户的用户才能登录该应用程序。
8eaef023-2b34-4da1-9baa-8bc8c9d6a490 或 contoso.onmicrosoft.com - 只有具有特定Azure AD租户的工作或学校帐户的用户才能登录该应用程序。可以使用Azure AD租户的友好域名或租户的GUID标识符。
关于范围的第二次查询 -
回答 - 请参阅此文档 - OpenID Connect scopes
关于声明的第三次查询 -
回答 - 请参阅此GIT Hub示例 - active-directory-dotnet-webapp-roleclaims