Skip to content

Commit 626b498

Browse files
Update lib/ to reflect pr #10
1 parent f484bdc commit 626b498

3 files changed

Lines changed: 108 additions & 51 deletions

File tree

lib/AuthenticationResponse.js

Lines changed: 92 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,65 @@ var FormUrlEncoded = require('./FormUrlEncoded');
1919
var IDToken = require('./IDToken');
2020
var Session = require('./Session');
2121
var onHttpError = require('./onHttpError');
22+
var HttpError = require('standard-http-error');
2223

2324
/**
2425
* AuthenticationResponse
2526
*/
2627

2728
var AuthenticationResponse = function () {
28-
function AuthenticationResponse() {
29+
/**
30+
* @param rp {RelyingParty}
31+
* @param [redirect] {string} req.query
32+
* @param [body] {string} req.body.text
33+
* @param session {Session|Storage} req.session or localStorage or similar
34+
* @param params {object} hashmap
35+
* @param mode {string} 'query'/'fragment'/'form_post',
36+
* determined in `parseResponse()`
37+
*/
38+
function AuthenticationResponse(_ref) {
39+
var rp = _ref.rp,
40+
redirect = _ref.redirect,
41+
body = _ref.body,
42+
session = _ref.session,
43+
mode = _ref.mode,
44+
_ref$params = _ref.params,
45+
params = _ref$params === undefined ? {} : _ref$params;
46+
2947
_classCallCheck(this, AuthenticationResponse);
48+
49+
this.rp = rp;
50+
this.redirect = redirect;
51+
this.body = body;
52+
this.session = session;
53+
this.mode = mode;
54+
this.params = params;
3055
}
3156

32-
_createClass(AuthenticationResponse, null, [{
33-
key: 'validateResponse',
57+
/**
58+
* validateResponse
59+
*
60+
* @description
61+
* Authentication response validation.
62+
*
63+
* @param {string|Object} response
64+
*
65+
* @returns {Promise<Session>}
66+
*/
3467

3568

36-
/**
37-
* validateResponse
38-
*
39-
* @description
40-
* Authentication response validation.
41-
*
42-
* @param {string|Object} response
43-
* @returns {Promise}
44-
*/
69+
_createClass(AuthenticationResponse, null, [{
70+
key: 'validateResponse',
4571
value: function validateResponse(response) {
46-
return Promise.resolve(response).then(this.parseResponse).then(this.matchRequest).then(this.validateStateParam).then(this.errorResponse).then(this.validateResponseMode).then(this.validateResponseParams).then(this.exchangeAuthorizationCode).then(this.validateIDToken).then(Session.fromAuthResponse);
72+
return Promise.resolve(response).then(this.parseResponse).then(this.errorResponse).then(this.matchRequest).then(this.validateStateParam).then(this.validateResponseMode).then(this.validateResponseParams).then(this.exchangeAuthorizationCode).then(this.validateIDToken).then(Session.fromAuthResponse);
4773
}
4874

4975
/**
5076
* parseResponse
5177
*
52-
* @param {Object} response
53-
* @returns {Promise}
78+
* @param {object} response
79+
*
80+
* @returns {object}
5481
*/
5582

5683
}, {
@@ -62,7 +89,7 @@ var AuthenticationResponse = function () {
6289
// response must be either a redirect uri or request body, but not both
6390

6491
if (redirect && body || !redirect && !body) {
65-
throw new Error('Invalid response mode');
92+
throw new HttpError(400, 'Invalid response mode');
6693
}
6794

6895
// parse redirect uri
@@ -73,7 +100,7 @@ var AuthenticationResponse = function () {
73100

74101

75102
if (search && hash || !search && !hash) {
76-
throw new Error('Invalid response mode');
103+
throw new HttpError(400, 'Invalid response mode');
77104
}
78105

79106
if (search) {
@@ -96,6 +123,40 @@ var AuthenticationResponse = function () {
96123
return response;
97124
}
98125

126+
/**
127+
* errorResponse
128+
*
129+
* @param {AuthenticationResponse} response
130+
*
131+
* @throws {Error} If response params include the OAuth2 'error' param,
132+
* throws an error based on it.
133+
*
134+
* @returns {AuthenticationResponse} Chainable
135+
*
136+
* @todo Figure out HTTP status code (typically 400, 401 or 403)
137+
* based on the OAuth2/OIDC `error` code, probably using an external library
138+
*/
139+
140+
}, {
141+
key: 'errorResponse',
142+
value: function errorResponse(response) {
143+
var errorCode = response.params.error;
144+
145+
if (errorCode) {
146+
var errorParams = {};
147+
errorParams['error'] = errorCode;
148+
errorParams['error_description'] = response.params['error_description'];
149+
errorParams['error_uri'] = response.params['error_uri'];
150+
errorParams['state'] = response.params['state'];
151+
152+
var error = new Error('AuthenticationResponse error: ' + errorCode);
153+
error.info = errorParams;
154+
throw error;
155+
}
156+
157+
return response;
158+
}
159+
99160
/**
100161
* matchRequest
101162
*
@@ -150,25 +211,6 @@ var AuthenticationResponse = function () {
150211
});
151212
}
152213

153-
/**
154-
* errorResponse
155-
*
156-
* @param {Object} response
157-
* @returns {Promise}
158-
*/
159-
160-
}, {
161-
key: 'errorResponse',
162-
value: function errorResponse(response) {
163-
var error = response.params.error;
164-
165-
if (error) {
166-
return Promise.reject(error);
167-
}
168-
169-
return Promise.resolve(response);
170-
}
171-
172214
/**
173215
* validateResponseMode
174216
*
@@ -341,17 +383,28 @@ var AuthenticationResponse = function () {
341383
/**
342384
* decodeIDToken
343385
*
344-
* @param {Object} response
345-
* @returns {Promise}
386+
* Note: If the `id_token` is not present in params, this method does not
387+
* get called (short-circuited in `validateIDToken()`).
388+
*
389+
* @param response {AuthenticationResponse}
390+
* @param response.params {object}
391+
* @param [response.params.id_token] {string} IDToken encoded as a JWT
392+
*
393+
* @returns {AuthenticationResponse} Chainable
346394
*/
347395

348396
}, {
349397
key: 'decodeIDToken',
350398
value: function decodeIDToken(response) {
351399
var jwt = response.params.id_token;
352400

353-
if (jwt) {
401+
try {
354402
response.decoded = IDToken.decode(jwt);
403+
} catch (decodeError) {
404+
var error = new HttpError(400, 'Error decoding ID Token');
405+
error.cause = decodeError;
406+
error.info = { id_token: jwt };
407+
throw error;
355408
}
356409

357410
return response;

lib/RelyingParty.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,22 +212,26 @@ var RelyingParty = function (_JSONDocument) {
212212
*
213213
* @param response {string} req.query or req.body.text
214214
* @param session {Session|Storage} req.session or localStorage or similar
215-
* @returns {Promise<Object>} Custom response object, with `params` and
216-
* `mode` properties
215+
*
216+
* @returns {Promise<Session>}
217217
*/
218218

219219
}, {
220220
key: 'validateResponse',
221-
value: function validateResponse(response, session) {
222-
session = session || this.store;
221+
value: function validateResponse(response) {
222+
var session = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.store;
223+
224+
var options = void 0;
223225

224226
if (response.match(/^http(s?):\/\//)) {
225-
response = { rp: this, redirect: response, session: session };
227+
options = { rp: this, redirect: response, session: session };
226228
} else {
227-
response = { rp: this, body: response, session: session };
229+
options = { rp: this, body: response, session: session };
228230
}
229231

230-
return AuthenticationResponse.validateResponse(response);
232+
var authResponse = new AuthenticationResponse(options);
233+
234+
return AuthenticationResponse.validateResponse(authResponse);
231235
}
232236

233237
/**

lib/Session.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,15 @@ var Session = function () {
146146
/**
147147
* @param response {AuthenticationResponse}
148148
*
149-
* @returns {Session}
149+
* @returns {Session} RelyingParty Session object
150150
*/
151151

152152
}, {
153153
key: 'fromAuthResponse',
154154
value: function fromAuthResponse(response) {
155155
var RelyingParty = require('./RelyingParty'); // import here due to circular dep
156156

157-
var payload = response.decoded.payload;
157+
var idClaims = response.decoded && response.decoded.payload || {};
158158

159159
var rp = response.rp;
160160

@@ -169,14 +169,14 @@ var Session = function () {
169169
var options = {
170170
credentialType: credentialType,
171171
sessionKey: sessionKey,
172-
issuer: payload.iss,
172+
issuer: idClaims.iss,
173+
idClaims: idClaims,
173174
authorization: {
174175
client_id: registration['client_id'],
175176
access_token: response.params['access_token'],
176177
id_token: response.params['id_token'],
177178
refresh_token: response.params['refresh_token']
178-
},
179-
idClaims: response.decoded && response.decoded.payload
179+
}
180180
};
181181

182182
return Session.from(options);

0 commit comments

Comments
 (0)