JwtHandler is a middleware that checks for a JWT token in the cookie or the authorization header. If the token is found, it is validated and the claims
(ac Auth)
| 18 | // JwtHandler is a middleware that checks for a JWT token in the cookie or the |
| 19 | // authorization header. If the token is found, it is validated and the claims |
| 20 | func JwtHandler(ac Auth) (HandlerFunc, error) { |
| 21 | jwtProvider, err := provider.NewProvider(ac.JWT) |
| 22 | if err != nil { |
| 23 | return nil, err |
| 24 | } |
| 25 | |
| 26 | cookie := ac.Cookie |
| 27 | |
| 28 | return func(w http.ResponseWriter, r *http.Request) (context.Context, error) { |
| 29 | var tok string |
| 30 | |
| 31 | if cookie != "" { |
| 32 | if ck, err := r.Cookie(cookie); err == nil && len(ck.Value) != 0 { |
| 33 | tok = ck.Value |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | if tok == "" { |
| 38 | if ah := r.Header.Get(authHeader); len(ah) > 7 && strings.HasPrefix(ah, "Bearer ") { |
| 39 | tok = ah[7:] |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | if tok == "" { |
| 44 | return nil, fmt.Errorf("no jwt token found in cookie or authorization header") |
| 45 | } |
| 46 | |
| 47 | keyFunc := jwtProvider.KeyFunc() |
| 48 | token, err := jwt.ParseWithClaims(tok, jwt.MapClaims{}, keyFunc) // jwt.MapClaims is already passed by reference |
| 49 | if err != nil { |
| 50 | return nil, err |
| 51 | } |
| 52 | |
| 53 | if claims, ok := token.Claims.(jwt.MapClaims); ok { |
| 54 | ctx := r.Context() |
| 55 | |
| 56 | if !jwtProvider.VerifyAudience(claims) { |
| 57 | return nil, fmt.Errorf("invalid aud claim") |
| 58 | } |
| 59 | |
| 60 | if !jwtProvider.VerifyIssuer(claims) { |
| 61 | return nil, fmt.Errorf("invalid iss claim") |
| 62 | } |
| 63 | |
| 64 | ctx, err = jwtProvider.SetContextValues(ctx, claims) |
| 65 | if err != nil { |
| 66 | return ctx, err |
| 67 | } |
| 68 | |
| 69 | // Attach optional identity claims for audit logging. These are |
| 70 | // strictly informational — the role / authorization decision is |
| 71 | // driven by sub / role. |
| 72 | if email, ok := claims["email"].(string); ok && email != "" { |
| 73 | ctx = context.WithValue(ctx, userEmailKey, email) |
| 74 | } |
| 75 | if name, ok := claims["name"].(string); ok && name != "" { |
| 76 | ctx = context.WithValue(ctx, userNameKey, name) |
| 77 | } |
no test coverage detected