NextJS 中的授权代码流程 - 如何将 PKCE code_verifier 传递给授权回调?

问题描述 投票:0回答:1

我已经使用 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。实际上,我们来自那里,但它造成了太多麻烦。)

next.js oauth-2.0 authorization server-side pkce
1个回答
0
投票

如果您可以将其存储在服务器端(加密它不是一个坏主意),那么这通常是更好的途径。麻烦出现在重定向和查找用于令牌交换的 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,因为它是通过网络调用传递的。

© www.soinside.com 2019 - 2024. All rights reserved.