Closed congiuluc closed 1 month ago
I'll mark the PR as draft for now, and please mark it as ready for review when you update it.
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:
.
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.
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?
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.
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