You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
6.3 KiB
141 lines
6.3 KiB
1 year ago
|
package middleware
|
||
|
|
||
|
import (
|
||
|
"github.com/golang-jwt/jwt/v5"
|
||
|
"github.com/labstack/echo-jwt/v4"
|
||
|
"github.com/labstack/echo/v4"
|
||
|
)
|
||
|
|
||
|
// JWTConfig defines the config for JWT middleware.
|
||
|
type JWTConfig struct {
|
||
|
// Skipper defines a function to skip middleware.
|
||
|
Skipper Skipper
|
||
|
|
||
|
// BeforeFunc defines a function which is executed just before the middleware.
|
||
|
BeforeFunc BeforeFunc
|
||
|
|
||
|
// SuccessHandler defines a function which is executed for a valid token.
|
||
|
SuccessHandler func(c echo.Context)
|
||
|
|
||
|
// ErrorHandler defines a function which is executed when all lookups have been done and none of them passed Validator
|
||
|
// function. ErrorHandler is executed with last missing (ErrExtractionValueMissing) or an invalid key.
|
||
|
// It may be used to define a custom JWT error.
|
||
|
//
|
||
|
// Note: when error handler swallows the error (returns nil) middleware continues handler chain execution towards handler.
|
||
|
// This is useful in cases when portion of your site/api is publicly accessible and has extra features for authorized users
|
||
|
// In that case you can use ErrorHandler to set default public JWT token value to request and continue with handler chain.
|
||
|
ErrorHandler func(c echo.Context, err error) error
|
||
|
|
||
|
// ContinueOnIgnoredError allows the next middleware/handler to be called when ErrorHandler decides to
|
||
|
// ignore the error (by returning `nil`).
|
||
|
// This is useful when parts of your site/api allow public access and some authorized routes provide extra functionality.
|
||
|
// In that case you can use ErrorHandler to set a default public JWT token value in the request context
|
||
|
// and continue. Some logic down the remaining execution chain needs to check that (public) token value then.
|
||
|
ContinueOnIgnoredError bool
|
||
|
|
||
|
// Context key to store user information from the token into context.
|
||
|
// Optional. Default value "user".
|
||
|
ContextKey string
|
||
|
|
||
|
// Signing key to validate token.
|
||
|
// This is one of the three options to provide a token validation key.
|
||
|
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
|
||
|
// Required if neither user-defined KeyFunc nor SigningKeys is provided.
|
||
|
SigningKey any
|
||
|
|
||
|
// Map of signing keys to validate token with kid field usage.
|
||
|
// This is one of the three options to provide a token validation key.
|
||
|
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
|
||
|
// Required if neither user-defined KeyFunc nor SigningKey is provided.
|
||
|
SigningKeys map[string]any
|
||
|
|
||
|
// Signing method used to check the token's signing algorithm.
|
||
|
// Optional. Default value HS256.
|
||
|
SigningMethod string
|
||
|
|
||
|
// KeyFunc defines a user-defined function that supplies the public key for a token validation.
|
||
|
// The function shall take care of verifying the signing algorithm and selecting the proper key.
|
||
|
// A user-defined KeyFunc can be useful if tokens are issued by an external party.
|
||
|
// Used by default ParseTokenFunc implementation.
|
||
|
//
|
||
|
// When a user-defined KeyFunc is provided, SigningKey, SigningKeys, and SigningMethod are ignored.
|
||
|
// This is one of the three options to provide a token validation key.
|
||
|
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
|
||
|
// Required if neither SigningKeys nor SigningKey is provided.
|
||
|
// Not used if custom ParseTokenFunc is set.
|
||
|
// Default to an internal implementation verifying the signing algorithm and selecting the proper key.
|
||
|
KeyFunc jwt.Keyfunc
|
||
|
|
||
|
// TokenLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
|
||
|
// to extract token from the request.
|
||
|
// Optional. Default value "header:Authorization".
|
||
|
// Possible values:
|
||
|
// - "header:<name>" or "header:<name>:<cut-prefix>"
|
||
|
// `<cut-prefix>` is argument value to cut/trim prefix of the extracted value. This is useful if header
|
||
|
// value has static prefix like `Authorization: <auth-scheme> <authorisation-parameters>` where part that we
|
||
|
// want to cut is `<auth-scheme> ` note the space at the end.
|
||
|
// In case of JWT tokens `Authorization: Bearer <token>` prefix we cut is `Bearer `.
|
||
|
// If prefix is left empty the whole value is returned.
|
||
|
// - "query:<name>"
|
||
|
// - "param:<name>"
|
||
|
// - "cookie:<name>"
|
||
|
// - "form:<name>"
|
||
|
// Multiple sources example:
|
||
|
// - "header:Authorization:Bearer ,cookie:myowncookie"
|
||
|
TokenLookup string
|
||
|
|
||
|
// TokenLookupFuncs defines a list of user-defined functions that extract JWT token from the given context.
|
||
|
// This is one of the two options to provide a token extractor.
|
||
|
// The order of precedence is user-defined TokenLookupFuncs, and TokenLookup.
|
||
|
// You can also provide both if you want.
|
||
|
TokenLookupFuncs []ValuesExtractor
|
||
|
|
||
|
// ParseTokenFunc defines a user-defined function that parses token from given auth. Returns an error when token
|
||
|
// parsing fails or parsed token is invalid.
|
||
|
// Defaults to implementation using `github.com/golang-jwt/jwt` as JWT implementation library
|
||
|
ParseTokenFunc func(c echo.Context, auth string) (any, error)
|
||
|
|
||
|
// Claims are extendable claims data defining token content. Used by default ParseTokenFunc implementation.
|
||
|
// Not used if custom ParseTokenFunc is set.
|
||
|
// Optional. Defaults to function returning jwt.MapClaims
|
||
|
NewClaimsFunc func(c echo.Context) jwt.Claims
|
||
|
}
|
||
|
|
||
|
// Errors
|
||
|
var (
|
||
|
ErrJWTMissing = echojwt.ErrJWTMissing
|
||
|
ErrJWTInvalid = echojwt.ErrJWTInvalid
|
||
|
)
|
||
|
|
||
|
func (config *JWTConfig) ToMiddleware() echo.MiddlewareFunc {
|
||
|
return echojwt.WithConfig(echojwt.Config{
|
||
|
Skipper: config.Skipper,
|
||
|
BeforeFunc: config.BeforeFunc,
|
||
|
SuccessHandler: config.SuccessHandler,
|
||
|
ErrorHandler: config.ErrorHandler,
|
||
|
ContinueOnIgnoredError: config.ContinueOnIgnoredError,
|
||
|
ContextKey: config.ContextKey,
|
||
|
SigningKey: config.SigningKey,
|
||
|
SigningKeys: config.SigningKeys,
|
||
|
SigningMethod: config.SigningMethod,
|
||
|
KeyFunc: config.KeyFunc,
|
||
|
TokenLookup: config.TokenLookup,
|
||
|
TokenLookupFuncs: config.TokenLookupFuncs,
|
||
|
ParseTokenFunc: config.ParseTokenFunc,
|
||
|
NewClaimsFunc: nil,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// JWT returns a JSON Web Token (JWT) auth middleware.
|
||
|
//
|
||
|
// For valid token, it sets the user in context and calls next handler.
|
||
|
// For invalid token, it returns "401 - Unauthorized" error.
|
||
|
// For missing token, it returns "400 - Bad Request" error.
|
||
|
//
|
||
|
// See: https://jwt.io/introduction
|
||
|
// See `JWTConfig.TokenLookup`
|
||
|
// See https://github.com/labstack/echo-jwt
|
||
|
func JWT(signingKey any) echo.MiddlewareFunc {
|
||
|
return echojwt.JWT(signingKey)
|
||
|
}
|