ParseWithClaims fails from json.NewDecoder
Aner-Git opened this issue · comments
An error occurs for this simple code:
import (
"testing"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
)
type cc struct {
Foo string `json:"foo"`
jwt.RegisteredClaims
}
func TestParseWClaims(t *testing.T) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, cc{Foo: "value"})
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString([]byte("xxxx"))
assert.Nil(t, err, "Sign failed")
parser := &jwt.Parser{}
var c cc
ttoken, err := parser.ParseWithClaims(tokenString, c, func(t *jwt.Token) (any, error) { return []byte("xxxx"), nil })
t.Logf("%+v", ttoken.Claims)
assert.Nil(t, err, "Parse claims")
assert.Equal(t, ttoken.Claims.(cc).Foo, "value")
}
Produces:
&fmt.wrapErrors{msg:"token is malformed: could not JSON decode claim: json: cannot unmarshal object into Go value of type jwt.Claims", errs:[]error{(*errors.errorString)(0xc0000588d0), (*json.UnmarshalTypeError)(0xc0000743c0)}}
go version
go version go1.20.4 linux/amd64
The error occurs calling Decode
of a json decoder. Here is a simplified example of the call stack in the code.
Note the func call which 'simulates' the call to ParseWithClaims.
type cc struct {
Foo string `json:"foo"`
jwt.RegisteredClaims
}
func TestJsonDec(t *testing.T) {
bs := []byte(`{"Foo":"value"}`)
func(claim jwt.Claims) {
c := claim
dec := json.NewDecoder(bytes.NewBuffer(bs))
e := dec.Decode(&c)
assert.Nil(t, e)
}(c)
}
Apart from using the map
not clear how to solve this.
Pass the memory address of c
, e.g.,
ttoken, err := parser.ParseWithClaims(tokenString, &c <--- here
and then assert Claims to your type (*cc) in this case, e.g.,
v, ok := ttoken.Claims.(*cc)
if ok {
fmt.Println(v.Foo)
// value
}
There is an example of custom claims here if it helps:
Lines 101 to 109 in 8aa5d6c
ttoken, err := jwt.ParseWithClaims(tokenString, &c, func(t *jwt.Token) (any, error) { return []byte("xxxx"), nil })
I get
jwt_test.go:63: &{Foo:value RegisteredClaims:{Issuer: Subject: Audience:[] ExpiresAt:<nil> NotBefore:<nil> IssuedAt:<nil> ID:}}
panic: interface conversion: jwt.Claims is *auth.cc, not auth.cc [recovered]
panic: interface conversion: jwt.Claims is *auth.cc, not auth.cc
A few suggestions,
- assert for the type so you don't get panic (comma okay):
- assert.Equal(t, ttoken.Claims.(cc).Foo, "value")
+ customClaims, ok := ttoken.Claims.(cc)
- the type you're asserting for should be
*cc
and notcc
ttoken.Claims.(*cc)
Moving this to the Q&A discussion.