From 15eff4fc9766afb475edc0506c3c24665842d54f Mon Sep 17 00:00:00 2001 From: Craig Pastro Date: Thu, 1 Jun 2023 14:08:23 -0700 Subject: [PATCH 1/4] Avoid use of json.NewDecoder Avoid use of json.NewDecoder if not needed. Resolves #303. --- parser.go | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/parser.go b/parser.go index f4386fba..dc76c1cf 100644 --- a/parser.go +++ b/parser.go @@ -135,30 +135,42 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke } return token, parts, newError("could not base64 decode header", ErrTokenMalformed, err) } - if err = json.Unmarshal(headerBytes, &token.Header); err != nil { + if err := json.Unmarshal(headerBytes, &token.Header); err != nil { return token, parts, newError("could not JSON decode header", ErrTokenMalformed, err) } // parse Claims - var claimBytes []byte token.Claims = claims - if claimBytes, err = p.DecodeSegment(parts[1]); err != nil { + claimBytes, err := p.DecodeSegment(parts[1]) + if err != nil { return token, parts, newError("could not base64 decode claim", ErrTokenMalformed, err) } - dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) - if p.useJSONNumber { - dec.UseNumber() - } - // JSON Decode. Special case for map type to avoid weird pointer behavior - if c, ok := token.Claims.(MapClaims); ok { - err = dec.Decode(&c) + + if !p.useJSONNumber { + // JSON Unmarshal. Special case for map type to avoid weird pointer behavior. + if c, ok := token.Claims.(MapClaims); ok { + err = json.Unmarshal(claimBytes, &c) + } else { + err = json.Unmarshal(claimBytes, &claims) + } + if err != nil { + return token, parts, newError("could not JSON decode claim", ErrTokenMalformed, err) + } } else { - err = dec.Decode(&claims) - } - // Handle decode error - if err != nil { - return token, parts, newError("could not JSON decode claim", ErrTokenMalformed, err) + dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) + dec.UseNumber() + + // JSON Decode. Special case for map type to avoid weird pointer behavior + if c, ok := token.Claims.(MapClaims); ok { + err = dec.Decode(&c) + } else { + err = dec.Decode(&claims) + } + // Handle decode error + if err != nil { + return token, parts, newError("could not JSON decode claim", ErrTokenMalformed, err) + } } // Lookup signature method From 6e5a57e839665170217d6cf8a4baeba29647c568 Mon Sep 17 00:00:00 2001 From: Craig Pastro Date: Thu, 1 Jun 2023 14:11:09 -0700 Subject: [PATCH 2/4] Move error handling to after decode --- parser.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/parser.go b/parser.go index dc76c1cf..c8ed0a48 100644 --- a/parser.go +++ b/parser.go @@ -154,9 +154,6 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke } else { err = json.Unmarshal(claimBytes, &claims) } - if err != nil { - return token, parts, newError("could not JSON decode claim", ErrTokenMalformed, err) - } } else { dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) dec.UseNumber() @@ -167,10 +164,9 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke } else { err = dec.Decode(&claims) } - // Handle decode error - if err != nil { - return token, parts, newError("could not JSON decode claim", ErrTokenMalformed, err) - } + } + if err != nil { + return token, parts, newError("could not JSON decode claim", ErrTokenMalformed, err) } // Lookup signature method From 6aee521de8fdb4a14a9668eabad99b6ac8d31838 Mon Sep 17 00:00:00 2001 From: Craig Pastro Date: Wed, 21 Jun 2023 09:05:34 -0700 Subject: [PATCH 3/4] address feedback --- parser.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/parser.go b/parser.go index c8ed0a48..6da3dadf 100644 --- a/parser.go +++ b/parser.go @@ -135,7 +135,7 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke } return token, parts, newError("could not base64 decode header", ErrTokenMalformed, err) } - if err := json.Unmarshal(headerBytes, &token.Header); err != nil { + if err = json.Unmarshal(headerBytes, &token.Header); err != nil { return token, parts, newError("could not JSON decode header", ErrTokenMalformed, err) } @@ -157,8 +157,7 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke } else { dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) dec.UseNumber() - - // JSON Decode. Special case for map type to avoid weird pointer behavior + // JSON Decode. Special case for map type to avoid weird pointer behavior. if c, ok := token.Claims.(MapClaims); ok { err = dec.Decode(&c) } else { From fb764cf6cb1657d8088cb2aa2fa3d5d8e60b683b Mon Sep 17 00:00:00 2001 From: Craig Pastro Date: Mon, 14 Aug 2023 13:43:11 -0700 Subject: [PATCH 4/4] Add comment justifying use of json.Unmarshal --- parser.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/parser.go b/parser.go index 6da3dadf..e24c5842 100644 --- a/parser.go +++ b/parser.go @@ -147,6 +147,9 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke return token, parts, newError("could not base64 decode claim", ErrTokenMalformed, err) } + // If `useJSONNumber` is enabled then we must use *json.Decoder to decode + // the claims. However, this comes with a performance penalty so only use + // it if we must and, otherwise, simple use json.Unmarshal. if !p.useJSONNumber { // JSON Unmarshal. Special case for map type to avoid weird pointer behavior. if c, ok := token.Claims.(MapClaims); ok {