身份服务器客户端的 AccessToken 为空

AccessToken is null for identity server client

我有以下 openid 选项:

 app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies",
            });



            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType = "oidc",
                SignInAsAuthenticationType = "Cookies",
                Authority = "http://localhost:5000",              
                ClientId = "mvcClient",
                ClientSecret = "secret",
                RedirectUri = "http://localhost:5002/signin-oidc",
                PostLogoutRedirectUri = "http://localhost:5002",
                ResponseType = "code id_token",                            
                Scope = "openid profile",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var claims_to_exclude = new[]
                        {
                            "aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
                        };

                        var claims_to_keep =
                            n.AuthenticationTicket.Identity.Claims
                            .Where(x => false == claims_to_exclude.Contains(x.Type)).ToList();
                        claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));




                        if (n.ProtocolMessage.AccessToken != null)
                        {
                            claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));

   }    
  }    
 }
}

我看到 n.ProtocolMessage.AccessToken 总是空的。

我在身份服务器中配置客户端是这样的:

 new Client()
                {
                    ClientId = "mvcClient",
                    ClientName = "MVC Client",                      
                    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

                    ClientSecrets = new List<Secret>()
                    {
                        new Secret("secret".Sha256())
                    },

                   // RequireConsent = false,

                    // where to redirect to after login
                    RedirectUris = { "http://localhost:5002/signin-oidc" },
                    // where to redirect to after logout
                    PostLogoutRedirectUris = { "http://localhost:5002" },

                    AllowedScopes =
                    {
                        StandardScopes.OpenId.Name,
                        StandardScopes.Profile.Name,
                        StandardScopes.OfflineAccess.Name,
                        StandardScopes.Roles.Name,
                        "API"
                    }
                },

我想知道为什么 n.ProtocolMessage.AccessToken 为 null 以及如何获取它的值

更新

如果我像这样将客户端类型更改为混合:

AllowedGrantTypes = GrantTypes.Hybrid,

and ResponseType = "code id_token token:

我在服务器上收到 invalid_request 错误

如果我尝试像这样获取访问令牌(在通知中):

var client = new TokenClient("http://localhost:5000/connect/token", "mvcClient", "secret");
                            var response = client.RequestClientCredentialsAsync("testscope").Result;
                            var accesstoken = response.AccessToken;
                            claims_to_keep.Add(new Claim("access_token", accesstoken));

结果令牌只有一个范围(即测试范围),而不是为该客户端定义的所有其他范围。

它为空,因为您没有请求访问令牌。

ResponseType = "code id_token" 表示在回调上给客户端一个 "Authoriziation Code" 和一个 "Id token" 。要接收访问令牌,

  1. token 包含在 ResponseType 中作为 ResponseType = "code id_token token" 并将客户端流更新为混合流(代码 + 令牌),因为这就是我们现在正在做的。

  1. 使用 ProtocolMessage 上可用的 "Authorization Code" 使用 /token 端点获取访问令牌。

访问令牌不应与代码和 id_token 一起返回。 获取它的正确方法是使用客户端 ID 和客户端密码通过后台通道。 将此添加到通知块:

AuthorizationCodeReceived = async n =>
{
    var tokenClient = new TokenClient(n.Options.Authority + "/connect/token", "Client_Id", "secret");
    var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

    if (tokenResponse.IsError)
    {
        throw new Exception(tokenResponse.Error);
    }
    else
    {
        string accessToken = tokenResponse.AccessToken;
        //Other logic
    }
}