node-oauth2-server icon indicating copy to clipboard operation
node-oauth2-server copied to clipboard

Add PKCE support

Open jcdogo opened this issue 5 years ago • 8 comments

This pull implements PKCE support (RFC7636). It is originally based on pull #452, but has been cleaned up a bit.

Summary of changes:

  1. PKCE is completely optional. If the PKCE-related parameters (code_challenge, code_challenge_method, and code_verifier) are not passed to the server, the server behaves exactly the same as before. PKCE mode is enabled only when:
  • code_challenge (and optionally code_challenge_method) parameters are included during authorization code grant.
  • code_verifier parameter is included during token grant. When code_verifier parameter is included, client_secret is ignored since we are using PKCE for authentication.
  1. This change introduces 2 new optional fields (codeChallenge and codeChallengeMethod) to the authorization code model. Changes are required to Model#saveAuthorizationCode and Model#getAuthorizationCode to persist and retrieve these 2 new fields if they are present.
  2. 100% backwards compatible with existing implementations. If existing servers do not update the Model#saveAuthorizationCode and Model#getAuthorizationCode methods, they will continue to work just as they did before the change.
  3. 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;
    }
  }

jcdogo avatar Oct 08 '20 23:10 jcdogo

This partially addresses issue #637 by implementing PKCE.

jcdogo avatar Oct 08 '20 23:10 jcdogo

@jcdogo thanks for your work. @thomseddon any idea on when this will land?

jensdev avatar Dec 14 '20 15:12 jensdev

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.

Nedomas avatar Jan 22 '21 23:01 Nedomas

In need of this as well :)

fjeddy avatar Feb 07 '21 10:02 fjeddy

yeah definitely in need of this. @thomseddon any chance this could make it out soon? even the v5 version would be fine :)

yinzara avatar Feb 16 '21 01:02 yinzara

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.

Legion2 avatar Feb 20 '21 23:02 Legion2

I think we must merge this ASAP because npm audit fails on lack of support with PKCE support !

lior1503 avatar May 05 '21 08:05 lior1503

Thanks for this PR. I'd like to use this merge ASAP. @mjsalinger when could this PR be merged?

softwaredev927 avatar May 21 '22 15:05 softwaredev927