[英]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.