繁体   English   中英

如何使用 jwt 在 nodejs 后端验证来自 Auth0 的令牌? JsonWebToken错误

[英]How can I verify a token from Auth0 in nodejs backend with jwt? JsonWebTokenError

我有一个带有 auth0 的反应前端来记录用户,一旦用户登录,我就会使用getAccessTokenSilently()获取令牌并将其发送到后端,如下所示:

const { user, isAuthenticated, getAccessTokenSilently } = useAuth0()

useEffect(() => {
    if (user) getTickets()
}, [user])

async function getTickets() {
    const token = await getAccessTokenSilently()
    const response = await fetch('http://localhost:4000/api/gettickets', {
        method: 'POST',
        headers: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ user, bar }),
    })
    const data = await response.json()
}

一旦我的后端有了令牌,我就会尝试像这样验证它 jsonwebtoken :

import express from 'express'
import jwt from 'jsonwebtoken'
import dotenv from 'dotenv'
dotenv.config()

const routerGetTickets = express.Router()

routerGetTickets.post('/', async (req, res) => {
    const PUBKEY = process.env.PUBKEY
    const token = req.headers.authorization?.split(' ')[1]

    if (token && PUBKEY) {
        jwt.verify(token, PUBKEY, { algorithms: ['RS256'] }, (err, data) => {
            console.log('token :>> ', token)
            if (err) {
                res.sendStatus(403)
                console.log('err :>> ', err)
                return
            } else {
                console.log('everything ok')
            }
        })
    }
})
export default routerGetTickets

如果我没记错的话,使用 RS256 算法,我必须提供使用 openssl 获得的公钥和我从 Auth0 仪表板中的应用程序下载的登录证书。

这是我得到的错误: err:>> JsonWebTokenError: secretOrPublicKey must be an asymmetric key when using RS256

这是我的 index.ts:

import React from 'react'
import ReactDOM from 'react-dom/client'
import './sass/index.scss'
import App from './App'
import { BrowserRouter } from 'react-router-dom'
import { Auth0Provider } from '@auth0/auth0-react'

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)

root.render(
<React.StrictMode>
    <BrowserRouter basename='/tombola'>
        <Auth0Provider
            domain='*******.uk.auth0.com'
            clientId='*****************************'
            authorizationParams={{
                redirect_uri: `${window.location.origin}/tombola/callback`,
                audience: 'https://******.uk.auth0.com/api/v2/',
                scope: 'read:current_user update:current_user_metadata'

            }}
        >
            <App />
        </Auth0Provider>
    </BrowserRouter>
</React.StrictMode>
)

我在也使用 Auth0 的验证 jwt 方法中遇到了这个问题,问题出在公钥上。

您没有在 PUBKEY 变量所在的位置显示您的 .env 文件,但我想您是从应用程序 -> 设置 -> 高级设置 -> 证书中获取它的,正如 Auth0 文档所说,但那是证书而不是公钥。

要获取公钥,您需要使用“jwks-rsa”库,它使用证书检索公钥,从您的 Auth0 应用程序域获取它,为此它需要两件事:

1- 构造 Auth0 提供密钥的 url 的域。

2- 您的 jwt 令牌的“孩子”header,它标识了正确的密钥。

代码如下所示:

async function HandleRequest(req, res) {
const cookie = req.headers.cookie;

const token = cookie.split(";")
.find(c => c.trim().startsWith("access_token="))
.split("=")[1]

const kid = decode(token, { complete: true }).header.kid;

const publicKey = (await JwksRsa({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: `https://${process.env.DOMAIN}/.well-known/jwks.json`
}).getSigningKey(kid)).getPublicKey()

if (cookie && cookie.includes("access_token")) {
    verify(
        token,
        publicKey,
        {
            algorithms: ["RS256"],
        },
        (err, decoded) => {
            if (err) {
                res.write(JSON.stringify(err));
            } else {
                res.write(JSON.stringify(decoded));
            }
        }
    );
} else {
    res.write("No access token found")
}
res.end();
return
}

请注意,在示例中,我在 api 路由中,处理请求并在标头中获取 jwt 令牌,我的 jwt 在标头中为“access_token”,您的可能不同,然后对其进行解码,提取 kid标识符,将其与构建的域 url 一起传递给 jwks-rsa,然后 jwks-rsa 库处理所有从您的 Auth0 应用程序获取证书的请求,以及从证书中检索公钥的所有加密工作。

您可以使用“crypto”节点模块从证书中检索,但我试过了,结果一团糟,因为它更适合 .pem 文件而不是字符串,但了解这一点很有用。

希望这对你有帮助,我知道 Auth0 在学习时会扰乱我们的头脑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM