Skip to content

Commit

Permalink
feat: added Node.js lts/dubnium support
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Aug 22, 2019
1 parent fcf64de commit 52e914c
Show file tree
Hide file tree
Showing 20 changed files with 375 additions and 295 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
fail-fast: false
matrix:
node-version:
- 10.13.0
- 10
- 12.0.0
- 12
os:
Expand Down
22 changes: 11 additions & 11 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ _**default value**_:

[draft-ietf-oauth-mtls-15](https://tools.ietf.org/html/draft-ietf-oauth-mtls-15) - OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens

Enables specific features from the Mutual TLS specification. The three main features have their own specific setting in this feature's configuration object and you must provide helpers for resolving some of the functions which are deployment-specific.
Enables specific features from the Mutual TLS specification. The three main features have their own specific setting in this feature's configuration object and you must provide helpers for resolving some of the functions which are deployment-specific. This feature is only supported in node runtime >= 12.0.0**



Expand Down Expand Up @@ -2038,7 +2038,7 @@ This option allows to configure the token serialization format. The different va
- `opaque` (default) formatted tokens store every property as a root property in your adapter
- `jwt` formatted tokens are issued as JWTs and stored the same as `opaque` only with additional property `jwt`. See `formats.jwtAccessTokenSigningAlg` for resolving the JWT Access Token signing algorithm. Note this is a proprietary format that will eventually get deprecated in favour of the 'jwt-ietf' value (once it gets stable and close to being an RFC)
- `jwt-ietf` formatted tokens are issued as JWTs and stored the same as `opaque` only with additional property `jwt-ietf`. See `formats.jwtAccessTokenSigningAlg` for resolving the JWT Access Token signing algorithm. This is an implementation of [JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens](https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-02) draft and to enable it you need to enable `features.ietfJWTAccessTokenProfile`. 'jwt-ietf' value (once it gets stable and close to being an RFC)
- `paseto` formatted tokens are issued as v2.public PASETOs and stored the same as `opaque` only with additional property `paseto`. The server must have an `OKP Ed25519` key available to sign with else it will throw a server error. PASETOs are also allowed to only have a single audience, if the token's "aud" resolves with more than one the server will throw a server error.
- `paseto` formatted tokens are issued as v2.public PASETOs and stored the same as `opaque` only with additional property `paseto`. The server must have an `OKP Ed25519` key available to sign with else it will throw a server error. PASETOs are also allowed to only have a single audience, if the token's "aud" resolves with more than one the server will throw a server error. **This format is only supported in node runtime >= 12.0.0**
- the value may also be a function dynamically determining the format (returning either `jwt`, `jwt-ietf`, `paseto` or `opaque` depending on the token itself)


Expand Down Expand Up @@ -2965,7 +2965,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -2995,7 +2995,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -3093,7 +3093,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -3190,7 +3190,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -3223,7 +3223,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -3321,7 +3321,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -3353,7 +3353,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -3385,7 +3385,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down Expand Up @@ -3483,7 +3483,7 @@ _**default value**_:
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
]
```
</details>
Expand Down
20 changes: 10 additions & 10 deletions docs/update-configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { get, words } = require('lodash');
const values = require('../lib/helpers/defaults');

function capitalizeSentences(copy) {
return copy.replace(/\. [a-z]/g, match => `. ${match.slice(-1).toUpperCase()}`);
return copy.replace(/\. [a-z]/g, (match) => `. ${match.slice(-1).toUpperCase()}`);
}

class Block {
Expand Down Expand Up @@ -102,8 +102,8 @@ const props = [
let override;
if (prop === 'example' && option.example) {
const i = Math.max(...Object.keys(option)
.filter(p => p.startsWith('example'))
.map(e => parseInt(e.slice(-1), 10) || 0));
.filter((p) => p.startsWith('example'))
.map((e) => parseInt(e.slice(-1), 10) || 0));
override = `example${i + 1}`;
}
option.active = override || prop;
Expand Down Expand Up @@ -159,13 +159,13 @@ const props = [
}, []);

const features = configuration.splice(0, featuresIdx).sort();
const clientsIdx = configuration.findIndex(x => x === 'clients');
const clientsIdx = configuration.findIndex((x) => x === 'clients');
const clients = configuration.splice(clientsIdx, 1);
const adapterIdx = configuration.findIndex(x => x === 'adapter');
const adapterIdx = configuration.findIndex((x) => x === 'adapter');
const adapter = configuration.splice(adapterIdx, 1);
const jwksIdx = configuration.findIndex(x => x === 'jwks');
const jwksIdx = configuration.findIndex((x) => x === 'jwks');
const jwks = configuration.splice(jwksIdx, 1);
const findAccountIdx = configuration.findIndex(x => x === 'findAccount');
const findAccountIdx = configuration.findIndex((x) => x === 'findAccount');
const findAccount = configuration.splice(findAccountIdx, 1);

let hidden;
Expand Down Expand Up @@ -285,9 +285,9 @@ const props = [
}
}

Object.keys(section).filter(p => p.startsWith('example')).forEach((prop) => {
Object.keys(section).filter((p) => p.startsWith('example')).forEach((prop) => {
const [title, ...content] = section[prop];
append(`<a name="${words(`${headingTitle} ${title}`).map(w => w.toLowerCase()).join('-')}"></a>`.replace('\n', ''));
append(`<a name="${words(`${headingTitle} ${title}`).map((w) => w.toLowerCase()).join('-')}"></a>`.replace('\n', ''));
append(`<details>\n <summary>(Click to expand) ${title}</summary>\n <br>\n\n`);

const parts = [];
Expand All @@ -311,7 +311,7 @@ const props = [
}

while (parts.length) {
const until = parts.findIndex(p => Array.isArray(p));
const until = parts.findIndex((p) => Array.isArray(p));
if (until === 0) {
const lines = parts.shift();
lines.forEach(append);
Expand Down
10 changes: 4 additions & 6 deletions lib/consts/jwa.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
const [major, minor] = process.version.substr(1).split('.').map((x) => parseInt(x, 10));

const OAEP256 = major > 12 || (major === 12 && minor >= 9);
const runtimeSupport = require('../helpers/runtime_support');

const signingAlgValues = [
'HS256', 'HS384', 'HS512',
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512',
'ES256', 'ES384', 'ES512',
'EdDSA',
];
runtimeSupport.EdDSA ? 'EdDSA' : undefined,
].filter(Boolean);

const encryptionAlgValues = [
// asymmetric kw
'RSA-OAEP', OAEP256 ? 'RSA-OAEP-256' : false, 'RSA1_5',
'RSA-OAEP', runtimeSupport['RSA-OAEP-256'] ? 'RSA-OAEP-256' : false, 'RSA1_5',
'ECDH-ES', 'ECDH-ES+A128KW', 'ECDH-ES+A192KW', 'ECDH-ES+A256KW',
// symmetric kw
'A128GCMKW', 'A192GCMKW', 'A256GCMKW', 'A128KW', 'A192KW', 'A256KW',
Expand Down
11 changes: 10 additions & 1 deletion lib/helpers/client_schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,16 @@ module.exports = function getSchema(provider) {
}
}

const responseTypes = [...new Set(this.response_types.map((rt) => rt.split(' ')).flat(1))];
const responseTypes = [
...new Set(this.response_types.map((rt) => rt.split(' '))),
].reduce((acc, val) => {
if (Array.isArray(val)) {
return [...acc, ...val];
}

acc.push(val);
return acc;
}, []);

if (this.grant_types.some((type) => ['authorization_code', 'implicit'].includes(type)) && !this.response_types.length) {
invalidate('response_types must contain members');
Expand Down
12 changes: 12 additions & 0 deletions lib/helpers/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { JWA } = require('../consts');
const defaults = require('./defaults');
const { STABLE, DRAFTS } = require('./features');
const attention = require('./attention');
const runtimeSupport = require('./runtime_support');

function authEndpointDefaults(config) {
[
Expand Down Expand Up @@ -68,6 +69,8 @@ module.exports = class Configuration {

this.logDraftNotice();

this.checkRuntimeFeatures();

this.ensureMaps();
this.ensureSets();

Expand Down Expand Up @@ -117,6 +120,15 @@ module.exports = class Configuration {
});
}

checkRuntimeFeatures() {
if (this.features.mTLS.enabled && !runtimeSupport.KeyObject) {
throw new Error('mTLS can only be enabled on Node.js >= 12.0.0 runtime');
}
if ((this.formats.AccessToken === 'paseto' || this.formats.ClientCredentials === 'paseto') && !runtimeSupport.EdDSA) {
throw new Error('paseto structured tokens can only be enabled on Node.js >= 12.0.0 runtime');
}
}

fixResponseTypes() {
const types = new Set();

Expand Down
31 changes: 21 additions & 10 deletions lib/helpers/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const os = require('os');
const MemoryAdapter = require('../adapters/memory_adapter');
const { DEV_KEYSTORE } = require('../consts');

const runtimeSupport = require('./runtime_support');
const base64url = require('./base64url');
const attention = require('./attention');
const nanoid = require('./nanoid');
Expand Down Expand Up @@ -390,6 +391,7 @@ const DEFAULTS = {
* description: Enables specific features from the Mutual TLS specification. The three main
* features have their own specific setting in this feature's configuration object and
* you must provide helpers for resolving some of the functions which are deployment-specific.
* **This feature is only supported in node runtime >= 12.0.0**
*
*/
mTLS: {
Expand Down Expand Up @@ -1232,7 +1234,7 @@ const DEFAULTS = {
* only with additional property `paseto`. The server must have an `OKP Ed25519` key available
* to sign with else it will throw a server error. PASETOs are also allowed to only have a
* single audience, if the token's "aud" resolves with more than one the server will throw a
* server error.
* server error. **This format is only supported in node runtime >= 12.0.0**
* - the value may also be a function dynamically determining the format (returning either
* `jwt`, `jwt-ietf`, `paseto` or `opaque` depending on the token itself)
*
Expand Down Expand Up @@ -1978,7 +1980,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -1999,7 +2001,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -2020,7 +2022,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -2042,7 +2044,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -2064,7 +2066,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -2086,7 +2088,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -2108,7 +2110,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -2129,7 +2131,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand Down Expand Up @@ -2368,7 +2370,7 @@ const DEFAULTS = {
* 'RS256', 'RS384', 'RS512',
* 'PS256', 'PS384', 'PS512',
* 'ES256', 'ES384', 'ES512',
* 'EdDSA',
* 'EdDSA', // (note: EdDSA is only supported in node runtime >= 12.0.0)
* ]
* ```
*/
Expand All @@ -2378,6 +2380,15 @@ const DEFAULTS = {
},
};

