11

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

Grokify
  • 15,092
  • 6
  • 60
  • 81
David Alsh
  • 6,747
  • 6
  • 34
  • 60
  • There is no public or private key, when you work with JWT. There is just a secrect. https://jwt.io/ – apxp Aug 14 '18 at 05:51
  • 3
    No. You could use RSA algorithm to sign, it needs a pair of private key and public key to sign and verify. – Nguyen Dang Minh Aug 14 '18 at 08: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 https://github.com/Keda87/golang-echo-jwt-rsa – Adiyat Mubarak Mar 22 '22 at 04:26

2 Answers2

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.

Community
  • 1
  • 1
Ullaakut
  • 3,554
  • 2
  • 19
  • 34
  • 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 – Adiyat Mubarak Mar 21 '22 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 https://en.wikipedia.org/wiki/Key_authentication – Ullaakut Mar 21 '22 at 14:53
  • Thank you @Ullaakut. will take a look at that. Seems like I misconfigured my project which still does not work. – Adiyat Mubarak Mar 21 '22 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 – Adiyat Mubarak Mar 22 '22 at 00:35
  • No worries! :) Good luck and have fun with JWT authentication! – Ullaakut Mar 22 '22 at 10:46