Microsoft Graph API userInfo endpoint UnknownError: Token must contain sub claim

Microsoft Graph API userInfo endpoint UnknownError: Token must contain sub claim

我正在尝试使用通过 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 端点访问令牌 [工作中]:

来自 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"
};

The access token is valid and does contain a sub claim.

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

1.Register an application with Azure AD

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

3.In Authentication,选择以下选项。

4.Hit浏览器下面的URL,替换掉你的<tenant-id><client-id>,登录你的用户账号,然后你会得到一个access_tokenid_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.Use access_token 调用 https://graph.microsoft.com/oidc/userinfo 端点,它工作正常,sub 值在我的示例中是 EY4uO7uc1IG2n8EboEalB4LDxJ1NU8nuc2JXZgkisN4

6.Decodehttps://jwt.io/中第4步得到的id_tokensub也是EY4uO7uc1IG2n8EboEalB4LDxJ1NU8nuc2JXZgkisN4,所以就是subhttps://graph.microsoft.com/oidc/userinfo 得到的端点是正确的。

If I sign-in to https://developer.microsoft.com/en-us/graph/graph-explorer, and use the access token it automatically retrieves, it works - for the same user. The sub claim is different though and there are two of them.

您从 Microsoft Graph Explorer 获得的标记是 access_token,第一个 subaccess_token 的值,第二个是您想要的,即 sub id_token.

It seems the token from OIDC doesn't have a correct sub claim - how come might this be?

没错,正如我上面提到的,您从 OIDC 获得的 sub 与从 id_token.

获得的 sub 相同

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

These are the same values that the app would see in the ID token issued to the app.

注意:您可能会发现手动获取的 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配置。