IdentityServer4 - 为输入参数 'scope' 提供的值无效。范围 https://graph.microsoft.com/user.read 电子邮件无效

IdentityServer4 - The provided value for the input parameter 'scope' is not valid. The scope https://graph.microsoft.com/user.read email is not valid

我正在尝试使用 Microsoft 帐户作为 IdentityServer4 中的外部登录,我在 Microsoft 应用程序门户下创建了一个新应用程序并将其配置如下:

  1. 我添加了新的网络平台
  2. 在委托权限下我添加了以下权限
    • User.Read
    • 电子邮件
    • openId
    • 简介

这是我在 IdentityServer4 中使用的代码,通过添加电子邮件作为范围来访问 Microsoft 帐户:

services.AddAuthentication()
    .AddMicrosoftAccount("MicrosoftAccount", options =>
    {
        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

        options.ClientId = "ClientId";
        options.ClientSecret = "ClientSecret";
        options.Scope.Add("email");

});

但是在尝试访问 Microsoft 帐户时出现以下错误

为输入参数 'scope' 提供的值无效。范围 https://graph.microsoft.com/user.read 电子邮件无效

使用 OpenID Connect 时,您必须始终在请求的范围列表中包含 openid。为了完整起见,这里有一个工作设置:

options.Scope.Add("openid");
options.Scope.Add("email");

这由 Microsoft here:

记录

If an app performs sign-in by using OpenID Connect, it must request the openid scope.

其实只是OpenID的一部分spec:

OpenID Connect requests MUST contain the openid scope value. If the openid scope value is not present, the behavior is entirely unspecified. Other scope values MAY be present. Scope values used that are not understood by an implementation SHOULD be ignored.

默认情况下 ASP.NET 核心 only sets the user.read scope by default, which is why you need to add it yourself. It seems that the Google implementation in ASP.NET Core does include the openid scope 中的 Microsoft 帐户实施,这解释了为什么您可能会看到不同提供商的不同结果。

鉴于您已将 profile 范围添加到委派权限列表中,您可能还想将其包含在请求的范围列表中。

这解释了错误的原因,但更简单的方法可能是完全保留请求的范围列表(仅使用默认值 user.read)。在我的示例中这样做,我仍然在我的示例中得到相同的声明列表,它由 nameidentifiernamegivennamesurnameemailaddress 组成.这可以解释为什么默认情况下不请求 OpenID 特定范围。