Codebase list golang-github-go-kit-kit / a5c7103
Fix typo in jwt package (#1070) * Fix typo in jwt package * change JWTTokenContextKey to JWTContextKey * revise errors as well as comments * Revision of typo fixing in jwt package * revert the API identifier to its previous value * add JWTTokenContextKey side by side of JWTContextKey for historical compatibility * Fixed a typo in JWT package (#1071) * define JWTContextKey as a new constant * mark JWTTokenContextKey as a deprecated constant * revise corresponding error messages * Fixed a typo in JWT package (#1071) * define JWTContextKey as a new constant * mark JWTTokenContextKey as a deprecated constant * revise corresponding error messages Co-authored-by: Amid <amid.dev@protonmail.com> Amid authored 2 years ago GitHub committed 2 years ago
5 changed file(s) with 52 addition(s) and 48 deletion(s). Raw diff Collapse all Expand all
66
77 NewParser takes a key function and an expected signing method and returns an
88 `endpoint.Middleware`. The middleware will parse a token passed into the
9 context via the `jwt.JWTTokenContextKey`. If the token is valid, any claims
9 context via the `jwt.JWTContextKey`. If the token is valid, any claims
1010 will be added to the context via the `jwt.JWTClaimsContextKey`.
1111
1212 ```go
2929
3030 NewSigner takes a JWT key ID header, the signing key, signing method, and a
3131 claims object. It returns an `endpoint.Middleware`. The middleware will build
32 the token string and add it to the context via the `jwt.JWTTokenContextKey`.
32 the token string and add it to the context via the `jwt.JWTContextKey`.
3333
3434 ```go
3535 import (
1111 type contextKey string
1212
1313 const (
14 // JWTTokenContextKey holds the key used to store a JWT Token in the
15 // context.
16 JWTTokenContextKey contextKey = "JWTToken"
14 // JWTContextKey holds the key used to store a JWT in the context.
15 JWTContextKey contextKey = "JWTToken"
16
17 // JWTTokenContextKey is an alias for JWTContextKey.
18 //
19 // Deprecated: prefer JWTContextKey.
20 JWTTokenContextKey = JWTContextKey
1721
1822 // JWTClaimsContextKey holds the key used to store the JWT Claims in the
1923 // context.
2630 ErrTokenContextMissing = errors.New("token up for parsing was not passed through the context")
2731
2832 // ErrTokenInvalid denotes a token was not able to be validated.
29 ErrTokenInvalid = errors.New("JWT Token was invalid")
33 ErrTokenInvalid = errors.New("JWT was invalid")
3034
3135 // ErrTokenExpired denotes a token's expire header (exp) has since passed.
32 ErrTokenExpired = errors.New("JWT Token is expired")
36 ErrTokenExpired = errors.New("JWT is expired")
3337
34 // ErrTokenMalformed denotes a token was not formatted as a JWT token.
35 ErrTokenMalformed = errors.New("JWT Token is malformed")
38 // ErrTokenMalformed denotes a token was not formatted as a JWT.
39 ErrTokenMalformed = errors.New("JWT is malformed")
3640
3741 // ErrTokenNotActive denotes a token's not before header (nbf) is in the
3842 // future.
4347 ErrUnexpectedSigningMethod = errors.New("unexpected signing method")
4448 )
4549
46 // NewSigner creates a new JWT token generating middleware, specifying key ID,
50 // NewSigner creates a new JWT generating middleware, specifying key ID,
4751 // signing string, signing method and the claims you would like it to contain.
4852 // Tokens are signed with a Key ID header (kid) which is useful for determining
4953 // the key to use for parsing. Particularly useful for clients.
5862 if err != nil {
5963 return nil, err
6064 }
61 ctx = context.WithValue(ctx, JWTTokenContextKey, tokenString)
65 ctx = context.WithValue(ctx, JWTContextKey, tokenString)
6266
6367 return next(ctx, request)
6468 }
8185 return &jwt.StandardClaims{}
8286 }
8387
84 // NewParser creates a new JWT token parsing middleware, specifying a
88 // NewParser creates a new JWT parsing middleware, specifying a
8589 // jwt.Keyfunc interface, the signing method and the claims type to be used. NewParser
8690 // adds the resulting claims to endpoint context or returns error on invalid token.
8791 // Particularly useful for servers.
8993 return func(next endpoint.Endpoint) endpoint.Endpoint {
9094 return func(ctx context.Context, request interface{}) (response interface{}, err error) {
9195 // tokenString is stored in the context from the transport handlers.
92 tokenString, ok := ctx.Value(JWTTokenContextKey).(string)
96 tokenString, ok := ctx.Value(JWTContextKey).(string)
9397 if !ok {
9498 return nil, ErrTokenContextMissing
9599 }
4343 t.Fatalf("Signer returned error: %s", err)
4444 }
4545
46 token, ok := ctx.(context.Context).Value(JWTTokenContextKey).(string)
46 token, ok := ctx.(context.Context).Value(JWTContextKey).(string)
4747 if !ok {
4848 t.Fatal("Token did not exist in context")
4949 }
5050
5151 if token != expectedKey {
52 t.Fatalf("JWT tokens did not match: expecting %s got %s", expectedKey, token)
52 t.Fatalf("JWTs did not match: expecting %s got %s", expectedKey, token)
5353 }
5454 }
5555
8686 }
8787
8888 // Invalid Token is passed into the parser
89 ctx := context.WithValue(context.Background(), JWTTokenContextKey, invalidKey)
89 ctx := context.WithValue(context.Background(), JWTContextKey, invalidKey)
9090 _, err = parser(ctx, struct{}{})
9191 if err == nil {
9292 t.Error("Parser should have returned an error")
9494
9595 // Invalid Method is used in the parser
9696 badParser := NewParser(keys, invalidMethod, MapClaimsFactory)(e)
97 ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
97 ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
9898 _, err = badParser(ctx, struct{}{})
9999 if err == nil {
100100 t.Error("Parser should have returned an error")
110110 }
111111
112112 badParser = NewParser(invalidKeys, method, MapClaimsFactory)(e)
113 ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
113 ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
114114 _, err = badParser(ctx, struct{}{})
115115 if err == nil {
116116 t.Error("Parser should have returned an error")
117117 }
118118
119119 // Correct token is passed into the parser
120 ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
120 ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
121121 ctx1, err := parser(ctx, struct{}{})
122122 if err != nil {
123123 t.Fatalf("Parser returned error: %s", err)
134134
135135 // Test for malformed token error response
136136 parser = NewParser(keys, method, StandardClaimsFactory)(e)
137 ctx = context.WithValue(context.Background(), JWTTokenContextKey, malformedKey)
137 ctx = context.WithValue(context.Background(), JWTContextKey, malformedKey)
138138 ctx1, err = parser(ctx, struct{}{})
139139 if want, have := ErrTokenMalformed, err; want != have {
140140 t.Fatalf("Expected %+v, got %+v", want, have)
147147 if err != nil {
148148 t.Fatalf("Unable to Sign Token: %+v", err)
149149 }
150 ctx = context.WithValue(context.Background(), JWTTokenContextKey, token)
150 ctx = context.WithValue(context.Background(), JWTContextKey, token)
151151 ctx1, err = parser(ctx, struct{}{})
152152 if want, have := ErrTokenExpired, err; want != have {
153153 t.Fatalf("Expected %+v, got %+v", want, have)
160160 if err != nil {
161161 t.Fatalf("Unable to Sign Token: %+v", err)
162162 }
163 ctx = context.WithValue(context.Background(), JWTTokenContextKey, token)
163 ctx = context.WithValue(context.Background(), JWTContextKey, token)
164164 ctx1, err = parser(ctx, struct{}{})
165165 if want, have := ErrTokenNotActive, err; want != have {
166166 t.Fatalf("Expected %+v, got %+v", want, have)
168168
169169 // test valid standard claims token
170170 parser = NewParser(keys, method, StandardClaimsFactory)(e)
171 ctx = context.WithValue(context.Background(), JWTTokenContextKey, standardSignedKey)
171 ctx = context.WithValue(context.Background(), JWTContextKey, standardSignedKey)
172172 ctx1, err = parser(ctx, struct{}{})
173173 if err != nil {
174174 t.Fatalf("Parser returned error: %s", err)
183183
184184 // test valid customized claims token
185185 parser = NewParser(keys, method, func() jwt.Claims { return &customClaims{} })(e)
186 ctx = context.WithValue(context.Background(), JWTTokenContextKey, customSignedKey)
186 ctx = context.WithValue(context.Background(), JWTContextKey, customSignedKey)
187187 ctx1, err = parser(ctx, struct{}{})
188188 if err != nil {
189189 t.Fatalf("Parser returned error: %s", err)
204204 var (
205205 kf = func(token *jwt.Token) (interface{}, error) { return []byte("secret"), nil }
206206 e = NewParser(kf, jwt.SigningMethodHS256, MapClaimsFactory)(endpoint.Nop)
207 key = JWTTokenContextKey
207 key = JWTContextKey
208208 val = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZCIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ28ta2l0In0.14M2VmYyApdSlV_LZ88ajjwuaLeIFplB8JpyNy0A19E"
209209 ctx = context.WithValue(context.Background(), key, val)
210210 )
2525 return ctx
2626 }
2727
28 return context.WithValue(ctx, JWTTokenContextKey, token)
28 return context.WithValue(ctx, JWTContextKey, token)
2929 }
3030 }
3131
3333 // useful for clients.
3434 func ContextToHTTP() http.RequestFunc {
3535 return func(ctx context.Context, r *stdhttp.Request) context.Context {
36 token, ok := ctx.Value(JWTTokenContextKey).(string)
36 token, ok := ctx.Value(JWTContextKey).(string)
3737 if ok {
3838 r.Header.Add("Authorization", generateAuthHeaderFromToken(token))
3939 }
5353
5454 token, ok := extractTokenFromAuthHeader(authHeader[0])
5555 if ok {
56 ctx = context.WithValue(ctx, JWTTokenContextKey, token)
56 ctx = context.WithValue(ctx, JWTContextKey, token)
5757 }
5858
5959 return ctx
6464 // useful for clients.
6565 func ContextToGRPC() grpc.ClientRequestFunc {
6666 return func(ctx context.Context, md *metadata.MD) context.Context {
67 token, ok := ctx.Value(JWTTokenContextKey).(string)
67 token, ok := ctx.Value(JWTContextKey).(string)
6868 if ok {
6969 // capital "Key" is illegal in HTTP/2.
7070 (*md)["authorization"] = []string{generateAuthHeaderFromToken(token)}
1414 // When the header doesn't exist
1515 ctx := reqFunc(context.Background(), &http.Request{})
1616
17 if ctx.Value(JWTTokenContextKey) != nil {
17 if ctx.Value(JWTContextKey) != nil {
1818 t.Error("Context shouldn't contain the encoded JWT")
1919 }
2020
2323 header.Set("Authorization", "no expected auth header format value")
2424 ctx = reqFunc(context.Background(), &http.Request{Header: header})
2525
26 if ctx.Value(JWTTokenContextKey) != nil {
26 if ctx.Value(JWTContextKey) != nil {
2727 t.Error("Context shouldn't contain the encoded JWT")
2828 }
2929
3131 header.Set("Authorization", generateAuthHeaderFromToken(signedKey))
3232 ctx = reqFunc(context.Background(), &http.Request{Header: header})
3333
34 token := ctx.Value(JWTTokenContextKey).(string)
34 token := ctx.Value(JWTContextKey).(string)
3535 if token != signedKey {
3636 t.Errorf("Context doesn't contain the expected encoded token value; expected: %s, got: %s", signedKey, token)
3737 }
4040 func TestContextToHTTP(t *testing.T) {
4141 reqFunc := ContextToHTTP()
4242
43 // No JWT Token is passed in the context
43 // No JWT is passed in the context
4444 ctx := context.Background()
4545 r := http.Request{}
4646 reqFunc(ctx, &r)
5050 t.Error("authorization key should not exist in metadata")
5151 }
5252
53 // Correct JWT Token is passed in the context
54 ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
53 // Correct JWT is passed in the context
54 ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
5555 r = http.Request{Header: http.Header{}}
5656 reqFunc(ctx, &r)
5757
5959 expected := generateAuthHeaderFromToken(signedKey)
6060
6161 if token != expected {
62 t.Errorf("Authorization header does not contain the expected JWT token; expected %s, got %s", expected, token)
62 t.Errorf("Authorization header does not contain the expected JWT; expected %s, got %s", expected, token)
6363 }
6464 }
6565
6969
7070 // No Authorization header is passed
7171 ctx := reqFunc(context.Background(), md)
72 token := ctx.Value(JWTTokenContextKey)
72 token := ctx.Value(JWTContextKey)
7373 if token != nil {
74 t.Error("Context should not contain a JWT Token")
74 t.Error("Context should not contain a JWT")
7575 }
7676
7777 // Invalid Authorization header is passed
7878 md["authorization"] = []string{fmt.Sprintf("%s", signedKey)}
7979 ctx = reqFunc(context.Background(), md)
80 token = ctx.Value(JWTTokenContextKey)
80 token = ctx.Value(JWTContextKey)
8181 if token != nil {
82 t.Error("Context should not contain a JWT Token")
82 t.Error("Context should not contain a JWT")
8383 }
8484
8585 // Authorization header is correct
8686 md["authorization"] = []string{fmt.Sprintf("Bearer %s", signedKey)}
8787 ctx = reqFunc(context.Background(), md)
88 token, ok := ctx.Value(JWTTokenContextKey).(string)
88 token, ok := ctx.Value(JWTContextKey).(string)
8989 if !ok {
90 t.Fatal("JWT Token not passed to context correctly")
90 t.Fatal("JWT not passed to context correctly")
9191 }
9292
9393 if token != signedKey {
94 t.Errorf("JWT tokens did not match: expecting %s got %s", signedKey, token)
94 t.Errorf("JWTs did not match: expecting %s got %s", signedKey, token)
9595 }
9696 }
9797
9898 func TestContextToGRPC(t *testing.T) {
9999 reqFunc := ContextToGRPC()
100100
101 // No JWT Token is passed in the context
101 // No JWT is passed in the context
102102 ctx := context.Background()
103103 md := metadata.MD{}
104104 reqFunc(ctx, &md)
108108 t.Error("authorization key should not exist in metadata")
109109 }
110110
111 // Correct JWT Token is passed in the context
112 ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
111 // Correct JWT is passed in the context
112 ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
113113 md = metadata.MD{}
114114 reqFunc(ctx, &md)
115115
116116 token, ok := md["authorization"]
117117 if !ok {
118 t.Fatal("JWT Token not passed to metadata correctly")
118 t.Fatal("JWT not passed to metadata correctly")
119119 }
120120
121121 if token[0] != generateAuthHeaderFromToken(signedKey) {
122 t.Errorf("JWT tokens did not match: expecting %s got %s", signedKey, token[0])
122 t.Errorf("JWTs did not match: expecting %s got %s", signedKey, token[0])
123123 }
124124 }