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:
parent
bb6baa2088
commit
ae09482493
@ -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 == "" {
|
||||||
|
Loading…
Reference in New Issue
Block a user