Added private error handler middleware
This commit is contained in:
		
							parent
							
								
									537b1ab886
								
							
						
					
					
						commit
						61507766fe
					
				
					 1 changed files with 50 additions and 23 deletions
				
			
		
							
								
								
									
										73
									
								
								jwt.go
									
										
									
									
									
								
							
							
						
						
									
										73
									
								
								jwt.go
									
										
									
									
									
								
							|  | @ -69,18 +69,33 @@ func NewMiddleware(c *Config) (*JWTMiddleware, error) { | |||
| 	return m, nil | ||||
| } | ||||
| 
 | ||||
| type jwtError struct { | ||||
| 	status  int | ||||
| 	err     error | ||||
| 	message string | ||||
| } | ||||
| 
 | ||||
| type errorHandler func(http.ResponseWriter, *http.Request) *jwtError | ||||
| 
 | ||||
| func (e errorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||||
| 	if err := e(w, r); err != nil { | ||||
| 		if err.message != "" { | ||||
| 			log.Printf("error (%v) while %s", err.err, err.message) | ||||
| 		} | ||||
| 		http.Error(w, err.err.Error(), err.status) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (m *JWTMiddleware) Secure(h http.Handler, v VerifyClaimsFunc) http.Handler { | ||||
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 	secureHandler := func(w http.ResponseWriter, r *http.Request) *jwtError { | ||||
| 		authHeader := r.Header.Get("Authorization") | ||||
| 		if authHeader == "" { | ||||
| 			http.Error(w, ErrMissingToken.Error(), http.StatusUnauthorized) | ||||
| 			return | ||||
| 			return &jwtError{status: http.StatusUnauthorized, err: ErrMissingToken} | ||||
| 		} | ||||
| 		token := strings.Split(authHeader, " ")[1] | ||||
| 		tokenParts := strings.Split(token, ".") | ||||
| 		if len(tokenParts) != 3 { | ||||
| 			http.Error(w, ErrMalformedToken.Error(), http.StatusUnauthorized) | ||||
| 			return | ||||
| 			return &jwtError{status: http.StatusUnauthorized, err: ErrMalformedToken} | ||||
| 		} | ||||
| 
 | ||||
| 		// First, verify JOSE header | ||||
|  | @ -90,15 +105,19 @@ func (m *JWTMiddleware) Secure(h http.Handler, v VerifyClaimsFunc) http.Handler | |||
| 		} | ||||
| 		header, err := decode(tokenParts[0]) | ||||
| 		if err != nil { | ||||
| 			log.Printf("error (%v) while decoding header (%v)", err, tokenParts[0]) | ||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||
| 			return | ||||
| 			return &jwtError{ | ||||
| 				status:  http.StatusInternalServerError, | ||||
| 				err:     err, | ||||
| 				message: fmt.Sprintf("decoding header (%v)", tokenParts[0]), | ||||
| 			} | ||||
| 		} | ||||
| 		err = json.Unmarshal(header, &t) | ||||
| 		if err != nil { | ||||
| 			log.Printf("error (%v) while unmarshalling header (%s)", err, header) | ||||
| 			http.Error(w, ErrMalformedToken.Error(), http.StatusInternalServerError) | ||||
| 			return | ||||
| 			return &jwtError{ | ||||
| 				status:  http.StatusInternalServerError, | ||||
| 				err:     ErrMalformedToken, | ||||
| 				message: fmt.Sprintf("unmarshalling header (%s)", header), | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Then, verify signature | ||||
|  | @ -107,32 +126,40 @@ func (m *JWTMiddleware) Secure(h http.Handler, v VerifyClaimsFunc) http.Handler | |||
| 		mac.Write(message) | ||||
| 		expectedMac, err := encode(mac.Sum(nil)) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 			return | ||||
| 			return &jwtError{status: http.StatusInternalServerError, err: err} | ||||
| 		} | ||||
| 		if !hmac.Equal([]byte(tokenParts[2]), []byte(expectedMac)) { | ||||
| 			log.Printf("invalid signature: %v", tokenParts[2]) | ||||
| 			http.Error(w, ErrInvalidSignature.Error(), http.StatusUnauthorized) | ||||
| 			return | ||||
| 			return &jwtError{ | ||||
| 				status:  http.StatusUnauthorized, | ||||
| 				err:     ErrInvalidSignature, | ||||
| 				message: fmt.Sprintf("checking signature (%v)", tokenParts[2]), | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Finally, check claims | ||||
| 		claimSet, err := decode(tokenParts[1]) | ||||
| 		if err != nil { | ||||
| 			log.Printf("error (%v) while decoding claims", err) | ||||
| 			http.Error(w, ErrDecoding.Error(), http.StatusInternalServerError) | ||||
| 			return | ||||
| 			return &jwtError{ | ||||
| 				status:  http.StatusInternalServerError, | ||||
| 				err:     ErrDecoding, | ||||
| 				message: "decoding claims", | ||||
| 			} | ||||
| 		} | ||||
| 		err = v(claimSet) | ||||
| 		if err != nil { | ||||
| 			log.Printf("claims handler error: %v", err) | ||||
| 			http.Error(w, err.Error(), http.StatusUnauthorized) | ||||
| 			return | ||||
| 			return &jwtError{ | ||||
| 				status:  http.StatusUnauthorized, | ||||
| 				err:     err, | ||||
| 				message: "handling claims callback", | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// If we make it this far, process the downstream handler | ||||
| 		h.ServeHTTP(w, r) | ||||
| 	}) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return errorHandler(secureHandler) | ||||
| } | ||||
| 
 | ||||
| func (m *JWTMiddleware) GenerateToken(w http.ResponseWriter, r *http.Request) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Matthew Dillon
						Matthew Dillon