How to parse the expiration date of a JWT to a time.Time() in Go?
Asked Answered
W

1

10

I'd like to parse the expiration date (exp) from a JSON Web Token (JWT) without verifying it. I've tried the following script (in an attempt to follow How to parse unix timestamp to time.Time):

package main

import (
    "fmt"
    "log"
    "strconv"
    "time"

    jwt "github.com/dgrijalva/jwt-go"
)

func main() {
    tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

    token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
    if err != nil {
        log.Fatal(err)
    }

    if claims, ok := token.Claims.(jwt.MapClaims); ok {
        fmt.Println(claims["exp"])
        i, err := strconv.ParseInt(claims["exp"].(string), 10, 64)
        if err != nil {
            log.Fatal(err)
        }

        tm := time.Unix(i, 0)
        fmt.Println(tm)
    }
}

However, I get this error:

> go run main.go
<nil>
panic: interface conversion: interface {} is nil, not string

goroutine 1 [running]:
main.main()
    /Users/kurt/go/src/github.com/khpeek/mygoproject/jwt_validation/main.go:23 +0x34a
exit status 2

Is there a way I could get a string for exp out of the jwt library? How could I make this give me the expiration date (or the iat) of the JWT?

Welbie answered 17/10, 2019 at 22:36 Comment(1)
Your code looks okay at a glance, but this token doesn't contain an exp claim (inspect it on jwt.io).Execration
W
7

I ended up calling int64 on claims["exp"] directly rather than first trying to convert it to a string:

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "time"

    jwt "github.com/dgrijalva/jwt-go"
)

func main() {
    tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

    token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
    if err != nil {
        log.Fatal(err)
    }

    claims, ok := token.Claims.(jwt.MapClaims)
    if !ok {
        log.Fatalf("Can't convert token's claims to standard claims")
    }

    var tm time.Time
    switch iat := claims["iat"].(type) {
    case float64:
        tm = time.Unix(int64(iat), 0)
    case json.Number:
        v, _ := iat.Int64()
        tm = time.Unix(v, 0)
    }

    fmt.Println(tm)
}

which prints

> go run main.go
2018-01-17 17:30:22 -0800 PST

Note that I've replaced exp with iat since the simplified example (obtained from jwt.io) does not have an exp claim, but it does have an iat one.

Welbie answered 17/10, 2019 at 23:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.