feat(openid): add the openid connect `at_hash` value

This commit is contained in:
Vijay Budhram 2018-08-29 12:02:54 -04:00
Родитель fc17ee50ad
Коммит a42ba28e57
3 изменённых файлов: 63 добавлений и 38 удалений

Просмотреть файл

@ -448,14 +448,15 @@ function _validateJwtSub(sub) {
return sub;
}
function generateIdToken(options) {
function generateIdToken(options, access) {
var now = Math.floor(Date.now() / 1000);
var claims = {
sub: hex(options.userId),
aud: hex(options.clientId),
iss: ID_TOKEN_ISSUER,
iat: now,
exp: now + ID_TOKEN_EXPIRATION
exp: now + ID_TOKEN_EXPIRATION,
at_hash: util.generateTokenHash(access.token)
};
if (options.amr) {
claims.amr = options.amr;
@ -467,42 +468,43 @@ function generateIdToken(options) {
return ID_TOKEN_KEY.sign(claims);
}
function generateTokens(options) {
function generateTokens (options) {
// we always are generating an access token here
// but depending on options, we may also be generating a refresh_token
var promises = {
access: db.generateAccessToken(options)
};
if (options.offline) {
promises.refresh = db.generateRefreshToken(options);
}
if (options.idToken) {
promises.idToken = generateIdToken(options);
}
return P.props(promises).then(function(result) {
var access = result.access;
var refresh = result.refresh;
var idToken = result.idToken;
return db.generateAccessToken(options)
.then((access) => {
const promises = {};
if (options.offline) {
promises.refresh = db.generateRefreshToken(options);
}
if (options.idToken) {
promises.idToken = generateIdToken(options, access);
}
var json = {
access_token: access.token.toString('hex'),
token_type: access.type,
scope: access.scope.toString()
};
if (options.authAt) {
json.auth_at = options.authAt;
}
json.expires_in = options.ttl;
if (refresh) {
json.refresh_token = refresh.token.toString('hex');
}
if (idToken) {
json.id_token = idToken;
}
if (options.keysJwe) {
json.keys_jwe = options.keysJwe;
}
return json;
});
return P.props(promises).then(function (result) {
const refresh = result.refresh;
const idToken = result.idToken;
const json = {
access_token: access.token.toString('hex'),
token_type: access.type,
scope: access.scope.toString()
};
if (options.authAt) {
json.auth_at = options.authAt;
}
json.expires_in = options.ttl;
if (refresh) {
json.refresh_token = refresh.token.toString('hex');
}
if (idToken) {
json.id_token = idToken;
}
if (options.keysJwe) {
json.keys_jwe = options.keysJwe;
}
return json;
});
});
}

Просмотреть файл

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const encrypt = require('./encrypt');
/**
* .base64URLEncode
*
@ -22,6 +24,23 @@ const base64URLEncode = function base64URLEncode(buf) {
.replace(/=/g, '');
};
module.exports = {
base64URLEncode: base64URLEncode
/**
* Generates a hash of the access token based on
* http://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
*
* This value is the hash of the ascii value of the access token, then the base64url
* value of the left half.
*
* @param {Buffer} accessTokenBuf
* @returns {String}
* @api public
*/
const generateTokenHash = function generateTokenHash (accessTokenBuf) {
const hash = encrypt.hash(accessTokenBuf.toString('ascii'));
return base64URLEncode(hash.slice(0, hash.length / 2));
};
module.exports = {
base64URLEncode: base64URLEncode,
generateTokenHash: generateTokenHash
};

Просмотреть файл

@ -17,6 +17,7 @@ const encrypt = require('../lib/encrypt');
const P = require('../lib/promise');
const Server = require('./lib/server');
const unique = require('../lib/unique');
const util = require('../lib/util');
const assertSecurityHeaders = require('./lib/util').assertSecurityHeaders;
@ -1952,6 +1953,9 @@ describe('/v1', function() {
assert.deepEqual(claims.amr, AMR);
assert.equal(claims.acr, ACR);
assert.equal(claims['fxa-aal'], AAL);
const at_hash = util.generateTokenHash(Buffer.from(res.result.access_token, 'hex'));
assert.equal(claims.at_hash, at_hash);
});
});