diff --git a/.eslintrc.json b/.eslintrc.json index e05edf2e..ebdd9863 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,7 +1,7 @@ { "extends": "airbnb-base", "parserOptions": { - "sourceType": "script", + "sourceType": "module", "ecmaVersion": 2022 }, "rules": { @@ -9,8 +9,8 @@ "code": 120, "ignoreComments": true }], - "strict": ["error", "safe"], "max-classes-per-file": ["off"], - "lines-between-class-members": ["off"] + "lines-between-class-members": ["off"], + "import/extensions": "off" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 34806d16..68567447 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Breaking changes - Drop node 12 support +- Rewrite library using ecmascript modules ### Maintainance - Use c8 to collect code coverage diff --git a/README.md b/README.md index 12d999f3..716d8325 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ npm install --save simple-oauth2 With a minimal configuration, create a client instance of any supported [grant type](#supported-grant-types). ```javascript +import { ClientCredentials, ResourceOwnerPassword, AuthorizationCode } from 'simple-oauth2'; + const config = { client: { id: '', @@ -63,8 +65,6 @@ const config = { tokenHost: 'https://api.oauth.com' } }; - -const { ClientCredentials, ResourceOwnerPassword, AuthorizationCode } = require('simple-oauth2'); ``` For a complete reference of configuration options, see the [API Options](./API.md#options) @@ -78,32 +78,28 @@ Depending on your use-case, any of the following supported grant types may be us The [Authorization Code](https://oauth.net/2/grant-types/authorization-code/) grant type is used by confidential and public clients to exchange an authorization code for an access token. After the user returns to the client via the redirect URL, the application will get the authorization code from the URL and use it to request an access token. ```javascript -async function run() { - const client = new AuthorizationCode(config); +const client = new AuthorizationCode(config); - const authorizationUri = client.authorizeURL({ - redirect_uri: 'http://localhost:3000/callback', - scope: '', - state: '' - }); +const authorizationUri = client.authorizeURL({ + redirect_uri: 'http://localhost:3000/callback', + scope: '', + state: '' +}); - // Redirect example using Express (see http://expressjs.com/api.html#res.redirect) - res.redirect(authorizationUri); +// Redirect example using Express (see http://expressjs.com/api.html#res.redirect) +res.redirect(authorizationUri); - const tokenParams = { - code: '', - redirect_uri: 'http://localhost:3000/callback', - scope: '', - }; +const tokenParams = { + code: '', + redirect_uri: 'http://localhost:3000/callback', + scope: '', +}; - try { - const accessToken = await client.getToken(tokenParams); - } catch (error) { - console.log('Access Token Error', error.message); - } +try { + const accessToken = await client.getToken(tokenParams); +} catch (error) { + console.log('Access Token Error', error.message); } - -run(); ``` See the [API reference](./API.md#new-authorizationcodeoptions) for a complete reference of available options or any of our available examples at the [example folder](./example). @@ -113,23 +109,19 @@ See the [API reference](./API.md#new-authorizationcodeoptions) for a complete re The [Resource Owner Password Credentials](https://oauth.net/2/grant-types/password/) grant type is a way to exchange a user's credentials for an access token. Because the client application has to collect the user's password and send it to the authorization server, it is not recommended that this grant be used at all anymore. ```javascript -async function run() { - const client = new ResourceOwnerPassword(config); +const client = new ResourceOwnerPassword(config); - const tokenParams = { - username: 'username', - password: 'password', - scope: '', - }; +const tokenParams = { + username: 'username', + password: 'password', + scope: '', +}; - try { - const accessToken = await client.getToken(tokenParams); - } catch (error) { - console.log('Access Token Error', error.message); - } +try { + const accessToken = await client.getToken(tokenParams); +} catch (error) { + console.log('Access Token Error', error.message); } - -run(); ``` See the [API reference](./API.md#new-resourceownerpasswordoptions) for a complete reference of available options. @@ -139,21 +131,17 @@ See the [API reference](./API.md#new-resourceownerpasswordoptions) for a complet The [Client Credentials](https://oauth.net/2/grant-types/client-credentials/) grant type is used by clients to obtain an access token outside of the context of a user. This is typically used by clients to access resources about themselves rather than to access a user's resources. ```javascript -async function run() { - const client = new ClientCredentials(config); +const client = new ClientCredentials(config); - const tokenParams = { - scope: '', - }; +const tokenParams = { + scope: '', +}; - try { - const accessToken = await client.getToken(tokenParams); - } catch (error) { - console.log('Access Token error', error.message); - } +try { + const accessToken = await client.getToken(tokenParams); +} catch (error) { + console.log('Access Token error', error.message); } - -run(); ``` See the [API reference](./API.md#new-clientcredentialsoptions) for a complete reference of available options. @@ -168,45 +156,33 @@ On long lived applications, it is often necessary to refresh access tokens. In s ```javascript -async function run() { - const accessTokenJSONString = JSON.stringify(accessToken); +const accessTokenJSONString = JSON.stringify(accessToken); - await persistAccessTokenJSON(accessTokenJSONString); -} - -run(); +await persistAccessTokenJSON(accessTokenJSONString); ``` By the time we need to refresh the persistent access token, we can get back an [AccessToken](./API.md#accesstoken) instance by using the client's [.createToken](./API.md#createtokentoken--accesstoken) method. ```javascript -async function run() { - const accessTokenJSONString = await getPersistedAccessTokenJSON(); - - let accessToken = client.createToken(JSON.parse(accessTokenJSONString)); -} +const accessTokenJSONString = await getPersistedAccessTokenJSON(); -run(); +let accessToken = client.createToken(JSON.parse(accessTokenJSONString)); ``` Once we have determined the access token needs refreshing with the [.expired()](./API.md#expiredexpirationwindowseconds--boolean) method, we can finally refresh it with a [.refresh()](./API.md#await-refreshparams--accesstoken) method call. ```javascript -async function run() { - if (accessToken.expired()) { - try { - const refreshParams = { - scope: '', - }; - - accessToken = await accessToken.refresh(refreshParams); - } catch (error) { - console.log('Error refreshing access token: ', error.message); - } +if (accessToken.expired()) { + try { + const refreshParams = { + scope: '', + }; + + accessToken = await accessToken.refresh(refreshParams); + } catch (error) { + console.log('Error refreshing access token: ', error.message); } } - -run(); ``` The [.expired()](./API.md##expiredexpirationwindowseconds--boolean) helper is useful for knowing when a token has definitively expired. However, there is a common race condition when tokens are near expiring. If an OAuth 2.0 token is issued with a `expires_in` property (as opposed to an `expires_at` property), there can be discrepancies between the time the OAuth 2.0 server issues the access token and when it is received. @@ -214,19 +190,15 @@ The [.expired()](./API.md##expiredexpirationwindowseconds--boolean) helper is us These come down to factors such as network and processing latency and can be worked around by preemptively refreshing the access token: ```javascript -async function run() { - const EXPIRATION_WINDOW_IN_SECONDS = 300; // Window of time before the actual expiration to refresh the token - - if (accessToken.expired(EXPIRATION_WINDOW_IN_SECONDS)) { - try { - accessToken = await accessToken.refresh(); - } catch (error) { - console.log('Error refreshing access token: ', error.message); - } +const EXPIRATION_WINDOW_IN_SECONDS = 300; // Window of time before the actual expiration to refresh the token + +if (accessToken.expired(EXPIRATION_WINDOW_IN_SECONDS)) { + try { + accessToken = await accessToken.refresh(); + } catch (error) { + console.log('Error refreshing access token: ', error.message); } } - -run(); ``` **Warning:** Tokens obtained with the Client Credentials grant may not be refreshed. Fetch a new token when it's expired. @@ -238,31 +210,23 @@ See the [API reference](./API.md#accesstoken) for a complete reference of availa When you've done with the token or you want to log out, you can revoke both access and refresh tokens. ```javascript -async function run() { - try { - await accessToken.revoke('access_token'); - await accessToken.revoke('refresh_token'); - } catch (error) { - console.log('Error revoking token: ', error.message); - } +try { + await accessToken.revoke('access_token'); + await accessToken.revoke('refresh_token'); +} catch (error) { + console.log('Error revoking token: ', error.message); } - -run(); ``` As a convenience method, you can also revoke both tokens in a single call: ```javascript -async function run() { - try { - // Revokes both tokens, refresh token is only revoked if the access_token is properly revoked - await accessToken.revokeAll(); - } catch (error) { - console.log('Error revoking token: ', error.message); - } +try { + // Revokes both tokens, refresh token is only revoked if the access_token is properly revoked + await accessToken.revokeAll(); +} catch (error) { + console.log('Error revoking token: ', error.message); } - -run(); ``` See the [API reference](./API.md#accesstoken) for a complete reference of available options. @@ -272,18 +236,14 @@ See the [API reference](./API.md#accesstoken) for a complete reference of availa Whenever a client or server error is produced, a [boom](https://github.com/hapijs/boom) error is thrown by the library. As such any [boom error property](https://hapi.dev/module/boom/api) is available, but the exact information may vary according to the type of error. ```javascript -async function run() { - const client = new ClientCredentials(config); +const client = new ClientCredentials(config); - try { - await client.getToken(); - } catch(error) { - console.log(error.output); - } +try { + await client.getToken(); +} catch(error) { + console.log(error.output); } -run(); - // { statusCode: 401, // payload: // { statusCode: 401, diff --git a/index.js b/index.js index 51838787..b41a1021 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,10 @@ -'use strict'; +import Config from './lib/config.js'; +import { Client } from './lib/client/index.js'; +import AuthorizationCodeGrantType from './lib/authorization-code-grant-type.js'; +import ResourceOwnerPasswordGrantType from './lib/resource-owner-password-grant-type.js'; +import ClientCredentialsGrantType from './lib/client-credentials-grant-type.js'; -const Config = require('./lib/config'); -const { Client } = require('./lib/client'); -const AuthorizationCodeGrantType = require('./lib/authorization-code-grant-type'); -const ResourceOwnerPasswordGrantType = require('./lib/resource-owner-password-grant-type'); -const ClientCredentialsGrantType = require('./lib/client-credentials-grant-type'); - -class AuthorizationCode extends AuthorizationCodeGrantType { +export class AuthorizationCode extends AuthorizationCodeGrantType { constructor(options) { const config = Config.apply(options); const client = new Client(config); @@ -15,7 +13,7 @@ class AuthorizationCode extends AuthorizationCodeGrantType { } } -class ClientCredentials extends ClientCredentialsGrantType { +export class ClientCredentials extends ClientCredentialsGrantType { constructor(options) { const config = Config.apply(options); const client = new Client(config); @@ -24,7 +22,7 @@ class ClientCredentials extends ClientCredentialsGrantType { } } -class ResourceOwnerPassword extends ResourceOwnerPasswordGrantType { +export class ResourceOwnerPassword extends ResourceOwnerPasswordGrantType { constructor(options) { const config = Config.apply(options); const client = new Client(config); @@ -32,9 +30,3 @@ class ResourceOwnerPassword extends ResourceOwnerPasswordGrantType { super(config, client); } } - -module.exports = { - ResourceOwnerPassword, - ClientCredentials, - AuthorizationCode, -}; diff --git a/lib/access-token-parser.js b/lib/access-token-parser.js index 86ccfcb6..c7aa60a4 100644 --- a/lib/access-token-parser.js +++ b/lib/access-token-parser.js @@ -1,6 +1,6 @@ -'use strict'; +import debugg from 'debug'; -const debug = require('debug')('simple-oauth2:access-token'); +const debug = debugg('simple-oauth2:access-token'); const EXPIRES_AT_PROPERTY_NAME = 'expires_at'; const EXPIRES_IN_PROPERTY_NAME = 'expires_in'; @@ -23,7 +23,8 @@ function parseExpirationDate(expirationDate) { return new Date(expirationDate); } -function parseToken(token) { +// eslint-disable-next-line import/prefer-default-export +export function parseToken(token) { const tokenProperties = {}; if (EXPIRES_AT_PROPERTY_NAME in token) { @@ -39,5 +40,3 @@ function parseToken(token) { ...tokenProperties, }; } - -module.exports = { parseToken }; diff --git a/lib/access-token.js b/lib/access-token.js index 61d8c8f2..4ff0c918 100644 --- a/lib/access-token.js +++ b/lib/access-token.js @@ -1,13 +1,11 @@ -'use strict'; - -const Hoek = require('@hapi/hoek'); -const GrantTypeParams = require('./grant-type-params'); -const { parseToken } = require('./access-token-parser'); +import Hoek from '@hapi/hoek'; +import GrantTypeParams from './grant-type-params.js'; +import { parseToken } from './access-token-parser.js'; const ACCESS_TOKEN_PROPERTY_NAME = 'access_token'; const REFRESH_TOKEN_PROPERTY_NAME = 'refresh_token'; -module.exports = class AccessToken { +export default class AccessToken { #config = null; #client = null; @@ -91,4 +89,4 @@ module.exports = class AccessToken { toJSON() { return this.token; } -}; +} diff --git a/lib/authorization-code-grant-type.js b/lib/authorization-code-grant-type.js index 5f7a75ae..3ad542c4 100644 --- a/lib/authorization-code-grant-type.js +++ b/lib/authorization-code-grant-type.js @@ -1,11 +1,9 @@ -'use strict'; +import { URL } from 'url'; +import querystring from 'querystring'; +import AccessToken from './access-token.js'; +import GrantTypeParams from './grant-type-params.js'; -const { URL } = require('url'); -const querystring = require('querystring'); -const AccessToken = require('./access-token'); -const GrantTypeParams = require('./grant-type-params'); - -module.exports = class AuthorizationCode { +export default class AuthorizationCode { #config = null; #client = null; @@ -61,4 +59,4 @@ module.exports = class AuthorizationCode { createToken(token) { return new AccessToken(this.#config, this.#client, token); } -}; +} diff --git a/lib/client-credentials-grant-type.js b/lib/client-credentials-grant-type.js index 635573d1..c6ddf2a6 100644 --- a/lib/client-credentials-grant-type.js +++ b/lib/client-credentials-grant-type.js @@ -1,9 +1,7 @@ -'use strict'; +import AccessToken from './access-token.js'; +import GrantTypeParams from './grant-type-params.js'; -const AccessToken = require('./access-token'); -const GrantTypeParams = require('./grant-type-params'); - -module.exports = class ClientCredentials { +export default class ClientCredentials { #config = null; #client = null; @@ -36,4 +34,4 @@ module.exports = class ClientCredentials { createToken(token) { return new AccessToken(this.#config, this.#client, token); } -}; +} diff --git a/lib/client/client.js b/lib/client/client.js index e95f310e..21999ee0 100644 --- a/lib/client/client.js +++ b/lib/client/client.js @@ -1,9 +1,9 @@ -'use strict'; +import Hoek from '@hapi/hoek'; +import Wreck from '@hapi/wreck'; +import debugg from 'debug'; +import { RequestOptions } from './request-options.js'; -const Hoek = require('@hapi/hoek'); -const Wreck = require('@hapi/wreck'); -const debug = require('debug')('simple-oauth2:client'); -const { RequestOptions } = require('./request-options'); +const debug = debugg('simple-oauth2:client'); const defaultHttpHeaders = { Accept: 'application/json', @@ -15,7 +15,7 @@ const defaultHttpOptions = { headers: defaultHttpHeaders, }; -module.exports = class Client { +export default class Client { #config = null; #client = null; @@ -41,4 +41,4 @@ module.exports = class Client { return response.payload; } -}; +} diff --git a/lib/client/credentials-encoding.js b/lib/client/credentials-encoding.js index 4ee7e00b..1797c5ce 100644 --- a/lib/client/credentials-encoding.js +++ b/lib/client/credentials-encoding.js @@ -1,8 +1,6 @@ -'use strict'; - const HEADER_ENCODING_FORMAT = 'base64'; -const credentialsEncodingModeEnum = { +export const credentialsEncodingModeEnum = { STRICT: 'strict', LOOSE: 'loose', }; @@ -31,7 +29,7 @@ function getCredentialsString(clientID, clientSecret) { return `${clientID}:${clientSecret}`; } -class CredentialsEncoding { +export class CredentialsEncoding { constructor(encodingMode) { this.encodingMode = encodingMode; } @@ -54,8 +52,3 @@ class CredentialsEncoding { return Buffer.from(encodedCredentials).toString(HEADER_ENCODING_FORMAT); } } - -module.exports = { - CredentialsEncoding, - credentialsEncodingModeEnum, -}; diff --git a/lib/client/index.js b/lib/client/index.js index a9e8cf8d..2ebe5ea7 100644 --- a/lib/client/index.js +++ b/lib/client/index.js @@ -1,10 +1,8 @@ -'use strict'; +import Client from './client.js'; +import { credentialsEncodingModeEnum } from './credentials-encoding.js'; +import { RequestOptions, authorizationMethodEnum, bodyFormatEnum } from './request-options.js'; -const Client = require('./client'); -const { credentialsEncodingModeEnum } = require('./credentials-encoding'); -const { RequestOptions, authorizationMethodEnum, bodyFormatEnum } = require('./request-options'); - -module.exports = { +export { Client, RequestOptions, credentialsEncodingModeEnum, diff --git a/lib/client/request-options.js b/lib/client/request-options.js index 64bf7eba..139565b8 100644 --- a/lib/client/request-options.js +++ b/lib/client/request-options.js @@ -1,19 +1,19 @@ -'use strict'; +import Hoek from '@hapi/hoek'; +import querystring from 'querystring'; +import debugg from 'debug'; +import { CredentialsEncoding } from './credentials-encoding.js'; -const Hoek = require('@hapi/hoek'); -const querystring = require('querystring'); -const debug = require('debug')('simple-oauth2:request-options'); -const { CredentialsEncoding } = require('./credentials-encoding'); +const debug = debugg('simple-oauth2:request-options'); const JSON_CONTENT_TYPE = 'application/json'; const FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded'; -const authorizationMethodEnum = { +export const authorizationMethodEnum = { HEADER: 'header', BODY: 'body', }; -const bodyFormatEnum = { +export const bodyFormatEnum = { FORM: 'form', JSON: 'json', }; @@ -24,7 +24,7 @@ function getDefaultRequestOptions() { }; } -class RequestOptions { +export class RequestOptions { #config = null; #requestOptions = null; @@ -70,9 +70,3 @@ class RequestOptions { return Hoek.applyToDefaults(requestOptions, this.#requestOptions); } } - -module.exports = { - RequestOptions, - authorizationMethodEnum, - bodyFormatEnum, -}; diff --git a/lib/config.js b/lib/config.js index 497d0de0..7fbcc365 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,7 +1,5 @@ -'use strict'; - -const Joi = require('joi'); -const { authorizationMethodEnum, bodyFormatEnum, credentialsEncodingModeEnum } = require('./client'); +import Joi from 'joi'; +import { authorizationMethodEnum, bodyFormatEnum, credentialsEncodingModeEnum } from './client/index.js'; // https://tools.ietf.org/html/draft-ietf-oauth-v2-31#appendix-A.1 const vsCharRegEx = /^[\x20-\x7E]*$/; @@ -50,4 +48,4 @@ const Config = { }, }; -module.exports = Config; +export default Config; diff --git a/lib/grant-type-params.js b/lib/grant-type-params.js index 4dcb5ff0..e896f762 100644 --- a/lib/grant-type-params.js +++ b/lib/grant-type-params.js @@ -1,5 +1,3 @@ -'use strict'; - function getScopeParam(scope, scopeSeparator) { if (scope === undefined) { return null; @@ -16,7 +14,7 @@ function getScopeParam(scope, scopeSeparator) { }; } -module.exports = class GrantTypeParams { +export default class GrantTypeParams { #params = null; #baseParams = null; #options = null; @@ -40,4 +38,4 @@ module.exports = class GrantTypeParams { return Object.assign(this.#baseParams, this.#params, scopeParams); } -}; +} diff --git a/lib/resource-owner-password-grant-type.js b/lib/resource-owner-password-grant-type.js index df6f4bed..b31f6252 100644 --- a/lib/resource-owner-password-grant-type.js +++ b/lib/resource-owner-password-grant-type.js @@ -1,9 +1,7 @@ -'use strict'; +import AccessToken from './access-token.js'; +import GrantTypeParams from './grant-type-params.js'; -const AccessToken = require('./access-token'); -const GrantTypeParams = require('./grant-type-params'); - -module.exports = class ResourceOwnerPassword { +export default class ResourceOwnerPassword { #config = null; #client = null; @@ -38,4 +36,4 @@ module.exports = class ResourceOwnerPassword { createToken(token) { return new AccessToken(this.#config, this.#client, token); } -}; +} diff --git a/package-lock.json b/package-lock.json index 454cd9d6..f8bf6260 100644 --- a/package-lock.json +++ b/package-lock.json @@ -143,9 +143,9 @@ "dev": true }, "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", "dev": true }, "@nodelib/fs.scandir": { @@ -740,6 +740,17 @@ "yargs-parser": "^20.2.7" }, "dependencies": { + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -785,6 +796,38 @@ "requires": { "glob": "^7.1.3" } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true } } }, @@ -3678,23 +3721,6 @@ } } }, - "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "requires": { - "type-fest": "^0.13.1" - }, - "dependencies": { - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true - } - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3918,6 +3944,21 @@ "argparse": "^1.0.7", "esprima": "^4.0.0" } + }, + "serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "requires": { + "type-fest": "^0.13.1" + } + }, + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true } } }, diff --git a/package.json b/package.json index 430157f2..f2e3011f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "simple-oauth2", "version": "4.2.0", + "type": "module", "support": true, "description": "Node.js client for OAuth2", "author": "Andrea Reginato ", diff --git a/test/_authorization-server-mock.js b/test/_authorization-server-mock.js index 1253def4..e6abd177 100644 --- a/test/_authorization-server-mock.js +++ b/test/_authorization-server-mock.js @@ -1,9 +1,7 @@ -'use strict'; - -const { URL } = require('url'); -const nock = require('nock'); -const Hoek = require('@hapi/hoek'); -const Boom = require('@hapi/boom'); +import { URL } from 'url'; +import nock from 'nock'; +import Hoek from '@hapi/hoek'; +import Boom from '@hapi/boom'; const accessToken = { access_token: '5683E74C-7514-4426-B64F-CF0C24223F69', @@ -12,7 +10,7 @@ const accessToken = { expires_in: '240000', }; -function createAuthorizationServer(authorizationServerUrl) { +export function createAuthorizationServer(authorizationServerUrl) { function tokenSuccessWithCustomPath(path, scopeOptions, params) { return nock(authorizationServerUrl, scopeOptions) .post(path, params) @@ -116,11 +114,11 @@ function createAuthorizationServer(authorizationServerUrl) { }; } -function getAccessToken() { +export function getAccessToken() { return accessToken; } -function getJSONEncodingScopeOptions(options = {}) { +export function getJSONEncodingScopeOptions(options = {}) { return Hoek.applyToDefaults({ reqheaders: { Accept: 'application/json', @@ -129,7 +127,7 @@ function getJSONEncodingScopeOptions(options = {}) { }, options); } -function getFormEncodingScopeOptions(options = {}) { +export function getFormEncodingScopeOptions(options = {}) { return Hoek.applyToDefaults({ reqheaders: { Accept: 'application/json', @@ -138,7 +136,7 @@ function getFormEncodingScopeOptions(options = {}) { }, options); } -function getHeaderCredentialsScopeOptions(options = {}) { +export function getHeaderCredentialsScopeOptions(options = {}) { return Hoek.applyToDefaults({ reqheaders: { Accept: 'application/json', @@ -146,11 +144,3 @@ function getHeaderCredentialsScopeOptions(options = {}) { }, }, options); } - -module.exports = { - getAccessToken, - createAuthorizationServer, - getJSONEncodingScopeOptions, - getFormEncodingScopeOptions, - getHeaderCredentialsScopeOptions, -}; diff --git a/test/_module-config.js b/test/_module-config.js index 39ad17d1..d8a04971 100644 --- a/test/_module-config.js +++ b/test/_module-config.js @@ -1,7 +1,5 @@ -'use strict'; - -const Hoek = require('@hapi/hoek'); -const Config = require('../lib/config'); +import Hoek from '@hapi/hoek'; +import Config from '../lib/config.js'; const baseConfig = { client: { @@ -13,15 +11,10 @@ const baseConfig = { }, }; -function createModuleConfig(config = {}) { +export function createModuleConfig(config = {}) { return Hoek.applyToDefaults(baseConfig, config); } -function createModuleConfigWithDefaults(config) { +export function createModuleConfigWithDefaults(config) { return Config.apply(createModuleConfig(config)); } - -module.exports = { - createModuleConfig, - createModuleConfigWithDefaults, -}; diff --git a/test/_property.js b/test/_property.js index adb780ce..10ba978c 100644 --- a/test/_property.js +++ b/test/_property.js @@ -1,9 +1,2 @@ -'use strict'; - -const has = (...args) => Object.prototype.hasOwnProperty.call(...args); -const hasIn = (object, propertyName) => propertyName in object; - -module.exports = { - has, - hasIn, -}; +export const has = (...args) => Object.prototype.hasOwnProperty.call(...args); +export const hasIn = (object, propertyName) => propertyName in object; diff --git a/test/access-token.js b/test/access-token.js index 1bbb49c9..83798e87 100644 --- a/test/access-token.js +++ b/test/access-token.js @@ -1,20 +1,18 @@ -'use strict'; - -const test = require('ava'); -const Chance = require('chance'); -const accessTokenMixin = require('chance-access-token'); -const { +import test from 'ava'; +import Chance from 'chance'; +import accessTokenMixin from 'chance-access-token'; +import { isValid, isDate, differenceInSeconds, isEqual, -} = require('date-fns'); +} from 'date-fns'; -const AccessToken = require('../lib/access-token'); -const { Client } = require('../lib/client'); -const { has, hasIn } = require('./_property'); -const { createModuleConfigWithDefaults: createModuleConfig } = require('./_module-config'); -const { createAuthorizationServer, getHeaderCredentialsScopeOptions } = require('./_authorization-server-mock'); +import AccessToken from '../lib/access-token.js'; +import { Client } from '../lib/client/index.js'; +import { has, hasIn } from './_property.js'; +import { createModuleConfigWithDefaults as createModuleConfig } from './_module-config.js'; +import { createAuthorizationServer, getHeaderCredentialsScopeOptions } from './_authorization-server-mock.js'; const chance = new Chance(); chance.mixin({ accessToken: accessTokenMixin }); diff --git a/test/authorization-code-grant-type.js b/test/authorization-code-grant-type.js index e8a39cc7..f4470862 100644 --- a/test/authorization-code-grant-type.js +++ b/test/authorization-code-grant-type.js @@ -1,16 +1,14 @@ -'use strict'; - -const test = require('ava'); -const { AuthorizationCode } = require('../index'); -const AccessToken = require('../lib/access-token'); -const { createModuleConfig } = require('./_module-config'); -const { +import test from 'ava'; +import { AuthorizationCode } from '../index.js'; +import AccessToken from '../lib/access-token.js'; +import { createModuleConfig } from './_module-config.js'; +import { getAccessToken, createAuthorizationServer, getJSONEncodingScopeOptions, getFormEncodingScopeOptions, getHeaderCredentialsScopeOptions, -} = require('./_authorization-server-mock'); +} from './_authorization-server-mock.js'; test('@authorizeURL => returns the authorization URL with no options and default module configuration', (t) => { const config = createModuleConfig(); diff --git a/test/client-credentials-grant-type.js b/test/client-credentials-grant-type.js index 171241b0..6f323915 100644 --- a/test/client-credentials-grant-type.js +++ b/test/client-credentials-grant-type.js @@ -1,16 +1,14 @@ -'use strict'; - -const test = require('ava'); -const { ClientCredentials } = require('../index'); -const AccessToken = require('../lib/access-token'); -const { createModuleConfig } = require('./_module-config'); -const { +import test from 'ava'; +import { ClientCredentials } from '../index.js'; +import AccessToken from '../lib/access-token.js'; +import { createModuleConfig } from './_module-config.js'; +import { getAccessToken, createAuthorizationServer, getJSONEncodingScopeOptions, getFormEncodingScopeOptions, getHeaderCredentialsScopeOptions, -} = require('./_authorization-server-mock'); +} from './_authorization-server-mock.js'; test('@createToken => creates a new access token instance from a JSON object', async (t) => { const oauth2 = new ClientCredentials(createModuleConfig()); diff --git a/test/errors.js b/test/errors.js index 871958e0..fca9a4f9 100644 --- a/test/errors.js +++ b/test/errors.js @@ -1,9 +1,7 @@ -'use strict'; - -const test = require('ava'); -const { AuthorizationCode } = require('../index'); -const { createModuleConfig } = require('./_module-config'); -const { createAuthorizationServer, getHeaderCredentialsScopeOptions } = require('./_authorization-server-mock'); +import test from 'ava'; +import { AuthorizationCode } from '../index.js'; +import { createModuleConfig } from './_module-config.js'; +import { createAuthorizationServer, getHeaderCredentialsScopeOptions } from './_authorization-server-mock.js'; const tokenParams = { code: 'code', diff --git a/test/index.js b/test/index.js index 180430ab..a38a8f00 100644 --- a/test/index.js +++ b/test/index.js @@ -1,9 +1,6 @@ -'use strict'; - -const test = require('ava'); - -const { ResourceOwnerPassword, ClientCredentials, AuthorizationCode } = require('../index'); -const { createModuleConfig } = require('./_module-config'); +import test from 'ava'; +import { ResourceOwnerPassword, ClientCredentials, AuthorizationCode } from '../index.js'; +import { createModuleConfig } from './_module-config.js'; test('@create => throws a validation error when no configuration is provided', (t) => { t.throws(() => new ResourceOwnerPassword()); diff --git a/test/resource-owner-password-grant-type.js b/test/resource-owner-password-grant-type.js index 696e7677..1fa446be 100644 --- a/test/resource-owner-password-grant-type.js +++ b/test/resource-owner-password-grant-type.js @@ -1,16 +1,14 @@ -'use strict'; - -const test = require('ava'); -const { ResourceOwnerPassword } = require('../index'); -const AccessToken = require('../lib/access-token'); -const { createModuleConfig } = require('./_module-config'); -const { +import test from 'ava'; +import { ResourceOwnerPassword } from '../index.js'; +import AccessToken from '../lib/access-token.js'; +import { createModuleConfig } from './_module-config.js'; +import { getAccessToken, createAuthorizationServer, getJSONEncodingScopeOptions, getFormEncodingScopeOptions, getHeaderCredentialsScopeOptions, -} = require('./_authorization-server-mock'); +} from './_authorization-server-mock.js'; test('@createToken => creates a new access token instance from a JSON object', async (t) => { const oauth2 = new ResourceOwnerPassword(createModuleConfig());