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

Add PKCE support (for v5-dev Typescript)

Open jcdogo opened this issue 5 years ago • 3 comments

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:

  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

Is this ever going to get merged? It would be amazing to have this functionality.

ghost avatar Feb 25 '21 19:02 ghost

You guys may want to check out this repo https://github.com/jasonraimondi/typescript-oauth2-server

miccoh1994 avatar May 12 '21 07:05 miccoh1994