13

I have a public key from my identity provider

-----BEGIN PUBLIC KEY-----
THIS
-----END PUBLIC KEY-----

And a JWT token from my client.

How do I check the token against the key? I'm having difficulty with jwt-go because the Parse function takes the token string and a getKey function.

Not sure how exactly to proceed

3
  • There is no public or private key, when you work with JWT. There is just a secrect. jwt.io
    – apxp
    Commented Aug 14, 2018 at 5:51
  • 3
    No. You could use RSA algorithm to sign, it needs a pair of private key and public key to sign and verify. Commented Aug 14, 2018 at 8:16
  • I have proof of concept to use jwt-go to sign a token using private key and public key for verification. it might help, you can check it here github.com/Keda87/golang-echo-jwt-rsa Commented Mar 22, 2022 at 4:26

2 Answers 2

16

The token was signed by RSA algorithm that uses a private key to sign and a public key to verify. Store your public key to the files system and use jwt.SigningMethodRS256.Verify() to verify. As the following snippet:

package main

import (
    "fmt"
    "strings"
    "log"
    "io/ioutil"
    jwt "github.com/dgrijalva/jwt-go"
)

func main() {
    publicKeyPath := "~/public_key.key"
    token := "your_jwt_token_here"

    if isValid, err := verifyToken(token, publicKeyPath)
    if err != nil {
        log.Fatal(err)
    }

    if isValid {
        fmt.Println("The token is valid")
    } else {
        fmt.Println("The token is invalid")
    }
}

func verifyToken(token, publicKeyPath string) (bool, error) {
    keyData, err := ioutil.ReadFile(publicKeyPath)
    if err != nil {
        return false, err
    }
    key, err := jwt.ParseRSAPublicKeyFromPEM(keyData)
    if err != nil {
        return false, err
    }

    parts := strings.Split(token, ".")
    err = jwt.SigningMethodRS256.Verify(strings.Join(parts[0:2], "."), parts[2], key)
    if err != nil {
        return false, nil
    }
    return true, nil
}
9

Using jwt-go, you can do this

token, err := p.Parse(IDToken, func(*jwt.Token) (interface{}, error) {
    return []byte(signingKey), nil
})

And it will verify the token against the key.

Quoting the documentation,

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

Parse methods use this callback function to supply the key for verification. The function receives the parsed, but unverified Token. This allows you to use properties in the Header of the token (such as kid) to identify which key to use.

5
  • if I generate JWT token with private key as my signing key, then it should be use the private key for the verification, isn't? and the question is how to verify using public key if I have JWT token generated from private key Commented Mar 21, 2022 at 14:51
  • Hi @AdiyatMubarak. No, verifications are done with public keys. The private key should only be known by the signer, who then sends the public key to verifiers/receivers of signed messages. See en.wikipedia.org/wiki/Key_authentication
    – Ullaakut
    Commented Mar 21, 2022 at 14:53
  • Thank you @Ullaakut. will take a look at that. Seems like I misconfigured my project which still does not work. Commented Mar 21, 2022 at 23:35
  • Previously I used raw byte from my private key for signing, then verifying with a raw byte from my public key, but it failure on verification. but it works now after I changed the signing and verify key using *rsa.PrivateKey and *rsa.PublicKey. thank you for pointing out @Ullaakut Commented Mar 22, 2022 at 0:35
  • No worries! :) Good luck and have fun with JWT authentication!
    – Ullaakut
    Commented Mar 22, 2022 at 10:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.