File tree Expand file tree Collapse file tree 6 files changed +40
-12
lines changed
Expand file tree Collapse file tree 6 files changed +40
-12
lines changed Original file line number Diff line number Diff line change 1+ using Jose ;
2+ using System . Security . Cryptography ;
3+
4+ public static class JwkHelper
5+ {
6+ public static WebApplication MapJwk ( this WebApplication app , out Jwk jwk )
7+ {
8+ var ecSigner = ECDsa . Create ( ECCurve . NamedCurves . nistP521 ) ; // Typically, you'd load this from a secure location and not create a new one each time
9+
10+ jwk = new Jwk ( ecSigner , false )
11+ {
12+ KeyId = "bank-api-2025-1"
13+ } ;
14+
15+ var keySet = new JwkSet ( jwk ) ;
16+
17+ app . MapGet ( "/.well-known/jwks.json" , ( ) => TypedResults . Ok ( keySet . ToDictionary ( ) ) )
18+ . ExcludeFromDescription ( )
19+ . AllowAnonymous ( ) ;
20+
21+ return app ;
22+ }
23+ }
Original file line number Diff line number Diff line change 11using Jose ;
2- using System . Security . Cryptography ;
32
43/// <summary>
54/// <para> This middleware class signs the response body of each HTTP response using JSON Web Signature (JWS) with ECDSA.</para>
65/// </summary>
76public class JwsResponseSigningMiddleware
87{
98 private readonly RequestDelegate _next ;
10- private readonly ECDsa _ecSigner ;
9+ private readonly Jwk _jwk ;
1110 private static readonly string [ ] headerCritValue = [ "kid" , "alg" ] ;
1211 private static readonly string [ ] pathsToSkip = [ "/scalar" , "/openapi" , "/health" ] ;
1312
14- public JwsResponseSigningMiddleware ( RequestDelegate next , ECDsa ecSigner )
13+ public JwsResponseSigningMiddleware ( RequestDelegate next , Jwk jwk )
1514 {
1615 _next = next ;
17- _ecSigner = ecSigner ;
16+ _jwk = jwk ;
1817 }
1918
2019 public async Task InvokeAsync ( HttpContext context )
@@ -39,13 +38,13 @@ public async Task InvokeAsync(HttpContext context)
3938 {
4039 { "crit" , headerCritValue } ,
4140 { "iat" , DateTimeOffset . UtcNow . ToUnixTimeSeconds ( ) } ,
42- { "kid" , "bank-api-2025-1" }
41+ { "kid" , _jwk . KeyId }
4342 } ;
4443
4544 // Sign the response body using ECDSA
4645 string jws = JWT . EncodeBytes (
4746 responseBytes ,
48- _ecSigner ,
47+ _jwk ,
4948 JwsAlgorithm . ES512 ,
5049 extraHeaders ,
5150 options : new JwtOptions { DetachPayload = true } ) ;
Original file line number Diff line number Diff line change 1- using System . Security . Cryptography ;
21using Gridify ;
32using Microsoft . OpenApi . Models ;
43
54var builder = WebApplication . CreateBuilder ( args ) ;
6- var ecSigner = ECDsa . Create ( ECCurve . NamedCurves . nistP521 ) ; // Typically, you'd load this from a secure location and not create a new one each time
75
86GlobalConfiguration . ApiDocument = builder . Configuration . GetRequiredSection ( "ApiDocument" ) . Get < OpenApiDocument > ( ) ! ;
97GlobalConfiguration . ApiSettings = builder . Configuration . GetRequiredSection ( "ApiSettings" ) . Get < GlobalConfiguration . SettingsModel > ( ) ! ;
2624
2725var app = builder . Build ( ) ;
2826
29- app . UseMiddleware < JwsResponseSigningMiddleware > ( ecSigner ) ;
27+ app . MapJwk ( out var jwk ) ; // register JWKS endpoint
28+ app . UseMiddleware < JwsResponseSigningMiddleware > ( jwk ) ;
3029app . UseMiddleware < ApiVersionHeaderMiddleware > ( ) ;
3130app . UseExceptionHandler ( ) ;
3231app . UsePathBase ( new ( $ "/{ GlobalConfiguration . ApiDocument . Info . Version } ") ) ; // Useful when versioning routing happens in an API Management system
Original file line number Diff line number Diff line change 77
88###
99
10+ https://{{host}}/{{apiVersion}}/.well-known/jwks.json
11+
12+ ###
13+
1014https://{{host}}/{{apiVersion}}/health
1115Ocp-Apim-Subscription-Key: Lifetime Subscription
1216
Original file line number Diff line number Diff line change 1- using System . Security . Cryptography ;
21using Gridify ;
32using Microsoft . OpenApi . Models ;
43
54var builder = WebApplication . CreateBuilder ( args ) ;
6- var ecSigner = ECDsa . Create ( ECCurve . NamedCurves . nistP521 ) ; // Typically, you'd load this from a secure location and not create a new one each time
75
86GlobalConfiguration . ApiDocument = builder . Configuration . GetRequiredSection ( "ApiDocument" ) . Get < OpenApiDocument > ( ) ! ;
97GlobalConfiguration . ApiSettings = builder . Configuration . GetRequiredSection ( "ApiSettings" ) . Get < GlobalConfiguration . SettingsModel > ( ) ! ;
2624
2725var app = builder . Build ( ) ;
2826
29- app . UseMiddleware < JwsResponseSigningMiddleware > ( ecSigner ) ;
27+ app . MapJwk ( out var jwk ) ; // register JWKS endpoint
28+ app . UseMiddleware < JwsResponseSigningMiddleware > ( jwk ) ;
3029app . UseMiddleware < ApiVersionHeaderMiddleware > ( ) ;
3130app . UseExceptionHandler ( ) ;
3231app . UsePathBase ( new ( $ "/{ GlobalConfiguration . ApiDocument . Info . Version } ") ) ; // Useful when versioning routing happens in an API Management system
Original file line number Diff line number Diff line change 77
88###
99
10+ https://{{host}}/{{apiVersion}}/.well-known/jwks.json
11+
12+ ###
13+
1014https://{{host}}/{{apiVersion}}/health
1115Ocp-Apim-Subscription-Key: Lifetime Subscription
1216
You can’t perform that action at this time.
0 commit comments