@@ -29,12 +29,12 @@ type (
29
29
// ErrorHandlerWithContext is almost identical to ErrorHandler, but it's passed the current context.
30
30
ErrorHandlerWithContext JWTErrorHandlerWithContext
31
31
32
- // Signing key to validate token. Used as fallback if SigningKeys has length 0.
33
- // Required. This or SigningKeys.
32
+ // Signing key to validate token. Used as fallback if KeyFunc is nil or SigningKeys has length 0.
33
+ // Required. This or SigningKeys or KeyFunc .
34
34
SigningKey interface {}
35
35
36
- // Map of signing keys to validate token with kid field usage.
37
- // Required. This or SigningKey.
36
+ // Map of signing keys to validate token with kid field usage. Used as fallback if KeyFunc is nil.
37
+ // Required. This or SigningKey or KeyFunc .
38
38
SigningKeys map [string ]interface {}
39
39
40
40
// Signing method, used to check token signing method.
@@ -64,7 +64,12 @@ type (
64
64
// Optional. Default value "Bearer".
65
65
AuthScheme string
66
66
67
- keyFunc jwt.Keyfunc
67
+ // KeyFunc defines a function to supply the key for a token verification.
68
+ // When a user-defined KeyFunc is provided, SigningKey, SigningKeys, and SigningMethod are ignored.
69
+ // Required. This or SigningKey or SigningKeys.
70
+ // Default to an internal implementation verifying the signing algorithm and selecting the proper key.
71
+ // See: `jwt.Keyfunc`
72
+ KeyFunc jwt.Keyfunc
68
73
}
69
74
70
75
// JWTSuccessHandler defines a function which is executed for a valid token.
99
104
TokenLookup : "header:" + echo .HeaderAuthorization ,
100
105
AuthScheme : "Bearer" ,
101
106
Claims : jwt.MapClaims {},
107
+ KeyFunc : nil ,
102
108
}
103
109
)
104
110
@@ -123,7 +129,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
123
129
if config .Skipper == nil {
124
130
config .Skipper = DefaultJWTConfig .Skipper
125
131
}
126
- if config .SigningKey == nil && len (config .SigningKeys ) == 0 {
132
+ if config .SigningKey == nil && len (config .SigningKeys ) == 0 && config . KeyFunc == nil {
127
133
panic ("echo: jwt middleware requires signing key" )
128
134
}
129
135
if config .SigningMethod == "" {
@@ -141,21 +147,8 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
141
147
if config .AuthScheme == "" {
142
148
config .AuthScheme = DefaultJWTConfig .AuthScheme
143
149
}
144
- config .keyFunc = func (t * jwt.Token ) (interface {}, error ) {
145
- // Check the signing method
146
- if t .Method .Alg () != config .SigningMethod {
147
- return nil , fmt .Errorf ("unexpected jwt signing method=%v" , t .Header ["alg" ])
148
- }
149
- if len (config .SigningKeys ) > 0 {
150
- if kid , ok := t .Header ["kid" ].(string ); ok {
151
- if key , ok := config .SigningKeys [kid ]; ok {
152
- return key , nil
153
- }
154
- }
155
- return nil , fmt .Errorf ("unexpected jwt key id=%v" , t .Header ["kid" ])
156
- }
157
-
158
- return config .SigningKey , nil
150
+ if config .KeyFunc == nil {
151
+ config .KeyFunc = config .defaultKeyFunc
159
152
}
160
153
161
154
// Initialize
@@ -196,11 +189,11 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
196
189
token := new (jwt.Token )
197
190
// Issue #647, #656
198
191
if _ , ok := config .Claims .(jwt.MapClaims ); ok {
199
- token , err = jwt .Parse (auth , config .keyFunc )
192
+ token , err = jwt .Parse (auth , config .KeyFunc )
200
193
} else {
201
194
t := reflect .ValueOf (config .Claims ).Type ().Elem ()
202
195
claims := reflect .New (t ).Interface ().(jwt.Claims )
203
- token , err = jwt .ParseWithClaims (auth , claims , config .keyFunc )
196
+ token , err = jwt .ParseWithClaims (auth , claims , config .KeyFunc )
204
197
}
205
198
if err == nil && token .Valid {
206
199
// Store user information from token into context.
@@ -225,6 +218,24 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
225
218
}
226
219
}
227
220
221
+ // defaultKeyFunc returns a signing key of the given token.
222
+ func (config * JWTConfig ) defaultKeyFunc (t * jwt.Token ) (interface {}, error ) {
223
+ // Check the signing method
224
+ if t .Method .Alg () != config .SigningMethod {
225
+ return nil , fmt .Errorf ("unexpected jwt signing method=%v" , t .Header ["alg" ])
226
+ }
227
+ if len (config .SigningKeys ) > 0 {
228
+ if kid , ok := t .Header ["kid" ].(string ); ok {
229
+ if key , ok := config .SigningKeys [kid ]; ok {
230
+ return key , nil
231
+ }
232
+ }
233
+ return nil , fmt .Errorf ("unexpected jwt key id=%v" , t .Header ["kid" ])
234
+ }
235
+
236
+ return config .SigningKey , nil
237
+ }
238
+
228
239
// jwtFromHeader returns a `jwtExtractor` that extracts token from the request header.
229
240
func jwtFromHeader (header string , authScheme string ) jwtExtractor {
230
241
return func (c echo.Context ) (string , error ) {
0 commit comments