if (!runtimeSupport.EdDSA) {
Object.values(DEFAULTS.whitelistedJWA).forEach((algs) => {
const index = algs.indexOf('EdDSA');
if (index !== -1) {
algs.splice(index, 1);
}
});
}

/*
* introspectionEndpointAuthMethods
*
Expand Down
9 changes: 9 additions & 0 deletions lib/helpers/runtime_support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const crypto = require('crypto');

const [major, minor] = process.version.substr(1).split('.').map((x) => parseInt(x, 10));

module.exports = {
'RSA-OAEP-256': major > 12 || (major === 12 && minor >= 9),
EdDSA: major >= 12,
KeyObject: typeof crypto.KeyObject !== 'undefined',
};
10 changes: 8 additions & 2 deletions lib/models/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const _ = require('lodash');
const jose = require('@panva/jose');
const LRU = require('lru-cache');

const runtimeSupport = require('../helpers/runtime_support');
const base64url = require('../helpers/base64url');
const request = require('../helpers/request');
const nanoid = require('../helpers/nanoid');
Expand All @@ -19,8 +20,13 @@ const sectorIdentifier = require('../helpers/sector_identifier');
const { LOOPBACKS } = require('../consts/client_attributes');

// intentionally ignore x5t and x5t#S256 so that they are left to be calculated by the jose library
const KEY_ATTRIBUTES = ['crv', 'e', 'kid', 'kty', 'n', 'use', 'key_ops', 'x', 'y', 'x5c'];
const KEY_TYPES = new Set(['RSA', 'EC', 'OKP', 'oct']);
const KEY_ATTRIBUTES = ['crv', 'e', 'kid', 'kty', 'n', 'use', 'key_ops', 'x', 'y'];
const KEY_TYPES = new Set(['RSA', 'EC', 'oct']);

if (runtimeSupport.KeyObject) {
KEY_TYPES.add('OKP');
KEY_ATTRIBUTES.push('x5c');
}

const fingerprint = (properties) => hash(properties, {
algorithm: 'sha256',
Expand Down
Loading

0 comments on commit 52e914c

Please sign in to comment.