go-chi / jwtauth

JWT authentication middleware for Go HTTP services
MIT License
541 stars 91 forks source link

int turns float64 after decode #62

Closed alexgarzao closed 3 years ago

alexgarzao commented 3 years ago

Hello.

I'm trying to get data from claims, after the decode. But it seems that the original value (an int) turns a float64, after the decode.

Example:

package main

import (
    "context"
    "fmt"

    "github.com/go-chi/jwtauth/v5"
)

func main() {
    tokenAuth := jwtauth.New("HS256", []byte("secret"), nil)
    _, tokenString, _ := tokenAuth.Encode(map[string]interface{}{"user_id": 123})

    myToken, _ := tokenAuth.Decode(tokenString)
    claims, _ := myToken.AsMap(context.Background())
    userID := claims["user_id"]

    _, ok := userID.(int)
    if ok {
        fmt.Printf("userID %v is int\n", userID)
    }

    _, ok = userID.(float64)
    if ok {
        fmt.Printf("userID %v is float\n", userID)
    }
}

When I run this, I got "userID 123 is float".

I'm using go 1.16.6, on ubuntu 21.04.

I am doing something wrong?

Thanks

VojtechVitek commented 3 years ago

This is expected per Go's JSON marshaller. https://pkg.go.dev/encoding/json#Decoder.UseNumber

I'd suggest to use a strongly typed struct for your data (instead of map[string]interface{}), where the unmarshaller would know what type of the field you actually expect.

But, the safest option is to render all IDs as strings in the JSON payload, since JSON (JavaScript) can't handle big integers. We ran into some problems with int64 IDs loosing precision in the JavaScript application, cause JavaScript's float couldn't handle it. The safest solution was to switch to strings (for IDs) everywhere.

type MyPayload struct{
  ID int64 `json:"id,string"`
}