Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/state/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ SessionStore.prototype.store = function(req, ctx, appState, meta, cb) {
if (ctx.maxAge) { state.maxAge = ctx.maxAge; }
if (ctx.nonce) { state.nonce = ctx.nonce; }
if (ctx.issued) { state.issued = ctx.issued; }
if (ctx.pkceCodeVerifier) { state.pkceCodeVerifier = ctx.pkceCodeVerifier; }
if (appState) { state.state = appState; }

if (!req.session[key]) { req.session[key] = {}; }
Expand Down
30 changes: 29 additions & 1 deletion lib/strategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ var passport = require('passport-strategy')
, url = require('url')
, util = require('util')
, utils = require('./utils')
, base64url = require('base64url')
, crypto = require('crypto')
, OAuth2 = require('oauth').OAuth2
, Profile = require('./profile')
, Context = require('./context')
Expand Down Expand Up @@ -62,6 +64,8 @@ function Strategy(options, verify) {
this._idTokenHint = options.idTokenHint;
this._nonce = options.nonce;
this._claims = options.claims;
this._pkce = options.pkce;
this._pkceMethod = (options.pkce === true) ? 'S256' : options.pkce;

var key = options.sessionKey || (this.name + ':' + url.parse(options.authorizationURL).hostname);
this._stateStore = options.store || new SessionStateStore({ key: key });
Expand Down Expand Up @@ -129,6 +133,9 @@ Strategy.prototype.authenticate = function(req, options) {

var params = { grant_type: 'authorization_code' };
if (callbackURL) { params.redirect_uri = callbackURL; }
if (ctx.pkceCodeVerifier) {
params.code_verifier = ctx.pkceCodeVerifier;
}

self._oauth2.getOAuthAccessToken(code, params, function(err, accessToken, refreshToken, params) {
if (err) {
Expand Down Expand Up @@ -333,8 +340,29 @@ Strategy.prototype.authenticate = function(req, options) {
if (claims) {
params.claims = JSON.stringify(claims);
}

var ctx = {};

var verifier, challenge;

if (this._pkceMethod) {
verifier = base64url(crypto.pseudoRandomBytes(32))
switch (this._pkceMethod) {
case 'plain':
challenge = verifier;
break;
case 'S256':
challenge = base64url(crypto.createHash('sha256').update(verifier).digest());
break;
default:
return this.error(new Error('Unsupported code verifier transformation method: ' + this._pkceMethod));
}

params.code_challenge = challenge;
params.code_challenge_method = this._pkceMethod;
ctx.pkceCodeVerifier = verifier;
}

if (params.max_age) {
ctx.maxAge = params.max_age;
ctx.issued = new Date();
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"main": "./lib",
"dependencies": {
"oauth": "0.10.x",
"passport-strategy": "1.x.x"
"passport-strategy": "1.x.x",
"base64url": "3.x.x"
},
"devDependencies": {
"chai": "2.x.x",
Expand Down