@@ -37,6 +37,12 @@ const (
3737 defaultHTTPTimeout = 5 * time .Second
3838)
3939
40+ // Auth0Config captures the Vault JWT issuer settings shared by gateway and node handlers.
41+ type Auth0Config struct {
42+ IssuerURL string `json:"issuerURL" toml:"issuerURL" yaml:"issuerURL"`
43+ Audience string `json:"audience" toml:"audience" yaml:"audience"`
44+ }
45+
4046// JWTBasedAuthConfig holds the configuration for JWTBasedAuth validation.
4147type JWTBasedAuthConfig struct {
4248 IssuerURL string
@@ -119,6 +125,19 @@ func WithDisabledJWTBasedAuth() JWTBasedAuthOption {
119125 }
120126}
121127
128+ // NewJWTBasedAuthFromAuth0Config constructs JWT auth from an optional Auth0 config.
129+ // When auth0 is not configured, the validator is created in a fail-closed disabled state.
130+ func NewJWTBasedAuthFromAuth0Config (auth0 * Auth0Config , limitsFactory limits.Factory , lggr logger.Logger ) (* jwtBasedAuth , error ) {
131+ if auth0 == nil || (auth0 .IssuerURL == "" && auth0 .Audience == "" ) {
132+ return NewJWTBasedAuth (JWTBasedAuthConfig {}, limitsFactory , lggr , WithDisabledJWTBasedAuth ())
133+ }
134+
135+ return NewJWTBasedAuth (JWTBasedAuthConfig {
136+ IssuerURL : auth0 .IssuerURL ,
137+ Audience : auth0 .Audience ,
138+ }, limitsFactory , lggr )
139+ }
140+
122141// NewJWTBasedAuth creates a JWTBasedAuth authorizer that verifies Auth0-issued JWTs
123142// against the provider's JWKS endpoint. The JWKS is fetched lazily on first
124143// use and refreshed on key-ID cache misses (rate-limited).
@@ -209,21 +228,27 @@ func (v *jwtBasedAuth) AuthorizeRequest(ctx context.Context, req jsonrpc.Request
209228 return nil , errors .New ("JWTBasedAuth is disabled" )
210229 }
211230
212- requestDigest , err := req .Digest ()
213- if err != nil {
214- v .lggr .Debugw ("JWTBasedAuth failed to compute request digest" , "method" , req .Method , "requestID" , req .ID , "error" , err )
215- return nil , fmt .Errorf ("failed to compute request digest: %w" , err )
216- }
217-
218231 claims , err := v .validateToken (ctx , req .Auth )
219232 if err != nil {
220233 v .lggr .Debugw ("JWTBasedAuth token validation failed" , "method" , req .Method , "requestID" , req .ID , "error" , err )
221234 return nil , fmt .Errorf ("invalid JWT auth token: %w" , err )
222235 }
223236
237+ normalizedReq , err := NormalizeRequestWithIdentity (req , claims .OrgID , claims .WorkflowOwner )
238+ if err != nil {
239+ v .lggr .Debugw ("JWTBasedAuth failed to normalize request identity" , "method" , req .Method , "requestID" , req .ID , "orgID" , claims .OrgID , "workflowOwner" , claims .WorkflowOwner , "error" , err )
240+ return nil , fmt .Errorf ("failed to normalize request identity: %w" , err )
241+ }
242+
243+ requestDigest , err := normalizedReq .Digest ()
244+ if err != nil {
245+ v .lggr .Debugw ("JWTBasedAuth failed to compute request digest" , "method" , req .Method , "requestID" , req .ID , "orgID" , claims .OrgID , "workflowOwner" , claims .WorkflowOwner , "error" , err )
246+ return nil , fmt .Errorf ("failed to compute request digest: %w" , err )
247+ }
248+
224249 if ! strings .EqualFold (requestDigest , claims .RequestDigest ) {
225250 v .lggr .Debugw ("JWTBasedAuth request digest mismatch" , "method" , req .Method , "requestID" , req .ID , "orgID" , claims .OrgID , "workflowOwner" , claims .WorkflowOwner , "computedDigest" , requestDigest , "claimedDigest" , claims .RequestDigest )
226- return nil , errors . New ("request digest mismatch" )
251+ return nil , fmt . Errorf ("request digest mismatch: computed=%s claimed=%s" , requestDigest , claims . RequestDigest )
227252 }
228253
229254 v .lggr .Debugw ("JWTBasedAuth authorization succeeded" , "method" , req .Method , "requestID" , req .ID , "orgID" , claims .OrgID , "workflowOwner" , claims .WorkflowOwner , "digest" , requestDigest , "expiresAt" , claims .ExpiresAt .UTC ().Unix ())
0 commit comments