diff --git a/.gitignore b/.gitignore index 1bc2be1..c6d04ab 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ build/Release # Dependency directoryand lockfiles node_modules yarn.lock +package-lock.json npm-shrinkwrap.json # Optional npm cache directory diff --git a/.nvmrc b/.nvmrc index 5debbed..2bf5ad0 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -lts/carbon +stable diff --git a/package.json b/package.json index 2ca5a12..bd32b52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openid-client-conformance-tests", - "version": "2.0.0", + "version": "3.0.0", "description": "node's openid-client library conformance tests", "scripts": { "test": "mocha", @@ -12,31 +12,29 @@ "id_token+token-implicit": "mocha --fgrep @id_token+token-implicit", "code+id_token-hybrid": "mocha --fgrep @code+id_token-hybrid", "code+token-hybrid": "mocha --fgrep @code+token-hybrid", - "code+id_token+token-hybrid": "mocha --fgrep @code+id_token+token-hybrid", - "coverage": "istanbul cover --root node_modules/openid-client _mocha" + "code+id_token+token-hybrid": "mocha --fgrep @code+id_token+token-hybrid" }, "repository": "panva/openid-client-conformance-tests", "engines": { - "node": ">=7.6.0" + "node": ">=12.0.0" }, "homepage": "https://github.com/panva/openid-client-conformance-tests", "author": "Filip Skokan", "license": "MIT", "dependencies": { - "base64url": "^2.0.0", - "fs-extra": "^1.0.0", + "base64url": "^3.0.1", + "fs-extra": "^7.0.1", "got": "^9.6.0", "lodash": "^4.17.11", - "mocha": "^3.1.2", - "nock": "^9.6.1", - "openid-client": "^2.0.0", - "tar": "^2.2.1", - "timekeeper": "^1.0.0" + "mocha": "^6.1.4", + "nock": "^11.0.0-beta.14", + "openid-client": "^3.0.0", + "tar": "^4.4.8", + "timekeeper": "^2.2.0" }, "devDependencies": { - "eslint": "^3.9.1", - "eslint-config-airbnb-base": "^10.0.0", - "eslint-plugin-import": "^2.16.0", - "istanbul": "next" + "eslint": "^5.16.0", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-plugin-import": "^2.17.2" } } diff --git a/test/claim-types.js b/test/claim-types.js index c489741..fc0cf8d 100644 --- a/test/claim-types.js +++ b/test/claim-types.js @@ -1,4 +1,4 @@ -'use strict'; +const { strict: assert } = require('assert'); const { noFollow, @@ -6,19 +6,17 @@ const { register, describe, authorize, - authorizationCallback, + callback, it, } = require('./helper'); -const assert = require('assert'); - describe('Claim Types', function () { it('rp-claims-aggregated', async function () { const response_type = 'code'; const { client } = await register('rp-claims-aggregated', { }); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); const userinfo = await client.userinfo(tokens); const aggregated = await client.unpackAggregatedClaims(userinfo); assert(aggregated.shoe_size); @@ -30,7 +28,7 @@ describe('Claim Types', function () { const { client } = await register('rp-claims-distributed', { }); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); const userinfo = await client.userinfo(tokens); const distributed = await client.fetchDistributedClaims(userinfo); assert(distributed.age); diff --git a/test/claims-request-parameter.js b/test/claims-request-parameter.js index fd7c9e2..0cd1d81 100644 --- a/test/claims-request-parameter.js +++ b/test/claims-request-parameter.js @@ -1,4 +1,4 @@ -'use strict'; +const { strict: assert } = require('assert'); const base64url = require('base64url'); const { @@ -7,19 +7,17 @@ const { register, describe, authorize, - authorizationCallback, + callback, it, } = require('./helper'); -const assert = require('assert'); - describe('claims Request Parameter', function () { it('rp-claims_request-id_token', async function () { const response_type = 'code'; const { client } = await register('rp-claims_request-id_token', { }); const authorization = await authorize(client.authorizationUrl({ claims: { id_token: { name: null } }, redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const { id_token: idToken } = await authorizationCallback(client, redirect_uri, params, { response_type }); + const { id_token: idToken } = await callback(client, redirect_uri, params, { response_type }); assert(JSON.parse(base64url.decode(idToken.split('.')[1])).name); }); @@ -28,7 +26,7 @@ describe('claims Request Parameter', function () { const { client } = await register('rp-claims_request-userinfo', { }); const authorization = await authorize(client.authorizationUrl({ claims: { userinfo: { name: null } }, redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); const userinfo = await client.userinfo(tokens); assert(userinfo.name); }); diff --git a/test/client-authentication.js b/test/client-authentication.js index 8b9a2aa..2a661a5 100644 --- a/test/client-authentication.js +++ b/test/client-authentication.js @@ -1,19 +1,18 @@ -'use strict'; +const { strict: assert } = require('assert'); const { forEach } = require('lodash'); -const jose = require('node-jose'); // eslint-disable-line import/no-extraneous-dependencies +const jose = require('@panva/jose'); // eslint-disable-line import/no-extraneous-dependencies const { noFollow, redirect_uri, register, describe, authorize, - authorizationCallback, + callback, it, + random, } = require('./helper'); -const assert = require('assert'); - describe('Client Authentication', function () { describe('rp-token_endpoint-client_secret_basic', function () { forEach({ @@ -25,11 +24,11 @@ describe('Client Authentication', function () { it(profile, async function () { const { client } = await register('rp-token_endpoint-client_secret_basic', { token_endpoint_auth_method: 'client_secret_basic' }); assert.equal(client.token_endpoint_auth_method, 'client_secret_basic'); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); assert(tokens); }); }); @@ -42,7 +41,7 @@ describe('Client Authentication', function () { const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); @@ -53,20 +52,20 @@ describe('Client Authentication', function () { const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); it('rp-token_endpoint-private_key_jwt', async function () { - const keystore = jose.JWK.createKeyStore(); - await keystore.generate('EC', 'P-256'); + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('EC'); const response_type = 'code'; const { client } = await register('rp-token_endpoint-private_key_jwt', { token_endpoint_auth_method: 'private_key_jwt' }, keystore); assert.equal(client.token_endpoint_auth_method, 'private_key_jwt'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); }); diff --git a/test/discovery.js b/test/discovery.js index 378799d..fc8170a 100644 --- a/test/discovery.js +++ b/test/discovery.js @@ -1,9 +1,11 @@ -'use strict'; - /* eslint-disable no-restricted-syntax */ const url = require('url'); const { Issuer } = require('openid-client'); + +const { strict: assert } = require('assert'); +const got = require('got'); +const nock = require('nock'); const { discover, noFollow, @@ -14,10 +16,6 @@ const { it, } = require('./helper'); -const assert = require('assert'); -const got = require('got'); -const nock = require('nock'); - afterEach(nock.cleanAll); afterEach(() => nock.enableNetConnect()); @@ -26,7 +24,7 @@ describe('Discovery', function () { const testId = 'rp-discovery-webfinger-url'; const input = `${root}/${rpId}/${testId}/joe`; const issuer = await Issuer.webfinger(input); - log('webfinger using', input, 'discovered', issuer.issuer); + log('webfinger using', input, 'discovered', issuer.issuer, JSON.stringify(issuer, null, 4)); assert.equal(issuer.issuer, `${root}/${rpId}/${testId}`); }); @@ -34,7 +32,7 @@ describe('Discovery', function () { const testId = 'rp-discovery-webfinger-acct'; const input = `acct:${rpId}.${testId}@${url.parse(root).host}`; const issuer = await Issuer.webfinger(input); - log('webfinger using', input, 'discovered', issuer.issuer); + log('webfinger using', input, 'discovered', issuer.issuer, JSON.stringify(issuer, null, 4)); assert.equal(issuer.issuer, `${root}/${rpId}/${testId}`); }); @@ -46,7 +44,7 @@ describe('Discovery', function () { reject(); } catch (err) { log('caught', err); - assert.equal(err.message, 'discovered issuer mismatch'); + assert.equal(err.message, `discovered issuer mismatch, expected ${root}/${rpId}/rp-discovery-issuer-not-matching-config, got: https://example.com`); } }); @@ -73,7 +71,7 @@ describe('Discovery', function () { const jwks = await issuer.keystore(); assert.equal(jwks.all().length, 4); - log('fetched jwks_uri', JSON.stringify(jwks.toJSON(), null, 4)); + log('fetched jwks_uri', JSON.stringify(jwks.toJWKS(), null, 4)); }); it('rp-discovery-webfinger-unknown-member', async function () { @@ -91,7 +89,7 @@ describe('Discovery', function () { reject(); } catch (err) { log('caught', err); - assert.equal(err.message, 'invalid issuer location'); + assert.equal(err.message, `invalid issuer location ${root.replace('https:', 'http:')}/${rpId}/rp-discovery-webfinger-http-href`); } }); }); diff --git a/test/dynamic-client-registration.js b/test/dynamic-client-registration.js index 0b93203..e8384f9 100644 --- a/test/dynamic-client-registration.js +++ b/test/dynamic-client-registration.js @@ -1,4 +1,4 @@ -'use strict'; +const { strict: assert } = require('assert'); const { register, @@ -6,8 +6,6 @@ const { it, } = require('./helper'); -const assert = require('assert'); - describe('Dynamic Client Registration', function () { it('rp-registration-dynamic @code-dynamic', async function () { const { client, issuer } = await register('rp-registration-dynamic', { }); diff --git a/test/helper.js b/test/helper.js index ea9354a..8089271 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,8 +1,6 @@ -'use strict'; - /* eslint-disable no-console */ -const { Issuer } = require('openid-client'); +const { Issuer, custom } = require('openid-client'); const path = require('path'); const fse = require('fs-extra'); const fs = require('fs'); @@ -10,6 +8,11 @@ const tar = require('tar'); const got = require('got'); const url = require('url'); const timekeeper = require('timekeeper'); +const base64url = require('base64url'); +const crypto = require('crypto'); + +const timeout = opts => Object.assign({ timeout: 5000 }, opts); +Issuer[custom.http_options] = timeout; let rpId = 'node-openid-client'; const echoUrl = 'https://limitless-retreat-96294.herokuapp.com'; @@ -17,10 +20,16 @@ const root = process.env.ISSUER || 'https://rp.certification.openid.net:8080'; const redirectUri = `https://${rpId}.dev/cb`; const [responseType, profile] = (() => { - const last = process.argv[process.argv.length - 1]; - if (last.startsWith('@')) { - return last.slice(1).split('-'); + const fgrep = process.argv.findIndex(a => a === '--fgrep'); + if (fgrep === -1) { + return []; } + + const value = process.argv[fgrep + 1]; + if (value.startsWith('@')) { + return value.slice(1).split('-'); + } + return []; })(); @@ -28,6 +37,10 @@ if (responseType && profile) { rpId = `${rpId}-${profile}-${responseType}`; } +console.log('RP Identifier', rpId); +const logsLocation = `${root}/log/${rpId}`; +console.log('Logs location', logsLocation); + async function syncTime() { const { headers: { date } } = await got.head(root); timekeeper.travel(new Date(date)); @@ -36,7 +49,7 @@ async function syncTime() { before(syncTime); before(async function () { - const logIndex = await got(`${root}/log/${rpId}`); + const logIndex = await got(logsLocation); if (/Clear all test logs/.exec(logIndex.body)) { console.log('Clearing logs'); await got(`${root}/clear/${rpId}`); @@ -45,22 +58,20 @@ before(async function () { }); before(function kickstartEcho() { - return got.get(echoUrl).then(() => {}, () => {}); + return got.get(echoUrl).catch(() => {}); }); -Issuer.defaultHttpOptions = { timeout: 5000 }; - if (profile) { const profileFolder = path.resolve('logs', profile); fse.emptyDirSync(`${profileFolder}/${responseType}`); after(async function () { - const logIndex = await got(`${root}/log/${rpId}`); + const logIndex = await got(logsLocation); if (/Download tar file/.exec(logIndex.body)) { await new Promise((resolve, reject) => { console.log('Downloading logs'); got.stream(`${root}/mktar/${rpId}`) - .pipe(tar.Extract({ - path: profileFolder, + .pipe(tar.x({ + cwd: profileFolder, })) .on('close', () => { fse.move(`${profileFolder}/${rpId}`, `${profileFolder}/${responseType}`, { @@ -83,7 +94,9 @@ let testId; global.log = function () {}; function myIt(...args) { - if (args[0].startsWith('rp-')) testId = args[0]; + if (args[0].startsWith('rp-')) { + [testId] = args; + } const localTestId = testId.includes(' ') ? testId.substring(0, testId.indexOf(' ')) : testId; if (args[1]) { it(args[0], async function () { @@ -117,14 +130,16 @@ myIt.skip = it.skip; myIt.only = it.only; function myDescribe(...args) { - if (args[0].startsWith('rp-')) testId = args[0]; + if (args[0].startsWith('rp-')) { + [testId] = args; + } describe.apply(this, args); } myDescribe.skip = describe.skip; myDescribe.only = describe.only; module.exports = { - noFollow: { followRedirect: false }, + noFollow: { timeout: 5000, followRedirect: false }, root, it: myIt, describe: myDescribe, @@ -132,9 +147,9 @@ module.exports = { syncTime, redirect_uri: redirectUri, redirect_uris: [redirectUri], - async authorizationCallback(client, ...params) { + async callback(client, ...params) { try { - const res = await client.authorizationCallback(...params); + const res = await client.callback(...params); log('authentication callback succeeded', JSON.stringify(res, null, 4)); return res; } catch (err) { @@ -163,15 +178,17 @@ module.exports = { }, async discover(test) { const issuer = await Issuer.discover(`${root}/${rpId}/${test}`); - log('discovered', issuer.issuer); + issuer[custom.http_options] = timeout; + log('discovered', issuer.issuer, JSON.stringify(issuer, null, 4)); return issuer; }, async register(test, metadata, keystore) { const issuer = await Issuer.discover(`${root}/${rpId}/${test}`); - log('discovered', issuer.issuer); + issuer[custom.http_options] = timeout; + log('discovered', issuer.issuer, JSON.stringify(issuer, null, 4)); const properties = Object.assign({ - client_name: Issuer.defaultHttpOptions.headers['User-Agent'], + client_name: 'openid-client/v3.x (https://github.com/panva/node-openid-client)', redirect_uris: [redirectUri], contacts: ['dummy@dummy.org'], response_types: responseType ? [responseType.replace(/\+/g, ' ')] : ['code', 'id_token', 'code token', 'code id_token', 'id_token token', 'code id_token token', 'none'], @@ -179,11 +196,13 @@ module.exports = { }, metadata); log('registering client', JSON.stringify(properties, null, 4)); - const client = await issuer.Client.register(properties, { keystore }); + const client = await issuer.Client.register(properties, { jwks: (keystore && keystore.toJWKS(true)) || undefined }); log('registered client', client.client_id, JSON.stringify(client.metadata, null, 4)); - client.CLOCK_TOLERANCE = 5; + client[custom.http_options] = timeout; + client[custom.clock_tolerance] = 5; return { issuer, client }; }, + random() { return base64url(crypto.randomBytes(32)); }, reject() { throw new Error('expected a rejection'); }, echo: { async post(body, type) { diff --git a/test/id-token.js b/test/id-token.js index 32611e2..05a514b 100644 --- a/test/id-token.js +++ b/test/id-token.js @@ -1,20 +1,21 @@ -'use strict'; +const { strict: assert } = require('assert'); const { forEach } = require('lodash'); -const jose = require('node-jose'); // eslint-disable-line import/no-extraneous-dependencies +const jose = require('@panva/jose'); // eslint-disable-line import/no-extraneous-dependencies const { noFollow, redirect_uri, register, reject, + root, describe, + rpId, + random, authorize, - authorizationCallback, + callback, it, } = require('./helper'); -const assert = require('assert'); - describe('ID Token', function () { describe('rp-id_token-bad-sig-rs256', function () { forEach({ @@ -28,15 +29,15 @@ describe('ID Token', function () { it(profile, async function () { const { client } = await register('rp-id_token-bad-sig-rs256', { id_token_signed_response_alg: 'RS256' }); assert.equal(client.id_token_signed_response_alg, 'RS256'); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { - assert.equal(err.message, 'invalid signature'); + assert.equal(err.message, 'failed to validate JWT signature'); } }); }); @@ -50,24 +51,24 @@ describe('ID Token', function () { const params = client.callbackParams(authorization.headers.location); try { - await authorizationCallback(client, redirect_uri, params, { response_type }); + await callback(client, redirect_uri, params, { response_type }); reject(); } catch (err) { - assert.equal(err.message, 'invalid signature'); + assert.equal(err.message, 'failed to validate JWT signature'); } }); it('rp-id_token-sig+enc', async function () { const response_type = 'code'; - const keystore = jose.JWK.createKeyStore(); - await keystore.generate('RSA', 512); + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('RSA'); const { client } = await register('rp-id_token-sig+enc', { id_token_signed_response_alg: 'RS256', id_token_encrypted_response_alg: 'RSA1_5' }, keystore); assert.equal(client.id_token_signed_response_alg, 'RS256'); assert.equal(client.id_token_encrypted_response_alg, 'RSA1_5'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); @@ -83,11 +84,11 @@ describe('ID Token', function () { it(profile, async function () { const { client } = await register('rp-id_token-sig-rs256', { id_token_signed_response_alg: 'RS256' }); assert.equal(client.id_token_signed_response_alg, 'RS256'); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); assert(tokens); }); }); @@ -100,7 +101,7 @@ describe('ID Token', function () { const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); @@ -111,7 +112,7 @@ describe('ID Token', function () { const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); @@ -128,7 +129,7 @@ describe('ID Token', function () { const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); @@ -139,7 +140,7 @@ describe('ID Token', function () { const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens.id_token); }); @@ -150,15 +151,15 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-bad-c_hash', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { - assert.equal(err.message, 'c_hash mismatch'); + assert(err.message.match(/^c_hash mismatch, expected \S+, got: \S+$/)); } }); }); @@ -171,12 +172,12 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-missing-c_hash', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { assert.equal(err.message, 'missing required property c_hash'); @@ -192,15 +193,15 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-bad-at_hash', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { - assert.equal(err.message, 'at_hash mismatch'); + assert(err.message.match(/^at_hash mismatch, expected \S+, got: \S+$/)); } }); }); @@ -213,12 +214,12 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-missing-at_hash', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { assert.equal(err.message, 'missing required property at_hash'); @@ -238,15 +239,15 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-issuer-mismatch', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { - assert.equal(err.message, 'unexpected iss value'); + assert.equal(err.message, `unexpected iss value, expected ${root}/${rpId}/rp-id_token-issuer-mismatch, got: https://example.org/`); } }); }); @@ -263,12 +264,12 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-iat', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { assert.equal(err.message, 'missing required JWT property iat'); @@ -286,10 +287,10 @@ describe('ID Token', function () { const params = client.callbackParams(authorization.headers.location); try { - await authorizationCallback(client, redirect_uri, params, { response_type }); + await callback(client, redirect_uri, params, { response_type }); reject(); } catch (err) { - assert.equal(err.message, 'invalid signature'); + assert.equal(err.message, 'failed to validate JWT signature'); } }); @@ -304,15 +305,15 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-aud', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { - assert.equal(err.message, 'aud is missing the client_id'); + assert.equal(err.message, `aud is missing the client_id, expected ${client.client_id} to be included in ["https://example.com/"]`); } }); }); @@ -329,12 +330,12 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-sub', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { assert.equal(err.message, 'missing required JWT property sub'); @@ -354,11 +355,11 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-kid-absent-single-jwks', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); assert(tokens); }); }); @@ -375,15 +376,15 @@ describe('ID Token', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-id_token-kid-absent-multiple-jwks', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, nonce, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { - assert.equal(err.message, 'multiple matching keys, kid must be provided'); + assert.equal(err.message, 'multiple matching keys found in issuer\'s jwks_uri for key parameters {"alg":"RS256"}, kid must be provided in this case'); } }); }); diff --git a/test/key-rotation.js b/test/key-rotation.js index 237afa2..7dc1b37 100644 --- a/test/key-rotation.js +++ b/test/key-rotation.js @@ -1,36 +1,84 @@ -'use strict'; - +const jose = require('@panva/jose'); // eslint-disable-line import/no-extraneous-dependencies +const { strict: assert } = require('assert'); +const timekeeper = require('timekeeper'); const { register, + random, + echo, noFollow, redirect_uri, describe, authorize, - authorizationCallback, + callback, it, syncTime, } = require('./helper'); -const assert = require('assert'); -const timekeeper = require('timekeeper'); - afterEach(syncTime); describe('Key Rotation', function () { it('rp-key-rotation-op-sign-key @code-config,@code-dynamic', async function () { const response_type = 'code'; const { client } = await register('rp-key-rotation-op-sign-key', { }); - const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); - const params = client.callbackParams(authorization.headers.location); - await authorizationCallback(client, redirect_uri, params, { response_type }); + let authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); + let params = client.callbackParams(authorization.headers.location); + await callback(client, redirect_uri, params, { response_type }); + + // await issuer.keystore(true); + timekeeper.travel(Date.now() + (61 * 1000)); // travel one minute from now, making the cached keystore stale + + authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); + params = client.callbackParams(authorization.headers.location); + const tokens = await callback(client, redirect_uri, params, { response_type }); + assert(tokens); + }); + + it('rp-key-rotation-op-sign-key-native @code-config,@code-dynamic', async function () { + const response_type = 'code'; + const { client } = await register('rp-key-rotation-op-sign-key-native', { }); + let authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); + let params = client.callbackParams(authorization.headers.location); + await callback(client, redirect_uri, params, { response_type }); timekeeper.travel(Date.now() + (61 * 1000)); // travel one minute from now, making the cached keystore stale - const secondAuthorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); - const secondParams = client.callbackParams(secondAuthorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, secondParams, { response_type }); + authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); + params = client.callbackParams(authorization.headers.location); + const tokens = await callback(client, redirect_uri, params, { response_type }); assert(tokens); }); - it('rp-key-rotation-op-enc-key'); + it('rp-key-rotation-op-enc-key', async function () { + const response_type = 'code'; + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('RSA'); + + const { issuer, client } = await register('rp-key-rotation-op-enc-key', { + request_object_signing_alg: 'RS256', + request_object_encryption_alg: 'RSA-OAEP', + request_object_encryption_enc: 'A128CBC-HS256', + }, keystore); + assert.equal(client.request_object_signing_alg, 'RS256'); + assert.equal(client.request_object_encryption_alg, 'RSA-OAEP'); + assert.equal(client.request_object_encryption_enc, 'A128CBC-HS256'); + + let state = random(); + let requestObject = await client.requestObject({ state }); + let request_uri = await echo.post(requestObject, 'application/jwt'); + + let authorization = await authorize(client.authorizationUrl({ redirect_uri, request_uri, response_type }), noFollow); + let params = client.callbackParams(authorization.headers.location); + await callback(client, redirect_uri, params, { response_type, state }); + + await issuer.keystore(true); + + state = random(); + requestObject = await client.requestObject({ state }); + request_uri = await echo.post(requestObject, 'application/jwt'); + + authorization = await authorize(client.authorizationUrl({ redirect_uri, request_uri, response_type }), noFollow); + params = client.callbackParams(authorization.headers.location); + const tokens = await callback(client, redirect_uri, params, { response_type, state }); + assert(tokens); + }); }); diff --git a/test/nonce-request-parameter.js b/test/nonce-request-parameter.js index 403a2cc..3c29ab9 100644 --- a/test/nonce-request-parameter.js +++ b/test/nonce-request-parameter.js @@ -1,31 +1,29 @@ -'use strict'; +const { strict: assert } = require('assert'); const { forEach } = require('lodash'); const { noFollow, redirect_uri, register, + random, reject, describe, authorize, - authorizationCallback, + callback, it, } = require('./helper'); -const assert = require('assert'); - describe('nonce Request Parameter', function () { describe('rp-nonce-unless-code-flow', function () { forEach({ '@id_token-implicit': 'id_token', '@id_token+token-implicit': 'id_token token', '@code+id_token-hybrid': 'code id_token', - '@code+token-hybrid': 'code token', '@code+id_token+token-hybrid': 'code id_token token', }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-nonce-unless-code-flow', { }); - const nonce = String(Math.random()); + const nonce = random(); try { client.authorizationUrl({ redirect_uri, response_type }); reject(); @@ -35,7 +33,7 @@ describe('nonce Request Parameter', function () { const authorization = await authorize(client.authorizationUrl({ nonce, redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); assert(tokens); }); }); @@ -52,15 +50,15 @@ describe('nonce Request Parameter', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-nonce-invalid', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type, nonce }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + await callback(client, redirect_uri, params, { nonce, response_type }); reject(); } catch (err) { - assert.equal(err.message, 'nonce mismatch'); + assert.equal(err.message, `nonce mismatch, expected ${nonce}, got: 012345678`); } }); }); diff --git a/test/request-uri-request-parameter.js b/test/request-uri-request-parameter.js index ad874be..9fa3cc0 100644 --- a/test/request-uri-request-parameter.js +++ b/test/request-uri-request-parameter.js @@ -1,7 +1,5 @@ -'use strict'; - -const assert = require('assert'); -const jose = require('node-jose'); // eslint-disable-line import/no-extraneous-dependencies +const { strict: assert } = require('assert'); +const jose = require('@panva/jose'); // eslint-disable-line import/no-extraneous-dependencies const { echo, @@ -10,42 +8,42 @@ const { noFollow, describe, authorize, - authorizationCallback, + callback, it, } = require('./helper'); describe('request_uri Request Parameter', function () { it('rp-request_uri-enc', async function () { const response_type = 'code'; - const keystore = jose.JWK.createKeyStore(); - await keystore.generate('RSA', 1024); + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('RSA'); const { client } = await register('rp-request_uri-enc', { - request_object_signing_alg: 'none', - request_object_encryption_alg: 'RSA1_5', + request_object_signing_alg: 'RS256', + request_object_encryption_alg: 'RSA-OAEP', request_object_encryption_enc: 'A128CBC-HS256', }, keystore); const requestObject = await client.requestObject({ state: 'foobar' }); const request_uri = await echo.post(requestObject, 'application/jwt'); - assert.equal(client.request_object_signing_alg, 'none'); - assert.equal(client.request_object_encryption_alg, 'RSA1_5'); + assert.equal(client.request_object_signing_alg, 'RS256'); + assert.equal(client.request_object_encryption_alg, 'RSA-OAEP'); assert.equal(client.request_object_encryption_enc, 'A128CBC-HS256'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, request_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - await authorizationCallback(client, redirect_uri, params, { state: 'foobar', response_type }); + await callback(client, redirect_uri, params, { state: 'foobar', response_type }); }); it('rp-request_uri-sig+enc', async function () { const response_type = 'code'; - const keystore = jose.JWK.createKeyStore(); - await keystore.generate('RSA', 1024); + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('RSA'); const { client } = await register('rp-request_uri-sig+enc', { request_object_signing_alg: 'RS256', - request_object_encryption_alg: 'RSA1_5', + request_object_encryption_alg: 'RSA-OAEP', request_object_encryption_enc: 'A128CBC-HS256', }, keystore); @@ -53,12 +51,12 @@ describe('request_uri Request Parameter', function () { const request_uri = await echo.post(requestObject, 'application/jwt'); assert.equal(client.request_object_signing_alg, 'RS256'); - assert.equal(client.request_object_encryption_alg, 'RSA1_5'); + assert.equal(client.request_object_encryption_alg, 'RSA-OAEP'); assert.equal(client.request_object_encryption_enc, 'A128CBC-HS256'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, request_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - await authorizationCallback(client, redirect_uri, params, { state: 'foobar', response_type }); + await callback(client, redirect_uri, params, { state: 'foobar', response_type }); }); it('rp-request_uri-unsigned @code-dynamic', async function () { @@ -69,16 +67,13 @@ describe('request_uri Request Parameter', function () { assert.equal(client.request_object_signing_alg, 'none'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, request_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - await authorizationCallback(client, redirect_uri, params, { state: 'foobar', response_type }); + await callback(client, redirect_uri, params, { state: 'foobar', response_type }); }); it('rp-request_uri-sig @code-dynamic', async function () { const response_type = 'code'; - const keystore = jose.JWK.createKeyStore(); - await keystore.generate('RSA', 1024, { - use: 'sig', - alg: 'RS256', - }); + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('RSA'); const { client } = await register('rp-request_uri-sig', { request_object_signing_alg: 'RS256' }, keystore); const requestObject = await client.requestObject({ state: 'foobar' }); @@ -86,6 +81,6 @@ describe('request_uri Request Parameter', function () { assert.equal(client.request_object_signing_alg, 'RS256'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, request_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - await authorizationCallback(client, redirect_uri, params, { state: 'foobar', response_type }); + await callback(client, redirect_uri, params, { state: 'foobar', response_type }); }); }); diff --git a/test/response-type-and-response-mode.js b/test/response-type-and-response-mode.js index 4ede1a2..fff0714 100644 --- a/test/response-type-and-response-mode.js +++ b/test/response-type-and-response-mode.js @@ -1,22 +1,20 @@ -'use strict'; - +const { forEach } = require('lodash'); +const { strict: assert } = require('assert'); +const url = require('url'); +const got = require('got'); +const querystring = require('querystring'); const { noFollow, redirect_uri, register, describe, + random, authorize, reject, - authorizationCallback, + callback, it, } = require('./helper'); -const { forEach } = require('lodash'); -const assert = require('assert'); -const url = require('url'); -const got = require('got'); -const querystring = require('querystring'); - describe('Response Type and Response Mode', function () { it('rp-response_type-code @code-basic', async function () { const { client } = await register('rp-response_type-code', { }); @@ -27,7 +25,7 @@ describe('Response Type and Response Mode', function () { it('rp-response_type-id_token @id_token-implicit', async function () { const { client } = await register('rp-response_type-id_token', { }); - const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'id_token', nonce: String(Math.random()) }), noFollow); + const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'id_token', nonce: random() }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); assert(params.id_token); @@ -35,7 +33,7 @@ describe('Response Type and Response Mode', function () { it('rp-response_type-id_token+token @id_token+token-implicit', async function () { const { client } = await register('rp-response_type-id_token+token', { }); - const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'id_token token', nonce: String(Math.random()) }), noFollow); + const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'id_token token', nonce: random() }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); assert(params.id_token); @@ -44,7 +42,7 @@ describe('Response Type and Response Mode', function () { it('rp-response_type-code+id_token @code+id_token-hybrid', async function () { const { client } = await register('rp-response_type-code+id_token', { }); - const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'code id_token', nonce: String(Math.random()) }), noFollow); + const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'code id_token', nonce: random() }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); assert(params.id_token); @@ -53,7 +51,7 @@ describe('Response Type and Response Mode', function () { it('rp-response_type-code+token @code+token-hybrid', async function () { const { client } = await register('rp-response_type-code+token', { }); - const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'code token', nonce: String(Math.random()) }), noFollow); + const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'code token', nonce: random() }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); assert(params.code); @@ -62,7 +60,7 @@ describe('Response Type and Response Mode', function () { it('rp-response_type-code+id_token+token @code+id_token+token-hybrid', async function () { const { client } = await register('rp-response_type-code+id_token+token', { }); - const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'code id_token token', nonce: String(Math.random()) }), noFollow); + const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type: 'code id_token token', nonce: random() }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); assert(params.id_token); @@ -82,8 +80,10 @@ describe('Response Type and Response Mode', function () { it(profile, async function () { const { client } = await register('rp-response_mode-form_post', { }); - const nonce = String(Math.random()); - const request = client.authorizationUrl({ response_mode: 'form_post', redirect_uri, response_type, nonce }); + const nonce = random(); + const request = client.authorizationUrl({ + response_mode: 'form_post', redirect_uri, response_type, nonce, + }); const { pathname, query } = url.parse(request, true); log('authentication request to', pathname); log('authentication request parameters', JSON.stringify(query, null, 4)); @@ -101,7 +101,7 @@ describe('Response Type and Response Mode', function () { const params = client.callbackParams(authorization); log('authentication response', JSON.stringify(params, null, 4)); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); assert(tokens); }); }); @@ -119,9 +119,11 @@ describe('Response Type and Response Mode', function () { it(profile, async function () { const { client } = await register('rp-response_mode-form_post-error', { }); - const nonce = String(Math.random()); - const state = String(Math.random()); - const request = client.authorizationUrl({ response_mode: 'form_post', redirect_uri, response_type, nonce, state, prompt: 'none', max_age: 0 }); + const nonce = random(); + const state = random(); + const request = client.authorizationUrl({ + response_mode: 'form_post', redirect_uri, response_type, nonce, state, prompt: 'none', max_age: 0, + }); const { pathname, query } = url.parse(request, true); log('authentication request to', pathname); log('authentication request parameters', JSON.stringify(query, null, 4)); @@ -140,7 +142,7 @@ describe('Response Type and Response Mode', function () { const params = client.callbackParams(authorization); log('authentication response', JSON.stringify(params, null, 4)); try { - await authorizationCallback(client, redirect_uri, params, { nonce, response_type, state }); + await callback(client, redirect_uri, params, { nonce, response_type, state }); reject(); } catch (err) { assert.equal(err.message, 'login_required'); diff --git a/test/scope-request-parameter.js b/test/scope-request-parameter.js index e50df7d..8f2b932 100644 --- a/test/scope-request-parameter.js +++ b/test/scope-request-parameter.js @@ -1,4 +1,4 @@ -'use strict'; +const { strict: assert } = require('assert'); const { forEach } = require('lodash'); const base64url = require('base64url'); @@ -6,14 +6,13 @@ const { noFollow, redirect_uri, register, + random, describe, authorize, - authorizationCallback, + callback, it, } = require('./helper'); -const assert = require('assert'); - describe('scope Request Parameter', function () { describe('rp-scope-userinfo-claims', function () { forEach({ @@ -26,15 +25,17 @@ describe('scope Request Parameter', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-scope-userinfo-claims', { }); - const nonce = String(Math.random()); - const authorization = await authorize(client.authorizationUrl({ nonce, redirect_uri, response_type, scope: 'openid email' }), noFollow); + const nonce = random(); + const authorization = await authorize(client.authorizationUrl({ + nonce, redirect_uri, response_type, scope: 'openid email', + }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); const userinfo = await (async () => { if (tokens.access_token) { - return await client.userinfo(tokens); + return client.userinfo(tokens); } return JSON.parse(base64url.decode(tokens.id_token.split('.')[1])); })(); diff --git a/test/userinfo-endpoint.js b/test/userinfo-endpoint.js index c8856ce..88859d8 100644 --- a/test/userinfo-endpoint.js +++ b/test/userinfo-endpoint.js @@ -1,22 +1,21 @@ -'use strict'; +const { strict: assert } = require('assert'); const { forEach } = require('lodash'); -const jose = require('node-jose'); // eslint-disable-line import/no-extraneous-dependencies +const jose = require('@panva/jose'); // eslint-disable-line import/no-extraneous-dependencies const { noFollow, redirect_uri, + random, redirect_uris, register, reject, describe, authorize, - authorizationCallback, + callback, userinfoCall, it, } = require('./helper'); -const assert = require('assert'); - describe('UserInfo Endpoint', function () { describe('rp-userinfo-bearer-header', function () { forEach({ @@ -28,11 +27,11 @@ describe('UserInfo Endpoint', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-userinfo-bearer-header', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ nonce, redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); const userinfo = await userinfoCall(client, tokens, { via: 'header' }); assert(userinfo); }); @@ -49,11 +48,11 @@ describe('UserInfo Endpoint', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-userinfo-bearer-body', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ nonce, redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); const userinfo = await userinfoCall(client, tokens, { via: 'body', verb: 'post' }); assert(userinfo); }); @@ -65,37 +64,37 @@ describe('UserInfo Endpoint', function () { const { client } = await register('rp-userinfo-sig', { redirect_uris, userinfo_signed_response_alg: 'HS256' }); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); const userinfo = await userinfoCall(client, tokens); assert(userinfo); }); it('rp-userinfo-sig+enc', async function () { const response_type = 'code'; - const keystore = jose.JWK.createKeyStore(); - await keystore.generate('RSA', 512); + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('RSA'); const { client } = await register('rp-userinfo-sig+enc', { userinfo_signed_response_alg: 'RS256', userinfo_encrypted_response_alg: 'RSA1_5', redirect_uris }, keystore); assert.equal(client.userinfo_signed_response_alg, 'RS256'); assert.equal(client.userinfo_encrypted_response_alg, 'RSA1_5'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); const userinfo = await userinfoCall(client, tokens); assert(userinfo.sub); }); it('rp-userinfo-enc', async function () { const response_type = 'code'; - const keystore = jose.JWK.createKeyStore(); - await keystore.generate('RSA', 512); + const keystore = new jose.JWKS.KeyStore(); + await keystore.generate('RSA'); const { client } = await register('rp-userinfo-enc', { userinfo_signed_response_alg: 'none', userinfo_encrypted_response_alg: 'RSA1_5', redirect_uris }, keystore); assert.equal(client.userinfo_signed_response_alg, 'none'); assert.equal(client.userinfo_encrypted_response_alg, 'RSA1_5'); const authorization = await authorize(client.authorizationUrl({ redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location); - const tokens = await authorizationCallback(client, redirect_uri, params, { response_type }); + const tokens = await callback(client, redirect_uri, params, { response_type }); const userinfo = await userinfoCall(client, tokens); assert(userinfo.sub); }); @@ -110,16 +109,16 @@ describe('UserInfo Endpoint', function () { }, (response_type, profile) => { it(profile, async function () { const { client } = await register('rp-userinfo-bad-sub-claim', { }); - const nonce = String(Math.random()); + const nonce = random(); const authorization = await authorize(client.authorizationUrl({ nonce, redirect_uri, response_type }), noFollow); const params = client.callbackParams(authorization.headers.location.replace('#', '?')); - const tokens = await authorizationCallback(client, redirect_uri, params, { nonce, response_type }); + const tokens = await callback(client, redirect_uri, params, { nonce, response_type }); try { await userinfoCall(client, tokens); reject(); } catch (err) { - assert.equal(err.message, 'userinfo sub mismatch'); + assert.equal(err.message, 'userinfo sub mismatch, expected 1b2fc9341a16ae4e30082965d537ae47c21a0f27fd43eab78330ed81751ae6db, got: foobar'); } }); });