Add PKCE support (for v5-dev Typescript)
This pull implements PKCE support (RFC7636). It is originally based on pull #452, but has been cleaned up a bit. Changes should be almost identical to pull #658, but cleaned up for Typescript.
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.
Is this ever going to get merged? It would be amazing to have this functionality.
You guys may want to check out this repo https://github.com/jasonraimondi/typescript-oauth2-server