diff --git a/jwt/middleware/middleware.go b/jwt/middleware/middleware.go index 547a170d..5ce21a14 100644 --- a/jwt/middleware/middleware.go +++ b/jwt/middleware/middleware.go @@ -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 } @@ -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 {