英文:
How to validate JWE token in Golang
问题
我有两个问题,但首先我想提供一些背景信息:
在我们的 Web 应用程序中,我们使用 NextAuth 生成 JWT 令牌,然后将其附加到针对我们的 Golang 服务器(用于获取资源)的请求中。
生成的令牌似乎是通过 A256GCM 生成的 JWE 令牌。在我们的 Golang 服务器中,我们想要验证令牌并提取其中的一些自定义声明。也就是说,我们在解密方面遇到了困难。我们使用 go-jose
如下所示:
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)
我们得到的错误信息是:
panic: square/go-jose: error in cryptographic primitive
附注:我传递给 NextAuth 用于 JWE 生成的密钥是 thisisaverylongtextusedforhashing
我想在我的 Golang 服务器中验证的原始 JWE 令牌是:eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..aiIqD7-cU8Hu92F8.Kx2k99cyLYJR1P0xK_1wUsVO521T7kYSKx-OEutVJcpzbX27hZH0kh2MlBLxQHdmc8q4uXglhjl4JE3nTp_c6nOjga-faHyxYqKrZGJFLlu9MC4JVUWyonX6doFq0gl3UX9ABtP2t35Qly-w1qKH8BdG9x4iB1YM-yvs1w-HpBbMFQR7U7X4oHWIh_YJQlWADesYq6da7A97GSSXs2Go6yb7SH5WWd7iQzDu-UO6eg._PqujCUyMUqOkID80vJiDw
。
英文:
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
.
答案1
得分: 1
根据您的输入,我整理了一个回答,希望能帮助您解决问题。首先,我使用了版本2的gopkg.in/go-jose/go-jose.v2
包,因为(根据我所看到的)算法A256GCM
在最新版本的包中不完全兼容,最新版本应该是版本3。以下是相关的代码:
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)
}
// 生成令牌
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))
// 解析令牌
claims, err := ValidateToken(string(decrypted))
if err != nil {
panic(err)
}
fmt.Println(len(claims))
}
在这里,我们首先生成一个私钥来加密令牌,然后通过其公钥解密它。为了简洁起见,我省略了用于生成和验证JWT令牌的代码。为了测试解决方案,我在生成的令牌中添加了两个自定义声明(username
和password
,在CustomClaims
结构体中定义)。然后,当我们解析令牌时,我们将能够获取它们的值。
如果有帮助,请告诉我!
英文:
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!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论