Skip to content

Commit b7dd125

Browse files
committed
Allow JWT middleware to gracefully fail when CredentialsOptional is set to true
1 parent 6b5e62b commit b7dd125

File tree

2 files changed

+44
-17
lines changed

2 files changed

+44
-17
lines changed

middleware/jwt.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ type (
3232
// ErrorHandlerWithContext is almost identical to ErrorHandler, but it's passed the current context.
3333
ErrorHandlerWithContext JWTErrorHandlerWithContext
3434

35+
// A boolean indicating if the credentials are required or not
36+
// Default value: false
37+
CredentialsOptional bool
38+
3539
// Signing key to validate token.
3640
// This is one of the three options to provide a token validation key.
3741
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
@@ -218,6 +222,10 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
218222
}
219223
// If none of extractor has a token, handle error
220224
if err != nil {
225+
if config.CredentialsOptional {
226+
return next(c)
227+
}
228+
221229
if config.ErrorHandler != nil {
222230
return config.ErrorHandler(err)
223231
}
@@ -237,6 +245,9 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
237245
}
238246
return next(c)
239247
}
248+
if config.CredentialsOptional {
249+
return next(c)
250+
}
240251
if config.ErrorHandler != nil {
241252
return config.ErrorHandler(err)
242253
}

middleware/jwt_test.go

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,15 @@ func TestJWT(t *testing.T) {
7575
validAuth := DefaultJWTConfig.AuthScheme + " " + token
7676

7777
for _, tc := range []struct {
78-
expPanic bool
79-
expErrCode int // 0 for Success
80-
config JWTConfig
81-
reqURL string // "/" if empty
82-
hdrAuth string
83-
hdrCookie string // test.Request doesn't provide SetCookie(); use name=val
84-
formValues map[string]string
85-
info string
78+
expPanic bool
79+
expErrCode int // 0 for Success
80+
expEmptyCtx bool
81+
config JWTConfig
82+
reqURL string // "/" if empty
83+
hdrAuth string
84+
hdrCookie string // test.Request doesn't provide SetCookie(); use name=val
85+
formValues map[string]string
86+
info string
8687
}{
8788
{
8889
expPanic: true,
@@ -266,6 +267,17 @@ func TestJWT(t *testing.T) {
266267
config: JWTConfig{SigningKey: validKey},
267268
info: "Valid JWT with lower case AuthScheme",
268269
},
270+
{
271+
expEmptyCtx: true,
272+
config: JWTConfig{SigningKey: validKey, CredentialsOptional: true},
273+
info: "Valid JWT",
274+
},
275+
{
276+
expEmptyCtx: false,
277+
hdrAuth: validAuth,
278+
config: JWTConfig{SigningKey: validKey, CredentialsOptional: true},
279+
info: "Valid JWT",
280+
},
269281
} {
270282
if tc.reqURL == "" {
271283
tc.reqURL = "/"
@@ -309,15 +321,19 @@ func TestJWT(t *testing.T) {
309321

310322
h := JWTWithConfig(tc.config)(handler)
311323
if assert.NoError(t, h(c), tc.info) {
312-
user := c.Get("user").(*jwt.Token)
313-
switch claims := user.Claims.(type) {
314-
case jwt.MapClaims:
315-
assert.Equal(t, claims["name"], "John Doe", tc.info)
316-
case *jwtCustomClaims:
317-
assert.Equal(t, claims.Name, "John Doe", tc.info)
318-
assert.Equal(t, claims.Admin, true, tc.info)
319-
default:
320-
panic("unexpected type of claims")
324+
if tc.expEmptyCtx {
325+
assert.Nil(t, c.Get("user"), tc.info)
326+
} else {
327+
user := c.Get("user").(*jwt.Token)
328+
switch claims := user.Claims.(type) {
329+
case jwt.MapClaims:
330+
assert.Equal(t, claims["name"], "John Doe", tc.info)
331+
case *jwtCustomClaims:
332+
assert.Equal(t, claims.Name, "John Doe", tc.info)
333+
assert.Equal(t, claims.Admin, true, tc.info)
334+
default:
335+
panic("unexpected type of claims")
336+
}
321337
}
322338
}
323339
}

0 commit comments

Comments
 (0)