Skip to content
This repository has been archived by the owner on Feb 25, 2019. It is now read-only.

Commit

Permalink
support Hybrid Flow, multiple response types, and response_mode param…
Browse files Browse the repository at this point in the history
…eter
  • Loading branch information
christiansmith committed Aug 15, 2014
1 parent 195365b commit 05dc52c
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 47 deletions.
122 changes: 75 additions & 47 deletions lib/oidc/authorize.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

var crypto = require('crypto')
, async = require('async')
, IDToken = require('../../models/IDToken')
, AccessToken = require('../../models/AccessToken')
, AuthorizationCode = require('../../models/AuthorizationCode')
Expand All @@ -24,68 +25,95 @@ var crypto = require('crypto')
module.exports = function (server) {

return function authorize (req, res, next) {
var params = req.connectParams;
var params = req.connectParams
, responseTypes = params.response_type.split(' ')
, responseMode = params.response_mode
|| (responseTypes.indexOf('code') !== -1)
? '?'
: '#'
;

// ACCESS GRANTED
if (params.authorize === "true") {

// Authorization Code Grant
if (params.response_type === 'code') {
AuthorizationCode.insert({
// compose the response
async.waterfall([

client_id: req.client._id,
redirect_uri: params.redirect_uri,
max_age: parseInt(params.max_age) || req.client.default_max_age,
user_id: req.user._id,
scope: req.scope

}, function (err, ac) {
if (err) { return next(err); }

// Ugly to do this explicitly, but FormUrlencoded will add an
// empty state param if we pass an undefined state.
var response = {
code: ac.code
};

if (params.state) {
response.state = params.state;
function includeAccessToken (callback) {
if (responseTypes.indexOf('token') !== -1) {
AccessToken.issue(req, server, function (err, response) {
if (err) { return callback(err); }
callback(null, response);
});
}

res.redirect(params.redirect_uri + '?' + FormUrlencoded.encode(response));
});
}
// initialize an empty response
else {
callback(null, {});
}
},

function includeAuthorizationCode (response, callback) {
if (responseTypes.indexOf('code') !== -1) {
AuthorizationCode.insert({

client_id: req.client._id,
redirect_uri: params.redirect_uri,
max_age: parseInt(params.max_age) || req.client.default_max_age,
user_id: req.user._id,
scope: req.scope

}, function (err, ac) {
if (err) { return callback(err); }
response.code = ac.code;
callback(null, response);
});
}

// Implicit Grant
if (params.response_type === 'id_token token') {
AccessToken.issue(req, server, function (err, response) {
if (err) { return next(err); }
// pass through to next
else {
callback(null, response);
}
},

function includeIDToken (response, callback) {
if (responseTypes.indexOf('id_token') !== -1) {
var shasum, hash, atHash;

if (response.access_token) {
shasum = crypto.createHash('sha256');
shasum.update(response.access_token);
hash = shasum.digest('hex');
atHash = hash.slice(0, hash.length / 2);
}

var idToken = new IDToken({
iss: server.settings.issuer,
sub: req.user._id,
aud: req.client._id,
exp: Date.now() + (response.expires_in) * 1000,
nonce: params.nonce,
at_hash: atHash
});

response.id_token = idToken.encode(server.settings.privateKey);
}

var shasum, hash;
shasum = crypto.createHash('sha256');
shasum.update(response.access_token);
hash = shasum.digest('hex');
atHash = hash.slice(0, hash.length / 2);
callback(null, response);

var idToken = new IDToken({
iss: server.settings.issuer,
sub: req.user._id,
aud: req.client._id,
exp: Date.now() + (response.expires_in) * 1000,
nonce: params.nonce,
at_hash: atHash
});
}

response.id_token = idToken.encode(server.settings.privateKey);
], function (err, response) {
if (err) { return next(err); }

if (params.state) {
response.state = params.state
response.state = params.state;
}

res.redirect(params.redirect_uri + '#' + FormUrlencoded.encode(response));
});
}

res.redirect(
params.redirect_uri + responseMode + FormUrlencoded.encode(response)
);
});
}

// ACCESS DENIED
Expand Down
21 changes: 21 additions & 0 deletions lib/oidc/validateAuthorizationParams.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ var responseTypes = [
];


/**
* Supported response modes
*/

var responseModes = [
'query',
'fragment'
];


/**
* Validate Authorization Parameters
*
Expand Down Expand Up @@ -66,6 +76,17 @@ function validateAuthorizationParams (req, res, next) {
}));
}

// unsupported response mode
if (params.response_mode
&& responseModes.indexOf(params.response_mode) === -1) {
return next(new AuthorizationError({
error: 'unsupported_response_mode',
error_description: 'Unsupported response mode',
redirect_uri: params.redirect_uri,
statusCode: 302
}));
}

// missing client id
if (!params.client_id) {
return next(new AuthorizationError({
Expand Down

0 comments on commit 05dc52c

Please sign in to comment.