3

I am following this example https://www.youtube.com/watch?v=eVlxuST7dCA to make a jwt auth. When I run the code below I get "Key is invalid" error. When I try printing tokenString it is empty. The GitHub to this sample is https://github.com/potatogopher/jwt-go-example/blob/master/server.go Why am I getting invalid error?

var privateKey []byte
privateKey, err := ioutil.ReadFile("demo.rsa")

token := jwt.New(jwt.GetSigningMethod("RS256"))
tokenString, err := token.SignedString(privateKey)

fmt.Println("TOKEN:", tokenString)
Grokify
  • 15,092
  • 6
  • 60
  • 81
amanda45
  • 535
  • 10
  • 29
  • 2
    Are you sure that demo.rsa is a valid key? – Charles Shiller Jun 29 '17 at 05:02
  • Whichever signing method you decide to use, make sure you hardcode it in and verify the incoming JWT has the correct signing method. I'm not sure if this is still a vulnerability in Go, but give this article a read to avoid opening a security hole. https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ – RayfenWindspear Jun 29 '17 at 18:20

2 Answers2

16

I think the example code you're referring to uses an outdated API of jwt-go. The RS256 signing method requires the key to be a rsa.PrivateKey and not a byte buffer. This means, that the private key first has to be parsed using the jwt.ParseRSAPrivateKeyFromPEMfunction.

I've updated your example below:

func main() {
    tokenString, err := createSignedTokenString()
    if err != nil {
        panic(err)
    }
    fmt.Printf("Signed token string:\n%v\n", tokenString)

    token, err := parseTokenFromSignedTokenString(tokenString)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Parsed token valid = %v, raw token:\n%v\n", token.Valid, token.Raw)
}

func createSignedTokenString() (string, error) {
    privateKey, err := ioutil.ReadFile("demo.rsa")
    if err != nil {
        return "", fmt.Errorf("error reading private key file: %v\n", err)
    }

    key, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey)
    if err != nil {
        return "", fmt.Errorf("error parsing RSA private key: %v\n", err)
    }

    token := jwt.New(jwt.SigningMethodRS256)
    tokenString, err := token.SignedString(key)
    if err != nil {
        return "", fmt.Errorf("error signing token: %v\n", err)
    }

    return tokenString, nil
}

func parseTokenFromSignedTokenString(tokenString string) (*jwt.Token, error) {
    publicKey, err := ioutil.ReadFile("demo.rsa.pub")
    if err != nil {
        return nil, fmt.Errorf("error reading public key file: %v\n", err)
    }

    key, err := jwt.ParseRSAPublicKeyFromPEM(publicKey)
    if err != nil {
        return nil, fmt.Errorf("error parsing RSA public key: %v\n", err)
    }

    parsedToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        return key, nil
    })
    if err != nil {
        return nil, fmt.Errorf("error parsing token: %v", err)
    }

    return parsedToken, nil
}
fhe
  • 6,099
  • 1
  • 41
  • 44
  • @fhe-Thanks, it works. How can I parse this after? I tried jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) but I always get invalid type – amanda45 Jun 30 '17 at 17:08
  • 1
    @amanda45 I've extended the example with parseTokenFromSignedTokenString() which shows how to verify a signed token string. It's important to use the rsa.PublicKey there :) – fhe Jun 30 '17 at 20:09
7

You need to create the private key with this command: openssl genrsa -out demo.rsa

If you dont want to do that, you can also use the hmac signing method where you only have to supply a secret key/string.

Example:

key := []byte("test")

token := jwt.New(jwt.SigningMethodHS256)
tokenString, err := token.SignedString(key)

fmt.Println("TOKEN:", tokenString)
Mustafa Gezen
  • 136
  • 2
  • 4