Skip to content

Commit

Permalink
more context for JWT middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
hummerdmag committed Sep 10, 2024
1 parent ecb753d commit d458d14
Showing 1 changed file with 60 additions and 10 deletions.
70 changes: 60 additions & 10 deletions jwt/middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,59 @@ const (
// next is a reference to the next handler in the handler chain
type Handler func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)

// ErrorHandler interface for handling error from middleware
// rw - readwriter to write error to (JSON, HTML or other error to the client)
// errorType - error returned from middleware, you can get description by calling errorType.Description()
// status - http status code
type ErrorHandler interface {
Error(rw http.ResponseWriter, errorType Error, status int, description string)
// JWTErrorHandlerContext is a context for handling errors from JWTv2 middleware.
type JWTErrorHandlerContext struct {
// ResponseWriter is an http.ResponseWriter to write error to (JSON, HTML or other error to the client).
ResponseWriter http.ResponseWriter
// Request is an http.Request to get more information about the request.
Request *http.Request
// ErrorType is an error returned from middleware, you can get description by calling errorType.Description().
ErrorType Error
// Status is an http status code.
Status int
// Description is a description of the error.
Description string
}

// JWT returns middleware function you can use to handle JWT token auth
func JWT(eh ErrorHandler, c validator.Config) (Handler, error) {
// JWTErrorHandler is an interface for handling errors from JWTv2 middleware.
type JWTErrorHandler interface {
Error(errContext *JWTErrorHandlerContext)
}

// JWTv2 returns middleware function you can use to handle JWT token auth.
// It extracts token from Authorization header, validates it and stores the parsed token in the context,
// use TokenFromContext to get token from context.
// It uses JWTErrorHandler to handle errors.
func JWTv2(eh JWTErrorHandler, c validator.Config) (Handler, error) {
v, err := validator.NewValidatorWithConfig(c)
if err != nil {
return nil, err
}

reportError := func(rw http.ResponseWriter, r *http.Request, errType Error, status int, description string) {
ec := &JWTErrorHandlerContext{
ResponseWriter: rw,
Request: r,
ErrorType: errType,
Status: status,
Description: description,
}

eh.Error(ec)
}

// Middleware middleware functions extracts token and validates it and store the parsed token in the context
return func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
tokenBytes := jwt.ExtractTokenFromBearerHeader(r.Header.Get(AuthorizationHeaderKey))
if tokenBytes == nil {
eh.Error(rw, ErrorTokenIsEmpty, http.StatusBadRequest, "")
reportError(rw, r, ErrorTokenIsEmpty, http.StatusBadRequest, "")
return
}
tokenString := string(tokenBytes)

token, err := v.ValidateString(tokenString)
if err != nil {
eh.Error(rw, ErrorTokenIsInvalid, http.StatusBadRequest, err.Error())
reportError(rw, r, ErrorTokenIsInvalid, http.StatusBadRequest, err.Error())
return
}

Expand All @@ -62,6 +89,29 @@ func JWT(eh ErrorHandler, c validator.Config) (Handler, error) {
}, nil
}

// ErrorHandler interface for handling error from middleware
// rw - http.ResponseWriter to write error to (JSON, HTML or other error to the client)
// errorType - error returned from middleware, you can get description by calling errorType.Description()
// status - http status code
type ErrorHandler interface {
Error(rw http.ResponseWriter, errorType Error, status int, description string)
}

// jwtErrorHandler is a wrapper for ErrorHandler to make it compatible with JWTErrorHandler
type jwtErrorHandler struct {
eh ErrorHandler
}

func (j jwtErrorHandler) Error(errContext *JWTErrorHandlerContext) {
j.eh.Error(errContext.ResponseWriter, errContext.ErrorType, errContext.Status, errContext.Description)
}

// JWT returns middleware function you can use to handle JWT token auth
// Deprecated: use JWT instead
func JWT(eh ErrorHandler, c validator.Config) (Handler, error) {
return JWTv2(jwtErrorHandler{eh}, c)
}

// TokenFromContext returns token from request context.
// Or nil if there is no token in context.
func TokenFromContext(ctx context.Context) model.Token {
Expand Down

0 comments on commit d458d14

Please sign in to comment.