-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added SigningKey parameter to JWT Token generator (fixes #913) #914
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Before we continue, let's also update the API, where we expose the ability to create JWT, with the ability to pass the signing key too:
public IActionResult CreateJwtToken([FromBody] JwtOptions jwtOptions) |
I'll mark the PR as draft for now, and please mark it as ready for review when you update it. |
Sorry @waldekmastykarz i don't undestand the API Update you refer, the SigningKey value is inside jwtOptions class so for action CreateJwtToken you can pass the SigningKey value directly in the body. Do you mean to pass the key differently? |
My bad, sorry! I totally missed that you've updated it already. I'll proceed with the review. Sorry for trouble. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to extend the logic of creating the token using the API. Right now, if you specify a key that's too short, proxy crashes with an exception.
Repro:
POST http://localhost:8897/proxy/createJwtToken
Content-Type: application/json
{
"name": "Dev Proxy",
"audiences": [
"https://myserver.com"
],
"issuer": "dev-proxy",
"roles": [
"admin"
],
"scopes": [
"Post.Read",
"Post.Write"
],
"claims": {
"claim1": "value",
"claim2": "value"
},
"validFor": 60,
"signingKey": "mySecret"
}
Expected:
400 Bad Request
The specified signing key is too short. A signing key must be at least 32 characters.
Current:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HN7EFMMH5MCK", Request id "0HN7EFMMH5MCK:00000001": An unhandled exception was thrown by the application.
System.ArgumentOutOfRangeException: IDX10653: The encryption algorithm 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha256' requires a key size of at least '128' bits. Key '[PII of type 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]', is of size: '64'. (Parameter 'key')
at Microsoft.IdentityModel.Tokens.SymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures, Boolean cacheProvider)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm, Boolean cacheProvider)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm)
at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateJwtSecurityTokenPrivate(String issuer, String audience, IList`1 audiences, ClaimsIdentity subject, Nullable`1 notBefore, Nullable`1 expires, Nullable`1 issuedAt, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, IDictionary`2 claimCollection, String tokenType, IDictionary`2 additionalHeaderClaims, IDictionary`2 additionalInnerHeaderClaims)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateJwtSecurityTokenPrivate(String issuer, String audience, ClaimsIdentity subject, Nullable`1 notBefore, Nullable`1 expires, Nullable`1 issuedAt, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, IDictionary`2 claimCollection, String tokenType, IDictionary`2 additionalHeaderClaims, IDictionary`2 additionalInnerHeaderClaims)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateJwtSecurityToken(String issuer, String audience, ClaimsIdentity subject, Nullable`1 notBefore, Nullable`1 expires, Nullable`1 issuedAt, SigningCredentials signingCredentials)
at Microsoft.DevProxy.Jwt.JwtIssuer.CreateSecurityToken(JwtCreatorOptions options) in /Users/waldek/github/microsoft/dev-proxy/dev-proxy/Jwt/JwtIssuer.cs:line 66
at Microsoft.DevProxy.Jwt.JwtTokenGenerator.CreateToken(JwtOptions jwtOptions) in /Users/waldek/github/microsoft/dev-proxy/dev-proxy/Jwt/JwtTokenGenerator.cs:line 20
at Microsoft.DevProxy.ApiControllers.ProxyController.CreateJwtToken(JwtOptions jwtOptions) in /Users/waldek/github/microsoft/dev-proxy/dev-proxy/ApiControllers/ProxyController.cs:line 58
at lambda_method2(Closure, Object, Object[])
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Ok in case "signingKey":"" same error or goes ahead and generates a random key? |
Let's use a random key if the user hasn't specified any key. If they specified an empty value, the API should respond with 400 Bad Request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works like a charm! 👏
The JWT Token generated by dev-proxy cannot be validated into an ASP.NET Core Web API.
Adding the signing key is possibile to validate the generated JWT token for a specific user and scope for a endpoint that requires authentication and authorization