MSAL和Azure AD:当我想获取用户ID时,我应该通过哪些范围?

时间:2017-11-11 16:18:44

标签: oauth-2.0 azure-active-directory bearer-token msal

我使用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

的配置中遗漏了什么

1 个答案:

答案 0 :(得分:1)

关于第一次查询 - 我在哪里可以找到有关这些端点的更多信息以及每个端点的用途...

回答 - https://login.microsoftonline.com/ {租户} /v2.0/.well-known/openid-configuration

{租户} 可以采用以下四种值之一:

  1. 常见 - 拥有个人Microsoft帐户和Azure Active Directory(Azure AD)中的工作或学校帐户的用户可以登录该应用程序。

  2. 组织 - 只有拥有Azure AD中的工作或学校帐户的用户才能登录该应用程序。

  3. 消费者 - 只有拥有个人Microsoft帐户的用户才能登录该应用程序。

  4. 8eaef023-2b34-4da1-9baa-8bc8c9d6a490 contoso.onmicrosoft.com - 只有具有特定Azure AD租户的工作或学校帐户的用户才能登录该应用程序。可以使用Azure AD租户的友好域名或租户的GUID标识符。

  5. 关于范围第二次查询 -

    回答 - 请参阅此文档 - OpenID Connect scopes

    关于声明第三次查询 -

    回答 - 请参阅此GIT Hub示例 - active-directory-dotnet-webapp-roleclaims