jwt
jwt copied to clipboard
Generating the wrong token when customising claims
Situation
type fooClaims struct {
Foo string `json:"foo"`
}
func main() {
key := ([]byte("foo"))
foo := fooClaims{
Foo: "foo",
}
token, err := jwt.Sign(jwt.HS256, key, foo, jwt.MaxAge(time.Second*1))
if err != nil {
panic(err)
}
fmt.Println(token)
}
This will successfully output a token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJmb28iLH0.x3KzbXc5PoGcb42h2vETFtGn5l1K3rhdJlQmgYGBR-k
Parsing the payload, the message looks like this
{"foo":"foo",}
This is not a valid json because it ends with ","
This causes the verify to return an error because the Json could not be parsed
jwt: payload is not a type of JSON
This only happens if MaxAge is not greater than 1 second
Reasons for speculation
I didn't do detailed testing, just inferred from the code
claims.go
MaxAge did not add the relevant information to the claims as the input time did not exceed 1 second
func MaxAge(maxAge time.Duration) SignOptionFunc {
return func(c *Claims) {
if maxAge <= time.Second {
return
}
now := Clock()
c.Expiry = now.Add(maxAge).Unix()
c.IssuedAt = now.Unix()
}
}
Custom claims are added with "," at the end
func Merge(claims interface{}, other interface{}) []byte {
claimsB, err := Marshal(claims)
if err != nil {
return nil
}
otherB, err := Marshal(other)
if err != nil {
return nil
}
if len(otherB) == 0 {
return claimsB
}
claimsB = claimsB[0 : len(claimsB)-1] // remove last '}'
otherB = otherB[1:] // remove first '{'
raw := append(claimsB, ',')
raw = append(raw, otherB...)
return raw
}
This resulted in the wrong payload being generated