8

I am trying to pass in a token to the "Parse(token String, keyFunc Keyfunc)" GO routine defined in this GO-library (http://godoc.org/github.com/dgrijalva/jwt-go) for JWT-token parsing/validation.

When I pass the token to this function -

token, err := jwt.Parse(getToken, func(token *jwt.Token) (interface{}, error) {
        return config.Config.Key, nil
    })

I get an error which says "Key is invalid or invalid type".

My config struct looks like this in config.go file -

config struct {
 Key string
}

Any suggestions to solve this problem? The token I am passing is a JWT token.

Grokify
  • 15,092
  • 6
  • 60
  • 81
psbits
  • 1,787
  • 5
  • 19
  • 34

5 Answers5

19
config struct {
 Key string
}

Key needs to be a []byte

Jesse
  • 206
  • 2
  • 2
  • 1
    While this code sample may possibly answer the question, it would be preferable to include some essential explanation to your answer. As it stands now this answer adds little to no value for future readers. – oɔɯǝɹ Feb 04 '15 at 19:25
  • How to implement this exactly? Earlier I tried using []byte("key") without any struct and it gave me the error. A little elaboration to the solution might be helpful for newcomers @Jesse – piedpipr Aug 18 '23 at 17:16
14

I am not sure if this can be an issue for someone else.

My problem was I was using Signing Method "SigningMethodES256" but "SigningMethodHS256" or Any with SigningMethodHS* works fine.

If someone knows why this is an issue please answer.

Mandeep Gill
  • 4,577
  • 1
  • 28
  • 34
  • 1
    A bit late. It's because each signing method has its own key type. You can see the type expected for every signing method here https://golang-jwt.github.io/jwt/usage/signing_methods/ – Lucas Tomic Jun 12 '23 at 17:21
  • Yes thanks, but few people getting this issue. – Mandeep Gill Jun 14 '23 at 10:56
6

Other way is to do something like this -

token, err := jwt.Parse(getToken, func(token *jwt.Token) (interface{}, error) {
        return []byte(config.Config.Key), nil
    })

The whole idea being that the Parse function returns a slice of bytes.

psbits
  • 1,787
  • 5
  • 19
  • 34
1

Taking a look at the function signatures in the GoDoc for github.com/dgrijalva/jwt-go we see:

func Parse(tokenString string, keyFunc Keyfunc) (*Token, error)

type Keyfunc func(*Token) (interface{}, error)

Keyfunc requires you to return (interface{}, error). Given the mysterious interface{} type, you might expect to be fine returning a string; however, a peek under the hood reveals that Parse() tries to Verify(), which attempts the following type assertion with your interface{} value as the key:

keyBytes, ok := key.([]byte)

That will succeed for []byte types, but will fail for string types. When that fails, the result is the error message you are getting. Read more about type assertions in the Effective Go documentation to learn why it fails.

Example: https://play.golang.org/p/9KKNFLLQrm

package main

import "fmt"

func main() {
    var a interface{}
    var b interface{}

    a = []byte("hello")
    b = "hello"

    key, ok := a.([]byte)
    if !ok {
        fmt.Println("a is an invalid type")
    } else {
        fmt.Println(key)
    }

    key, ok = b.([]byte)
    if !ok {
        fmt.Println("b is an invalid type")
    } else {
        fmt.Println(key)
    }
}

[104 101 108 108 111]
b is an invalid type
Niko
  • 658
  • 8
  • 14
1

This is working for me.

token.SignedString([]byte("mysecretkey"))

func GenerateJWT(email string, username string) (tokenString string, err error) {

    expirationTime := time.Now().Add(1 * time.Hour)
    claims := &JWTClime{
        Email:    email,
        Username: username,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenString, err = token.SignedString([]byte("mysecretkey"))

    return
}
venkat7668
  • 2,657
  • 1
  • 22
  • 26