2

I've got 2 questions but first I want to provide some context:

On our webapp, we are using NextAuth to generate jwt tokens which then we attach to requests against our Golang server (for fetching resources).

The generated tokens seem to be JWE tokens generated via A256GCM. In our golang server we want to validate the token and extract a few custom claims of it. That said, we're struggling to find a way to do the decryption. We're using go-jose as follows:

rawToken := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..aiIqD7-cU8Hu92F8.Kx2k99cyLYJR1P0xK_1wUsVO521T7kYSKx-OEutVJcpzbX27hZH0kh2MlBLxQHdmc8q4uXglhjl4JE3nTp_c6nOjga-faHyxYqKrZGJFLlu9MC4JVUWyonX6doFq0gl3UX9ABtP2t35Qly-w1qKH8BdG9x4iB1YM-yvs1w-HpBbMFQR7U7X4oHWIh_YJQlWADesYq6da7A97GSSXs2Go6yb7SH5WWd7iQzDu-UO6eg._PqujCUyMUqOkID80vJiDw`
key := []byte("thisisaverylongtextusedforhashing")

enc, err := jwt.ParseEncrypted(rawToken)
if err != nil {
    panic(err)
}

out := jwt.Claims{}
if err := enc.Claims(key, &out); err != nil {
    panic(err)
}
fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject)

We are getting: panic: square/go-jose: error in cryptographic primitive

PS: secret I pass to nextAuth used for the JWE generation: thisisaverylongtextusedforhashing

Raw JWE token that NextAuth outputs and which I want to validate in my golang server: eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..aiIqD7-cU8Hu92F8.Kx2k99cyLYJR1P0xK_1wUsVO521T7kYSKx-OEutVJcpzbX27hZH0kh2MlBLxQHdmc8q4uXglhjl4JE3nTp_c6nOjga-faHyxYqKrZGJFLlu9MC4JVUWyonX6doFq0gl3UX9ABtP2t35Qly-w1qKH8BdG9x4iB1YM-yvs1w-HpBbMFQR7U7X4oHWIh_YJQlWADesYq6da7A97GSSXs2Go6yb7SH5WWd7iQzDu-UO6eg._PqujCUyMUqOkID80vJiDw.

Martin
  • 1,159
  • 10
  • 34

1 Answers1

1

Given your input, I put together a response that could help you with your issue. First, I used version 2 of the package gopkg.in/go-jose/go-jose.v2 because (from what I saw) the algorithm A256GCM is not fully compatible in the newest version of the package that should be version 3. Below you can find the relevant code:

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "fmt"
    "io"
    "os"
    "time"

    "github.com/golang-jwt/jwt"
    jose_jwt "gopkg.in/go-jose/go-jose.v2"
)

type CustomClaims struct {
    Username string `json:"username"`
    Password string `json:"password"`
    jwt.StandardClaims
}

func main() {
    privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        panic(err)
    }

    // generate token
    token, err := generateToken()
    if err != nil {
        panic(err)
    }

    publicKey := &privateKey.PublicKey
    encrypter, err := jose_jwt.NewEncrypter(jose_jwt.A256GCM, jose_jwt.Recipient{
        Algorithm: jose_jwt.RSA_OAEP_256,
        Key:       publicKey,
    }, nil)
    if err != nil {
        panic(err)
    }

    plainText := []byte(token)
    object, err := encrypter.Encrypt(plainText)
    if err != nil {
        panic(err)
    }

    serialized := object.FullSerialize()

    object, err = jose_jwt.ParseEncrypted(serialized)
    if err != nil {
        panic(err)
    }

    decrypted, err := object.Decrypt(privateKey)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(decrypted))

    // parse token
    claims, err := ValidateToken(string(decrypted))
    if err != nil {
        panic(err)
    }

    fmt.Println(len(claims))
}

Here, we first generate a private key to encrypt the token and then decrypt it through its public key. I omitted the code used to generate and validate a JWT token for brevity. To test out the solution I added two custom claims to the generated token (username and password that are defined in the CustomClaims struct). Then, when we parse the token, we'll be able to retrieve their values.
Let me know if this helps you!

ossan
  • 1,665
  • 4
  • 10
  • Thanks! In NextAuth (where the jwe gets generated) we provide the secret above (testone given). I don't think we have access to any PK to use for the algo here. I've given our exact secret + output jwe for reference – Martin Nov 28 '22 at 10:27
  • Can you provide all the relevant file? With also the import section and so on? So I'm sure about what you used. – ossan Nov 28 '22 at 10:33
  • For NextAuth (nextjs) or our golang token validation? – Martin Nov 28 '22 at 11:01
  • If you can provide everything so I'll be able to repro everything from scratch, thanks! – ossan Nov 28 '22 at 11:08
  • https://goplay.tools/snippet/FsiIc2Uw_12 here's the exact decryption, again, the token is generated by our auth server (via nextauth) with the provided secret – Martin Nov 28 '22 at 11:13