1
0
mirror of https://github.com/labstack/echo.git synced 2024-11-24 08:22:21 +02:00

Add HandleEmptyToken to JWT middleware

Now it is possible to add custom handler for missing JWT.
This commit is contained in:
Przemek Komosa 2016-07-02 00:55:11 +02:00
parent bb6baa2088
commit ae09482493
2 changed files with 46 additions and 4 deletions

View File

@ -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
} }
} }

View File

@ -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 == "" {