mirror of
				https://github.com/labstack/echo.git
				synced 2025-10-30 23:57:38 +02:00 
			
		
		
		
	Add HandleEmptyToken to JWT middleware
Now it is possible to add custom handler for missing JWT.
This commit is contained in:
		| @@ -32,6 +32,10 @@ type ( | |||||||
| 		// - "header:<name>" | 		// - "header:<name>" | ||||||
| 		// - "query:<name>" | 		// - "query:<name>" | ||||||
| 		TokenLookup string `json:"token_lookup"` | 		TokenLookup string `json:"token_lookup"` | ||||||
|  |  | ||||||
|  | 		// HandleEmptyToken is handler executed when there is no token. | ||||||
|  | 		// It could be used for redirection. | ||||||
|  | 		HandleEmptyToken echo.HandlerFunc | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	jwtExtractor func(echo.Context) (string, error) | 	jwtExtractor func(echo.Context) (string, error) | ||||||
| @@ -52,7 +56,12 @@ var ( | |||||||
| 		SigningMethod: AlgorithmHS256, | 		SigningMethod: AlgorithmHS256, | ||||||
| 		ContextKey:    "user", | 		ContextKey:    "user", | ||||||
| 		TokenLookup:   "header:" + echo.HeaderAuthorization, | 		TokenLookup:   "header:" + echo.HeaderAuthorization, | ||||||
|  | 		HandleEmptyToken: func(c echo.Context) error { | ||||||
|  | 			return echo.NewHTTPError(http.StatusBadRequest, errJWTEmptyToken.Error()) | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	errJWTEmptyToken = errors.New("empty jwt") | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // JWT returns a JSON Web Token (JWT) auth middleware. | // JWT returns a JSON Web Token (JWT) auth middleware. | ||||||
| @@ -84,6 +93,9 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { | |||||||
| 	if config.TokenLookup == "" { | 	if config.TokenLookup == "" { | ||||||
| 		config.TokenLookup = DefaultJWTConfig.TokenLookup | 		config.TokenLookup = DefaultJWTConfig.TokenLookup | ||||||
| 	} | 	} | ||||||
|  | 	if config.HandleEmptyToken == nil { | ||||||
|  | 		config.HandleEmptyToken = DefaultJWTConfig.HandleEmptyToken | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Initialize | 	// Initialize | ||||||
| 	parts := strings.Split(config.TokenLookup, ":") | 	parts := strings.Split(config.TokenLookup, ":") | ||||||
| @@ -97,6 +109,9 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { | |||||||
| 		return func(c echo.Context) error { | 		return func(c echo.Context) error { | ||||||
| 			auth, err := extractor(c) | 			auth, err := extractor(c) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
|  | 				if err == errJWTEmptyToken { | ||||||
|  | 					return config.HandleEmptyToken(c) | ||||||
|  | 				} | ||||||
| 				return echo.NewHTTPError(http.StatusBadRequest, err.Error()) | 				return echo.NewHTTPError(http.StatusBadRequest, err.Error()) | ||||||
| 			} | 			} | ||||||
| 			token, err := jwt.Parse(auth, func(t *jwt.Token) (interface{}, error) { | 			token, err := jwt.Parse(auth, func(t *jwt.Token) (interface{}, error) { | ||||||
| @@ -122,11 +137,15 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { | |||||||
| func jwtFromHeader(header string) jwtExtractor { | func jwtFromHeader(header string) jwtExtractor { | ||||||
| 	return func(c echo.Context) (string, error) { | 	return func(c echo.Context) (string, error) { | ||||||
| 		auth := c.Request().Header().Get(header) | 		auth := c.Request().Header().Get(header) | ||||||
|  | 		lenAuth := len(auth) | ||||||
|  | 		if lenAuth == 0 { | ||||||
|  | 			return "", errJWTEmptyToken | ||||||
|  | 		} | ||||||
| 		l := len(bearer) | 		l := len(bearer) | ||||||
| 		if len(auth) > l+1 && auth[:l] == bearer { | 		if lenAuth > l+1 && auth[:l] == bearer { | ||||||
| 			return auth[l+1:], nil | 			return auth[l+1:], nil | ||||||
| 		} | 		} | ||||||
| 		return "", errors.New("empty or invalid jwt in authorization header") | 		return "", errors.New("invalid jwt in authorization header") | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -135,9 +154,10 @@ func jwtFromHeader(header string) jwtExtractor { | |||||||
| func jwtFromQuery(param string) jwtExtractor { | func jwtFromQuery(param string) jwtExtractor { | ||||||
| 	return func(c echo.Context) (string, error) { | 	return func(c echo.Context) (string, error) { | ||||||
| 		token := c.QueryParam(param) | 		token := c.QueryParam(param) | ||||||
|  | 		var err error | ||||||
| 		if token == "" { | 		if token == "" { | ||||||
| 			return "", errors.New("empty jwt in query param") | 			err = errJWTEmptyToken | ||||||
| 		} | 		} | ||||||
| 		return token, nil | 		return token, err | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,6 +19,9 @@ func TestJWT(t *testing.T) { | |||||||
| 	validKey := []byte("secret") | 	validKey := []byte("secret") | ||||||
| 	invalidKey := []byte("invalid-key") | 	invalidKey := []byte("invalid-key") | ||||||
| 	validAuth := bearer + " " + token | 	validAuth := bearer + " " + token | ||||||
|  | 	redirect := func(c echo.Context) error { | ||||||
|  | 		return echo.NewHTTPError(http.StatusFound, "redirect") | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	for _, tc := range []struct { | 	for _, tc := range []struct { | ||||||
| 		expPanic   bool | 		expPanic   bool | ||||||
| @@ -60,6 +63,15 @@ func TestJWT(t *testing.T) { | |||||||
| 			expErrCode: http.StatusBadRequest, | 			expErrCode: http.StatusBadRequest, | ||||||
| 			info:       "Empty header auth field", | 			info:       "Empty header auth field", | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			config: JWTConfig{ | ||||||
|  | 				SigningKey:       validKey, | ||||||
|  | 				HandleEmptyToken: redirect, | ||||||
|  | 			}, | ||||||
|  | 			hdrAuth:    "", | ||||||
|  | 			expErrCode: http.StatusFound, | ||||||
|  | 			info:       "Empty header auth field with redirect", | ||||||
|  | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			config: JWTConfig{ | 			config: JWTConfig{ | ||||||
| 				SigningKey:  validKey, | 				SigningKey:  validKey, | ||||||
| @@ -95,6 +107,16 @@ func TestJWT(t *testing.T) { | |||||||
| 			expErrCode: http.StatusBadRequest, | 			expErrCode: http.StatusBadRequest, | ||||||
| 			info:       "Empty query", | 			info:       "Empty query", | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			config: JWTConfig{ | ||||||
|  | 				SigningKey:       validKey, | ||||||
|  | 				TokenLookup:      "query:jwt", | ||||||
|  | 				HandleEmptyToken: redirect, | ||||||
|  | 			}, | ||||||
|  | 			reqURL:     "/?a=b", | ||||||
|  | 			expErrCode: http.StatusFound, | ||||||
|  | 			info:       "Empty query with redirect", | ||||||
|  | 		}, | ||||||
| 	} { | 	} { | ||||||
|  |  | ||||||
| 		if tc.reqURL == "" { | 		if tc.reqURL == "" { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user