From 8000c6240bea4385432a0ce923d4db0f66bff028 Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 15:16:34 -0700 Subject: [PATCH 1/8] Added map function --- basculehttp/tokenFactory.go | 8 ++++++-- jws.go | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/basculehttp/tokenFactory.go b/basculehttp/tokenFactory.go index e535e08..8753f2c 100644 --- a/basculehttp/tokenFactory.go +++ b/basculehttp/tokenFactory.go @@ -117,12 +117,16 @@ func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Requ return nil, ErrorInvalidToken } - claims, ok := jwsToken.Claims.(*jwt.MapClaims) + claims, ok := jwsToken.Claims.(*bascule.ClaimsWithLeeway) if !ok { return nil, emperror.Wrap(ErrorUnexpectedClaims, "failed to parse JWS") } - payload := bascule.Attributes(*claims) + claimsMap, err := claims.GetMap() + if err != nil { + return nil, emperror.WrapWith(err, "failed to get map of claims", "claims struct", claims) + } + payload := bascule.Attributes(claimsMap) principal, ok := payload[jwtPrincipalKey].(string) if !ok { diff --git a/jws.go b/jws.go index 92485af..f0984bf 100644 --- a/jws.go +++ b/jws.go @@ -1,6 +1,7 @@ package bascule import ( + "encoding/json" "errors" jwt "github.com/dgrijalva/jwt-go" @@ -65,3 +66,17 @@ func (c *ClaimsWithLeeway) Valid() error { return vErr } + +// GetMap returns a map of string to interfaces of the values in the ClaimsWithLeeway +func (c *ClaimsWithLeeway) GetMap() (map[string]interface{}, error) { + var finalMap map[string]interface{} + inrec, err := json.Marshal(c) + if err != nil { + return nil, err + } + err = json.Unmarshal(inrec, &finalMap) + if err != nil { + return nil, err + } + return finalMap, nil +} From f637225e30abe6ae5aa99113c41c688b20242855 Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 15:53:43 -0700 Subject: [PATCH 2/8] Improved errors --- basculehttp/constructor.go | 6 ++++-- basculehttp/tokenFactory.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/basculehttp/constructor.go b/basculehttp/constructor.go index bc5c380..6a26b75 100644 --- a/basculehttp/constructor.go +++ b/basculehttp/constructor.go @@ -8,7 +8,9 @@ import ( "net/textproto" "strings" + "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" + "github.com/goph/emperror" "github.com/xmidt-org/bascule" ) @@ -67,7 +69,7 @@ func (c *constructor) decorate(next http.Handler) http.Handler { ctx := request.Context() token, err := tf.ParseAndValidate(ctx, request, key, authorization[i+len(c.headerDelimiter):]) if err != nil { - c.error(logger, ParseFailed, authorization, err) + c.error(logger, ParseFailed, authorization, emperror.Wrap(err, "failed to parse and validate token")) WriteResponse(response, http.StatusForbidden, err) return } @@ -91,7 +93,7 @@ func (c *constructor) decorate(next http.Handler) http.Handler { } func (c *constructor) error(logger bascule.Logger, e ErrorResponseReason, auth string, err error) { - logger.Log(level.Key(), level.ErrorValue(), bascule.ErrorKey, err.Error(), "auth", auth) + log.With(logger, emperror.Context(err)...).Log(level.Key(), level.ErrorValue(), bascule.ErrorKey, err.Error(), "auth", auth) c.onErrorResponse(e, err) } diff --git a/basculehttp/tokenFactory.go b/basculehttp/tokenFactory.go index 8753f2c..63cff13 100644 --- a/basculehttp/tokenFactory.go +++ b/basculehttp/tokenFactory.go @@ -130,7 +130,7 @@ func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Requ principal, ok := payload[jwtPrincipalKey].(string) if !ok { - return nil, ErrorUnexpectedPrincipal + return nil, emperror.WrapWith(ErrorUnexpectedPrincipal, "failed to get and convert principal", "principal", payload[jwtPrincipalKey]) } return bascule.NewToken("jwt", principal, payload), nil From 1d75b7337dc2bf4b1706d44fbe4467eb4a338bf4 Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 16:07:14 -0700 Subject: [PATCH 3/8] Adding full payload for debugging --- basculehttp/tokenFactory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basculehttp/tokenFactory.go b/basculehttp/tokenFactory.go index 63cff13..ddee6d5 100644 --- a/basculehttp/tokenFactory.go +++ b/basculehttp/tokenFactory.go @@ -130,7 +130,7 @@ func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Requ principal, ok := payload[jwtPrincipalKey].(string) if !ok { - return nil, emperror.WrapWith(ErrorUnexpectedPrincipal, "failed to get and convert principal", "principal", payload[jwtPrincipalKey]) + return nil, emperror.WrapWith(ErrorUnexpectedPrincipal, "failed to get and convert principal", "principal", payload[jwtPrincipalKey], "payload", payload) } return bascule.NewToken("jwt", principal, payload), nil From 0e67a21c18b94f41cbbb04c42f7d216a1f698b4b Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 16:14:02 -0700 Subject: [PATCH 4/8] Change MapClaims to StandardClaims --- basculehttp/tokenFactory.go | 5 ++--- jws.go | 2 +- jws_test.go | 2 -- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/basculehttp/tokenFactory.go b/basculehttp/tokenFactory.go index ddee6d5..c47d5cf 100644 --- a/basculehttp/tokenFactory.go +++ b/basculehttp/tokenFactory.go @@ -26,7 +26,7 @@ var ( ErrorUnexpectedPayload = errors.New("payload isn't a map of strings to interfaces") ErrorUnexpectedPrincipal = errors.New("principal isn't a string") ErrorInvalidToken = errors.New("token isn't valid") - ErrorUnexpectedClaims = errors.New("claims wasn't MapClaims as expected") + ErrorUnexpectedClaims = errors.New("claims wasn't ClaimsWithLeeway as expected") ) // TokenFactory is a strategy interface responsible for creating and validating @@ -105,8 +105,7 @@ func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Requ } leewayclaims := bascule.ClaimsWithLeeway{ - MapClaims: make(jwt.MapClaims), - Leeway: btf.Leeway, + Leeway: btf.Leeway, } jwsToken, err := btf.Parser.ParseJWT(value, &leewayclaims, keyfunc) diff --git a/jws.go b/jws.go index f0984bf..ae39eb6 100644 --- a/jws.go +++ b/jws.go @@ -27,7 +27,7 @@ func (parser defaultJWTParser) ParseJWT(token string, claims jwt.Claims, parseFu var DefaultJWTParser JWTParser = defaultJWTParser{} type ClaimsWithLeeway struct { - jwt.MapClaims + jwt.StandardClaims Leeway Leeway } diff --git a/jws_test.go b/jws_test.go index 7fa2d69..c4197dc 100644 --- a/jws_test.go +++ b/jws_test.go @@ -3,14 +3,12 @@ package bascule import ( "testing" - jwt "github.com/dgrijalva/jwt-go" "github.com/stretchr/testify/assert" ) func TestValid(t *testing.T) { assert := assert.New(t) claims := ClaimsWithLeeway{ - MapClaims: make(jwt.MapClaims), Leeway: Leeway{ EXP: 5, NBF: 5, From 9f18d3f56439faa69af288f89a696acf5b86dd95 Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 16:27:40 -0700 Subject: [PATCH 5/8] Revert "Change MapClaims to StandardClaims" This reverts commit 0e67a21c18b94f41cbbb04c42f7d216a1f698b4b. --- basculehttp/tokenFactory.go | 5 +++-- jws.go | 2 +- jws_test.go | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/basculehttp/tokenFactory.go b/basculehttp/tokenFactory.go index c47d5cf..ddee6d5 100644 --- a/basculehttp/tokenFactory.go +++ b/basculehttp/tokenFactory.go @@ -26,7 +26,7 @@ var ( ErrorUnexpectedPayload = errors.New("payload isn't a map of strings to interfaces") ErrorUnexpectedPrincipal = errors.New("principal isn't a string") ErrorInvalidToken = errors.New("token isn't valid") - ErrorUnexpectedClaims = errors.New("claims wasn't ClaimsWithLeeway as expected") + ErrorUnexpectedClaims = errors.New("claims wasn't MapClaims as expected") ) // TokenFactory is a strategy interface responsible for creating and validating @@ -105,7 +105,8 @@ func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Requ } leewayclaims := bascule.ClaimsWithLeeway{ - Leeway: btf.Leeway, + MapClaims: make(jwt.MapClaims), + Leeway: btf.Leeway, } jwsToken, err := btf.Parser.ParseJWT(value, &leewayclaims, keyfunc) diff --git a/jws.go b/jws.go index ae39eb6..f0984bf 100644 --- a/jws.go +++ b/jws.go @@ -27,7 +27,7 @@ func (parser defaultJWTParser) ParseJWT(token string, claims jwt.Claims, parseFu var DefaultJWTParser JWTParser = defaultJWTParser{} type ClaimsWithLeeway struct { - jwt.StandardClaims + jwt.MapClaims Leeway Leeway } diff --git a/jws_test.go b/jws_test.go index c4197dc..7fa2d69 100644 --- a/jws_test.go +++ b/jws_test.go @@ -3,12 +3,14 @@ package bascule import ( "testing" + jwt "github.com/dgrijalva/jwt-go" "github.com/stretchr/testify/assert" ) func TestValid(t *testing.T) { assert := assert.New(t) claims := ClaimsWithLeeway{ + MapClaims: make(jwt.MapClaims), Leeway: Leeway{ EXP: 5, NBF: 5, From 20c5c52cfd224ebbdc26be528e57f422b983bd46 Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 16:28:44 -0700 Subject: [PATCH 6/8] Change GetMap Function --- jws.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/jws.go b/jws.go index f0984bf..503a410 100644 --- a/jws.go +++ b/jws.go @@ -1,7 +1,6 @@ package bascule import ( - "encoding/json" "errors" jwt "github.com/dgrijalva/jwt-go" @@ -69,14 +68,16 @@ func (c *ClaimsWithLeeway) Valid() error { // GetMap returns a map of string to interfaces of the values in the ClaimsWithLeeway func (c *ClaimsWithLeeway) GetMap() (map[string]interface{}, error) { - var finalMap map[string]interface{} - inrec, err := json.Marshal(c) - if err != nil { - return nil, err - } - err = json.Unmarshal(inrec, &finalMap) - if err != nil { - return nil, err - } - return finalMap, nil + // for StandardClaims, which don't work with the []string aud values that we use + // var finalMap map[string]interface{} + // inrec, err := json.Marshal(c) + // if err != nil { + // return nil, err + // } + // err = json.Unmarshal(inrec, &finalMap) + // if err != nil { + // return nil, err + // } + // return finalMap, nil + return c.MapClaims, nil } From 7c4b0a642f772de7e0f6e8f5b6e46be691f8c2d5 Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 17:25:42 -0700 Subject: [PATCH 7/8] Add UnmarshalJSON --- basculehttp/tokenFactory.go | 2 +- jws.go | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/basculehttp/tokenFactory.go b/basculehttp/tokenFactory.go index ddee6d5..39b3597 100644 --- a/basculehttp/tokenFactory.go +++ b/basculehttp/tokenFactory.go @@ -130,7 +130,7 @@ func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Requ principal, ok := payload[jwtPrincipalKey].(string) if !ok { - return nil, emperror.WrapWith(ErrorUnexpectedPrincipal, "failed to get and convert principal", "principal", payload[jwtPrincipalKey], "payload", payload) + return nil, emperror.WrapWith(ErrorUnexpectedPrincipal, "failed to get and convert principal", "principal", payload[jwtPrincipalKey], "claims map", claimsMap, "payload", payload) } return bascule.NewToken("jwt", principal, payload), nil diff --git a/jws.go b/jws.go index 503a410..6dce056 100644 --- a/jws.go +++ b/jws.go @@ -1,6 +1,7 @@ package bascule import ( + "encoding/json" "errors" jwt "github.com/dgrijalva/jwt-go" @@ -66,6 +67,11 @@ func (c *ClaimsWithLeeway) Valid() error { return vErr } +func (c *ClaimsWithLeeway) UnmarshalJSON(data []byte) error { + c.MapClaims = make(jwt.MapClaims) // just to be sure it's clean before each unmarshal + return json.Unmarshal(data, &c.MapClaims) +} + // GetMap returns a map of string to interfaces of the values in the ClaimsWithLeeway func (c *ClaimsWithLeeway) GetMap() (map[string]interface{}, error) { // for StandardClaims, which don't work with the []string aud values that we use From 6984bc034333769ffeb5f36a54ef74acd9d89cae Mon Sep 17 00:00:00 2001 From: Kristina Spring Date: Mon, 16 Sep 2019 17:30:26 -0700 Subject: [PATCH 8/8] Cleanup code --- basculehttp/tokenFactory.go | 2 +- jws.go | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/basculehttp/tokenFactory.go b/basculehttp/tokenFactory.go index 39b3597..ddee6d5 100644 --- a/basculehttp/tokenFactory.go +++ b/basculehttp/tokenFactory.go @@ -130,7 +130,7 @@ func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Requ principal, ok := payload[jwtPrincipalKey].(string) if !ok { - return nil, emperror.WrapWith(ErrorUnexpectedPrincipal, "failed to get and convert principal", "principal", payload[jwtPrincipalKey], "claims map", claimsMap, "payload", payload) + return nil, emperror.WrapWith(ErrorUnexpectedPrincipal, "failed to get and convert principal", "principal", payload[jwtPrincipalKey], "payload", payload) } return bascule.NewToken("jwt", principal, payload), nil diff --git a/jws.go b/jws.go index 6dce056..6fae206 100644 --- a/jws.go +++ b/jws.go @@ -74,16 +74,5 @@ func (c *ClaimsWithLeeway) UnmarshalJSON(data []byte) error { // GetMap returns a map of string to interfaces of the values in the ClaimsWithLeeway func (c *ClaimsWithLeeway) GetMap() (map[string]interface{}, error) { - // for StandardClaims, which don't work with the []string aud values that we use - // var finalMap map[string]interface{} - // inrec, err := json.Marshal(c) - // if err != nil { - // return nil, err - // } - // err = json.Unmarshal(inrec, &finalMap) - // if err != nil { - // return nil, err - // } - // return finalMap, nil return c.MapClaims, nil }