问题描述
我正在尝试弄清楚如何为代码流定义AuthorizationCodetokenRequest 对于JWT场景,使用IdentityModole框架
假设我在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不正确 在任何地方都找不到有效的代码示例。
解决方法
首先,您需要在IdentityServer的“客户端定义”中定义希望客户端支持的流。
您可以通过设置以下属性来做到这一点:
AllowedGrantTypes = GrantTypes.Code,
有关如何正确创建客户定义的详细信息,请参见here。
示例客户端如下所示:
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";
});
您需要调整代码以适合您的需求。