3

We have a JWT token that we need to decode, the issue is that we are using TinyGo and some libraries are not supported, How can it be done for TinyGo / core Go libraries which is already supported? I want to print the "name" value:

I'm not able to get the name, any idea?

func main() {
    token := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`
    base64String := base64.StdEncoding.EncodeToString([]byte(token))
    decodedData, err := base64.StdEncoding.DecodeString(base64String)
    if err != nil {
        panic(err)
    }

    name := decodedData["name"]

    fmt.Println(name)

}

The decoded token is:

PAYLOAD
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

See this example token from https://jwt.io

blackgreen
  • 34,072
  • 23
  • 111
  • 129
JME
  • 881
  • 2
  • 11
  • 23
  • 2
    you asked this question before and I told you already that you can't just base64 decode the complete token string. This is simply wrong. A JWT consists of 3 base64 encoded parts: base64urlencodedHeader.base64urlencodedPayload.base64urlencodedSignature. You need to split the string first. – jps Jun 28 '21 at 09:45
  • @jps - as im struggling with it, could you please provide an example ? – JME Jun 28 '21 at 09:47
  • 1
    I'm not a go programmer. Just [split the string](https://stackoverflow.com/questions/16551354/how-to-split-a-string-and-assign-it-to-variables) into 3 parts (header, payload, signature) and then decode the payload. Why did you delete the original question? You should not just repost the question if you don't get a satisfying answer within a few minutes. You did not even give feedback to the existing answer, that's not nice. Respond to comments and answers and update your question is the way to get a solution here. – jps Jun 28 '21 at 09:51

1 Answers1

3

Decoding and getting the name part is easy. But this does not ensure the token is valid, meaning the owner of the token is truly what the name says!

JWT tokens just contain the base64 encoded forms of a header, payload and signature parts, connected with a .. So just split the token by ., decode the base64 string and you may use json.Unmarshal() to convert the header and playload parts to maps or structs.

You must verify the signature to ensure the name is valid. If you don't perform signature verification, a token may easily be forged to pose as anyone. Signature verification is exactly what JWT libs do (besides parsing and generating tokens). How to do that, check the sources of JWT libs. I also believe there are open-source libs that process JWT tokens that also work with tiny-go.

Example code to decode the parts and print the name:

token := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`
for i, part := range strings.Split(token, ".") {
    fmt.Printf("[%d] part: %s\n", i, part)
    decoded, err := base64.RawURLEncoding.DecodeString(part)
    if err != nil {
        panic(err)
    }
    fmt.Println("decoded:", string(decoded))
    if i != 1 {
        continue // i == 1 is the payload
    }

    var m map[string]interface{}
    if err := json.Unmarshal(decoded, &m); err != nil {
        fmt.Println("json decoding failed:", err)
        continue
    }
    if name, ok := m["name"]; ok {
        fmt.Println("name:", name)
    }
}

Which outputs (try it on the Go Playground):

[0] part: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
decoded: {"alg":"HS256","typ":"JWT"}
[1] part: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
decoded: {"sub":"1234567890","name":"John Doe","iat":1516239022}
name: John Doe
[2] part: SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
decoded: I�J�IHNJ(]�O���lj~�:N�%_�u,×
icza
  • 389,944
  • 63
  • 907
  • 827
  • Thanks a lot 1+ , one question why I need the loop ? if I need only the `payload` it should be simply? – JME Jun 28 '21 at 10:19
  • 1
    I used a loop to print all the token "parts" so you can see what's in it. If you only need the name, you only need to process the 2nd part (`strings.Split(token, ".")[1]`). But you really should validate the token, else it provides no security. – icza Jun 28 '21 at 10:39
  • 1
    It seems encoder/json doesn't actually work in TinyGo, not sure if it used to (I don't think so; unless older implementations didn't use reflection). – John Keates May 18 '22 at 01:58