【问题标题】:Microsoft Graph API userInfo endpoint UnknownError: Token must contain sub claimMicrosoft Graph API userInfo 端点 UnknownError:令牌必须包含子声明
【发布时间】:2021-05-24 11:37:15
【问题描述】:

我正在尝试使用通过 Open ID Connect 接收到的访问令牌在 https://graph.microsoft.com/oidc/userinfo 处执行 userinfo 端点。

收到的响应是:

400 错误请求

{
    "error": {
        "code": "UnknownError",
        "message": "Token must contain sub claim.",
        "innerError": {
            "date": "2021-02-22T07:14:37",
            "request-id": "650a2928-b0e7-49ae-9e6d-ecb569ee69e6",
            "client-request-id": "650a2928-b0e7-49ae-9e6d-ecb569ee69e6"
        }
    }
}

访问令牌有效并且确实包含子声明。

如果我登录到https://developer.microsoft.com/en-us/graph/graph-explorer,并使用它自动检索的访问令牌,它就可以工作——对于同一个用户。子声明是不同的,但有两个。

似乎来自 OIDC 的令牌没有正确的子声明 - 这怎么可能?

直接从 /authorize 端点 [WORKING] 访问令牌:

来自 OIDC 的访问令牌 [不工作]:

OIDC 配置:
options.Authority = authority;
options.ClientId = Configuration[ConfigKeys.IdentityProvider.ClientID];
options.ClientSecret = Configuration[ConfigKeys.IdentityProvider.ClientSecret];

options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.CallbackPath = Configuration[ConfigKeys.IdentityProvider.CallbackPath];
options.SignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;

options.CorrelationCookie.Expiration
    = options.NonceCookie.Expiration
    = options.ProtocolValidator.NonceLifetime
    = options.RemoteAuthenticationTimeout
    = TimeSpan.FromHours(8);

options.Resource = "https://graph.microsoft.com";
options.GetClaimsFromUserInfoEndpoint = false;
options.UseTokenLifetime = true;
options.RequireHttpsMetadata = true;
options.SaveTokens = true;

options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("offline_access");
options.Scope.Add("groups");

options.RemoteAuthenticationTimeout = TimeSpan.FromHours(10);
options.TokenValidationParameters = new TokenValidationParameters
{
    ValidateIssuer = true,
    ValidIssuer = authority,
    //NameClaimType = "name"
};

【问题讨论】:

  • 你解析token来查看了吗?
  • 是 - jwt.io

标签: .net-core azure-active-directory microsoft-graph-api openid-connect


【解决方案1】:

访问令牌有效并且确实包含子声明。

我想你没有正确获取令牌,请按照以下步骤操作。

1.Register an application with Azure AD

2.在AD App的API permissions,在Microsoft Graph中添加如下权限

3.在Authentication中,选择以下选项。

4.在浏览器中点击下面的网址,替换你的<tenant-id><client-id>,登录你的用户账户,你会得到一个access_token和一个id_token

https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize?client_id=<client-id>&response_type=token+id_token&redirect_uri=http://localhost&scope=user.read+openid+profile+email&response_mode=fragment&state=12345&nonce=678910

5.使用access_token调用https://graph.microsoft.com/oidc/userinfo端点,效果很好,在我的示例中sub的值为EY4uO7uc1IG2n8EboEalB4LDxJ1NU8nuc2JXZgkisN4

6.解码https://jwt.io/中第4步得到的id_tokensub也是EY4uO7uc1IG2n8EboEalB4LDxJ1NU8nuc2JXZgkisN4,也就是说从https://graph.microsoft.com/oidc/userinfo端点得到的sub是正确的。

如果我登录到https://developer.microsoft.com/en-us/graph/graph-explorer,并使用它自动检索的访问令牌,它就可以工作——对于同一个用户。子声明是不同的,但有两个。

您从 Microsoft Graph Explorer 获得的令牌是 access_token,第一个 subaccess_token 的值,第二个是您想要的,即 subid_token

似乎来自 OIDC 的令牌没有正确的子声明 - 这怎么可能?

没错,正如我上面提到的,你从 OIDC 得到的sub 和从id_token 得到的sub 是一样的。

参考 - https://docs.microsoft.com/en-us/azure/active-directory/develop/userinfo#userinfo-response

这些值与应用在向应用发出的ID token 中看到的值相同。

注意:您可能会发现手动获取的sub 与从MS Graph Explorer 获取的第二个sub 不同,这是因为您的用户帐户登录了两个不同的客户端,一个是Graph Explorer 的客户端,另一个是您的自定义 AD App。

参考 - https://docs.microsoft.com/en-us/azure/active-directory/develop/id-tokens

更新:

OIDC 不使用 v2.0 端点,为了解决这个问题,我们需要配置 OIDC 使其使用 v2.0 端点,只需在配置的authority 中添加v2.0

【讨论】:

  • 您提供的信息非常好,但它还不能正常工作。我设置了以前不存在的 Graph API 权限,然后使用 tenantid 和 clientid 参数从 /authorize 端点获取了访问令牌 - 这很有效。与来自 OIDC 的访问令牌相比,它包含相同的 access_token 'sub' 但不包含 id_token 'sub' - 它不起作用。
  • @user3167162 你能详细说明一下这个Comparing with the access token from OIDC, it contains the same access_token 'sub' but not the id_token 'sub'吗?也许在jwt.io 中有一些快照?您是否从/authorize 端点获得了access_tokenid_token?你曾经调用过哪个令牌/oidc/userinfo
  • 我已检索到两个访问令牌并针对/oidc/userinfo 端点进行了测试:一个直接来自/authorize 端点,正如您所指示的那样 - 它有效。一秒钟通过OIDC - 这是行不通的。请参阅上面的其他信息。
  • @user3167162 在authority 中添加v2.0
  • @user3167162 完成。
猜你喜欢
  • 2019-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-01
  • 1970-01-01
相关资源
最近更新 更多