Skip to content

Commit

Permalink
Add HandleEmptyToken to JWT middleware
Browse files Browse the repository at this point in the history
Now it is possible to add custom handler for missing JWT.
  • Loading branch information
Komosa committed Jul 1, 2016
1 parent bb6baa2 commit ae09482
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
28 changes: 24 additions & 4 deletions middleware/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ type (
// - "header:<name>"
// - "query:<name>"
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)
Expand All @@ -52,7 +56,12 @@ var (
SigningMethod: AlgorithmHS256,
ContextKey: "user",
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.
Expand Down Expand Up @@ -84,6 +93,9 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
if config.TokenLookup == "" {
config.TokenLookup = DefaultJWTConfig.TokenLookup
}
if config.HandleEmptyToken == nil {
config.HandleEmptyToken = DefaultJWTConfig.HandleEmptyToken
}

// Initialize
parts := strings.Split(config.TokenLookup, ":")
Expand All @@ -97,6 +109,9 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
return func(c echo.Context) error {
auth, err := extractor(c)
if err != nil {
if err == errJWTEmptyToken {
return config.HandleEmptyToken(c)
}
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
token, err := jwt.Parse(auth, func(t *jwt.Token) (interface{}, error) {
Expand All @@ -122,11 +137,15 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
func jwtFromHeader(header string) jwtExtractor {
return func(c echo.Context) (string, error) {
auth := c.Request().Header().Get(header)
lenAuth := len(auth)
if lenAuth == 0 {
return "", errJWTEmptyToken
}
l := len(bearer)
if len(auth) > l+1 && auth[:l] == bearer {
if lenAuth > l+1 && auth[:l] == bearer {
return auth[l+1:], nil
}
return "", errors.New("empty or invalid jwt in authorization header")
return "", errors.New("invalid jwt in authorization header")
}
}

Expand All @@ -135,9 +154,10 @@ func jwtFromHeader(header string) jwtExtractor {
func jwtFromQuery(param string) jwtExtractor {
return func(c echo.Context) (string, error) {
token := c.QueryParam(param)
var err error
if token == "" {
return "", errors.New("empty jwt in query param")
err = errJWTEmptyToken
}
return token, nil
return token, err
}
}
22 changes: 22 additions & 0 deletions middleware/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ func TestJWT(t *testing.T) {
validKey := []byte("secret")
invalidKey := []byte("invalid-key")
validAuth := bearer + " " + token
redirect := func(c echo.Context) error {
return echo.NewHTTPError(http.StatusFound, "redirect")
}

for _, tc := range []struct {
expPanic bool
Expand Down Expand Up @@ -60,6 +63,15 @@ func TestJWT(t *testing.T) {
expErrCode: http.StatusBadRequest,
info: "Empty header auth field",
},
{
config: JWTConfig{
SigningKey: validKey,
HandleEmptyToken: redirect,
},
hdrAuth: "",
expErrCode: http.StatusFound,
info: "Empty header auth field with redirect",
},
{
config: JWTConfig{
SigningKey: validKey,
Expand Down Expand Up @@ -95,6 +107,16 @@ func TestJWT(t *testing.T) {
expErrCode: http.StatusBadRequest,
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 == "" {
Expand Down

0 comments on commit ae09482

Please sign in to comment.