node-oauth2-server
node-oauth2-server copied to clipboard
Add PKCE support
This pull implements PKCE support (RFC7636). It is originally based on pull #452, but has been cleaned up a bit.
Summary of changes:
- PKCE is completely optional. If the PKCE-related parameters (
code_challenge,code_challenge_method, andcode_verifier) are not passed to the server, the server behaves exactly the same as before. PKCE mode is enabled only when:
code_challenge(and optionallycode_challenge_method) parameters are included during authorization code grant.code_verifierparameter is included during token grant. Whencode_verifierparameter is included,client_secretis ignored since we are using PKCE for authentication.
- This change introduces 2 new optional fields (
codeChallengeandcodeChallengeMethod) to the authorization code model. Changes are required toModel#saveAuthorizationCodeandModel#getAuthorizationCodeto persist and retrieve these 2 new fields if they are present. - 100% backwards compatible with existing implementations. If existing servers do not update the
Model#saveAuthorizationCodeandModel#getAuthorizationCodemethods, they will continue to work just as they did before the change. - Added lots of tests and updated the documentation.
Example of my changes to saveAuthorizationCode for a MongoDB model (in Typescript):
const mongoOAuthCodeGrant = {
code: code.authorizationCode,
expires_at: code.expiresAt,
redirect_uri: code.redirectUri,
scope: code.scope,
client_id: client.id,
user_id: userId,
oauth_client_id: mongoOAuthClient._id,
};
if (code.codeChallenge) {
mongoOAuthCodeGrant.code_challenge = code.codeChallenge;
if (code.codeChallengeMethod) {
mongoOAuthCodeGrant.code_challenge_method = code.codeChallengeMethod;
}
}
const saveResult = await db
.collection(oauthAuthCodeGrantsCollectionName)
.insertOne(mongoOAuthCodeGrant);
Example of my changes to getAuthorizationCode for a MongoDB model (in Typescript)
const mongoAuthCodeGrant = await db
.collection(oauthAuthCodeGrantsCollectionName)
.findOne({code: authorizationCode});
const user = await getUserById(mongoAuthCodeGrant.user_id);
const client = await getClientById(mongoAuthCodeGrant.client_id);
const grant: OAuthCodeGrant = {
authorizationCode: mongoAuthCodeGrant.code,
expiresAt: mongoAuthCodeGrant.expires_at,
redirectUri: mongoAuthCodeGrant.redirect_uri,
scope: mongoAuthCodeGrant.scope,
client: client,
user: user,
};
if (mongoAuthCodeGrant.code_challenge) {
grant.codeChallenge = mongoAuthCodeGrant.code_challenge;
if (mongoAuthCodeGrant.code_challenge_method) {
grant.codeChallengeMethod = mongoAuthCodeGrant.code_challenge_method;
}
}
This partially addresses issue #637 by implementing PKCE.
@jcdogo thanks for your work. @thomseddon any idea on when this will land?
Can confirm that this implementation works well for practical purposes. Would love to get this well-reviewed and merged. Let me know if there's any help needed as we plan to use this in an open-source auth wrapper library.
In need of this as well :)
yeah definitely in need of this. @thomseddon any chance this could make it out soon? even the v5 version would be fine :)
We have a React frontend so the client secret is visible in the frontend code which is download by every user. We need the PKCE support.
I think we must merge this ASAP because npm audit fails on lack of support with PKCE support !
Thanks for this PR. I'd like to use this merge ASAP. @mjsalinger when could this PR be merged?