我已经使用 openid-client 在 NextJS 中实现了 OAuth2 授权代码流程(尚未使用 PKCE)。现在我应该在哪里存储
code_verifier
以及如何将其传递给服务器端调用的回调。
到目前为止我做了什么(草图):
// on server-side:
import { BaseClient, Issuer, custom, generators } from 'openid-client';
const issuer = await Issuer.discover('https://www.my-oidc-provider-endpoint');
const client = new issuer.Client({
client_id: 'myClientId',
client_secret: 'myClientSecret',
redirect_uri: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`,
});
// This must happen on server-side b/c the library is not available in the browser:
// const code_verifier = generators.codeVerifier();
// const code_challenge = generators.codeChallenge(code_verifier);
const authorizationUrl = client.authorizationUrl({
scope: 'openid email profile rights',
// code_challenge,
// code_challenge_method: 'S256',
})
// on client-side
// the authorizationUrl was passed via getStaticProps
window.location.assign(authorizationUrl)
并且在我的
api/auth/callback
处的 api 端点中,一旦用户在 https://www.my-oidc-provider-endpoint
输入凭据后调用:
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const client = await authClientProvider.getClient();
const params = client.callbackParams(req);
const tokenSet = await client.callback(`${APP_URL}/api/auth/callback`, params/* , {code_verifier}*/);
setTokenCookies(req, res, tokenSet.access_token, tokenSet.refresh_token); // implemented elsewhere
res.redirect(308, process.env.NEXT_PUBLIC_APP_URL);
return res;
}
这一切正常,但没有实现 PKCE。所以我的问题是:
目前,我会将
code_verifier
作为 authorizationUrl
的一部分传递给客户端。这够了吗?但是我如何让它可用于我的回调端点api/auth/callback
,这是我所理解的纯服务器端?我是否必须使用 state
参数并以 code_verifier
作为服务器端的密钥缓存 state
?
我发现了一个类似的问题,但提问者似乎并不担心将其存储在cookie中(我必须先从
authorization_url
中刮掉它,无论如何原因是什么?如果是为了安全性,我可以在服务器端对其进行加密),并且他们似乎并不担心将其传递给服务器端的回调处理程序。我可以直接在客户端生成我的 code_verifier
(没有来自 generators
的 openid-client
的帮助),但这并没有让我如预期的那样,而且我仍然无法将它传递给api 回调。
(旁注:我不想使用NextAuth。实际上,我们来自那里,但它造成了太多麻烦。)
如果您可以将其存储在服务器端(加密它不是一个坏主意),那么这通常是更好的途径。麻烦出现在重定向和查找用于令牌交换的 code_verifier 上。您可以创建类似会话 ID 的内容并将其用作查找的键: https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#session-id-properties
另一种途径是加密并在 cookie 中发送,确保对 cookie 采取适当的预防措施: https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#server-security cookie 应该往返返回您可以解密的位置并将其用于令牌交换。这里的风险是有人可以访问和解密(如果没有充分加密)您的 code_verifier,因为它是通过网络调用传递的。