I've implemented the OAuth2 Authorization Code Flow (without PKCE yet) in NextJS with the openid-client. Now where I should store the code_verifier
and how I could pass it to the invoked callback at server-side.
What I did so far (sketch):
// 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)
and in my api endpoint at api/auth/callback
, called once the user has entered their credentials at https://www.my-oidc-provider-endpoint.tld
:
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
return res.redirect(APP_URL);
}
This works all fine, but doesn't implement PKCE. So my question is:
At the moment, I would pass the code_verifier
to the client-side as a part of authorizationUrl
. Does this suffice? But how would I make it available to my callback endpoint api/auth/callback
, which is for all I understand pure server-side? Do I have to utilize the state
param and cache the code_verifier
with the state
as key at the server-side?
I've found a similar question, but the questioner don't seem to be troubled with storing it in cookies (I would have to scrape it from the authorization_url
first, and for what reason anyway? If it was for security, I could encrypt it at the server-side), and they don't seem to be troubled with passing it to the callback handler at the server-side. I could generate my code_verifier
directly on the client-side (without the help of the generators
from openid-client
), but this doesn't strike me as intended, and I still wouldn't be able to pass it to the api callback.
(Sidenote: I don't want to use NextAuth. Actually, we came from there, but it was causing too much trouble.)