0

我试图弄清楚如何使用 IdentityModole framwork 为 JWT 场景的代码流定义我的 AuthorizationCodeTokenRequest

假设我的 OP 服务器上有一个已定义的客户端


new Client
{
ClientId = "myClientId"
ClientSecrets = {
new Secret("MyVerySpecialSecret".Sha256())
}

在客户端,我想使用JWT获取 AuthorizationCode

        var securityToken = tokenHandler.CreateJwtSecurityToken(
            issuer: clientID,
            audience: opEndPoint.TokenEndpoint,
            subject: new ClaimsIdentity(new List<Claim>()
            {
                        new Claim(JwtClaimTypes.JwtId, Guid.NewGuid().ToString()),
                        new Claim(JwtClaimTypes.Subject, clientID),
                        new Claim(JwtClaimTypes.IssuedAt, new DateTimeOffset(now).ToEpochTime().ToString(),
                            ClaimValueTypes.Integer64)
            }),
            expires:now.AddMinutes(5),
            signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MyVerySpecialSecret")), SecurityAlgorithms.HmacSha256Signature)
        );

        var clientAuthJwt = tokenHandler.WriteToken(securityToken);
var request = new AuthorizationCodeTokenRequest()
{
Address = opEndPoint.TokenEndpoint,
ClientId = clientID,
Code = code,
ClientAssertion = new ClientAssertion()
{
Type = OidcConstants.ClientAssertionTypes.JwtBearer,
Value = clientAuthJwt
},
RedirectUri = opEndPoint.RedirectUri,
GrantType = OidcConstants.GrantTypes.AuthorizationCode
};

    var response = client.RequestAuthorizationCodeTokenAsync(request).Result;

我得到“invalid_client”,所以很明显我使用的 SigningCredentials 不正确,无法在任何地方找到工作代码示例。

4

1 回答 1

0

首先,您需要在 IdentityServer 的客户端定义中定义您希望客户端支持的流。

您可以通过设置以下属性来做到这一点:

AllowedGrantTypes = GrantTypes.Code,

有关如何正确创建客户端定义的详细信息,请参阅此处。

示例客户端可能如下所示:

       var client2 = new Client
        {
            ClientId = "authcodeflowclient",        //Unique ID of the client
            ClientName = "AuthCodeFlow Client",     //Client display name (used for logging and consent screen)
            ClientUri = "https://www.edument.se",   //URI to further information about client (used on consent screen)
            RequirePkce = true,
            AllowOfflineAccess =true,

            ClientSecrets = new List<Secret>
            {
                new Secret
                {
                    Value = "mysecret".Sha512()
                }
            },

            AllowedGrantTypes = GrantTypes.Code,

            // When requesting both an id token and access token, should the user claims always
            // be added to the id token instead of requiring the client to use the userinfo endpoint.
            // Defaults to false.
            AlwaysIncludeUserClaimsInIdToken = false,

            //Specifies whether this client is allowed to receive access tokens via the browser. 
            //This is useful to harden flows that allow multiple response types 
            //(e.g. by disallowing a hybrid flow client that is supposed to  use code id_token to add the token response type and thus leaking the token to the browser.
            AllowAccessTokensViaBrowser = false,

            RedirectUris =
            {
                "https://localhost:5001/CodeFlow/Callback",
                "https://localhost:5001/RefreshToken/Callback",
                "https://localhost:5001/signin-oidc"
            },

            PostLogoutRedirectUris = { "https://localhost:5001/signout-callback-oidc" },

            // By default a client has no access to any resources
            // specify the allowed resources by adding the corresponding scopes names.
            // If empty, the client can't access any scope
            AllowedScopes =
            {
                //Standard scopes
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Phone,
                "employee_info",
                "shop.admin",
                "shop.employee",
                "shop.guest"
            },

            AllowedCorsOrigins =
            {
                "https://localhost:5001"
            }
        };

SigningCredentials 是一个单独的东西,它控制 IdentityServer 颁发的密钥的颁发方式。在开发中,您无需担心这一点,因为当您调用此方法时,所有这些都已处理完毕。builder.AddDeveloperSigningCredential();

您只需要在部署 IdentityServer 时处理 SigningCredentials。

在客户端,您需要在 ASP.NET Core 客户端应用程序中编写如下所示的代码:

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        }).AddCookie(options =>
        {
            options.LoginPath = "/User/Login";
            options.LogoutPath = "/User/Logout";
            options.AccessDeniedPath = "/User/AccessDenied";
        }).AddOpenIdConnect(options =>
        {
            options.Authority = "https://localhost:6001";
            options.ClientId = "authcodeflowclient";
            options.ClientSecret = "mysecret";
            options.ResponseType = "code";

            options.Scope.Clear();
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("email");
            options.Scope.Add("employee_info");



            options.SaveTokens = true;
            options.SignedOutRedirectUri = "/";
            options.GetClaimsFromUserInfoEndpoint = true;

            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = JwtClaimTypes.Name,
                RoleClaimType = JwtClaimTypes.Role,
            };

            options.Prompt = "consent";
        });

您需要调整代码以满足您的需要。

于 2020-09-07T14:13:23.140 回答