simple-oauth2
Advanced tools
Comparing version 3.4.0 to 4.0.0
# Changelog | ||
## Next | ||
## 4.0.0 | ||
### Breaking changes | ||
* [#292](https://github.com/lelylan/simple-oauth2/pull/292) [#313](https://github.com/lelylan/simple-oauth2/pull/313) Require at least Node 12 | ||
* [#292](https://github.com/lelylan/simple-oauth2/pull/292) Use private class fields for non-public API's | ||
* [#292](https://github.com/lelylan/simple-oauth2/pull/292) Access token `.token` property is now frozen | ||
* [#318](https://github.com/lelylan/simple-oauth2/pull/318) New public API separating each grant type into it's own submodule | ||
* [#321](https://github.com/lelylan/simple-oauth2/pull/321) Rename resource owner credentials module to be accurate | ||
### Maintainance | ||
* [#292](https://github.com/lelylan/simple-oauth2/pull/292) Upgrade @hapi/hoek to v9 (requires Node 12) | ||
* [#292](https://github.com/lelylan/simple-oauth2/pull/292) Upgrade @hapi/joi to v17 (requires Node 12) | ||
* [#292](https://github.com/lelylan/simple-oauth2/pull/292) Upgrade @hapi/wreck to v17 (requires Node 12) | ||
* [#311](https://github.com/lelylan/simple-oauth2/pull/311) Upgrade nock dev library to v12 | ||
* [#319](https://github.com/lelylan/simple-oauth2/pull/319) Add Node 14 to test matrix | ||
### Documentation | ||
* [#314](https://github.com/lelylan/simple-oauth2/pull/314) Add client credentials token refresh disclaimer | ||
* [#317](https://github.com/lelylan/simple-oauth2/pull/317) Fix output documentation for boom errors | ||
* [#320](https://github.com/lelylan/simple-oauth2/pull/320) Add complete reference documentation | ||
## 3.4.0 | ||
@@ -6,0 +24,0 @@ ### Improvements |
90
index.js
'use strict'; | ||
const Joi = require('@hapi/joi'); | ||
const Client = require('./lib/client'); | ||
const AuthorizationCode = require('./lib/grants/authorization-code'); | ||
const PasswordOwner = require('./lib/grants/password-owner'); | ||
const ClientCredentials = require('./lib/grants/client-credentials'); | ||
const AccessToken = require('./lib/access-token'); | ||
const { authorizationMethodEnum, bodyFormatEnum, encodingModeEnum } = require('./lib/request-options'); | ||
const Config = require('./lib/config'); | ||
const AuthorizationCodeGrant = require('./lib/grants/authorization-code'); | ||
const ResourceOwnerPasswordGrant = require('./lib/grants/resource-owner-password'); | ||
const ClientCredentialsGrant = require('./lib/grants/client-credentials'); | ||
// https://tools.ietf.org/html/draft-ietf-oauth-v2-31#appendix-A.1 | ||
const vsCharRegEx = /^[\x20-\x7E]*$/; | ||
class AuthorizationCode extends AuthorizationCodeGrant { | ||
constructor(options) { | ||
const config = Config.apply(options); | ||
const client = new Client(config); | ||
const clientSchema = Joi.object().keys({ | ||
id: Joi.string().pattern(vsCharRegEx).allow(''), | ||
secret: Joi.string().pattern(vsCharRegEx).allow(''), | ||
secretParamName: Joi.string().default('client_secret'), | ||
idParamName: Joi.string().default('client_id'), | ||
}).required(); | ||
super(config, client); | ||
} | ||
} | ||
const authSchema = Joi.object().keys({ | ||
tokenHost: Joi.string().required().uri({ scheme: ['http', 'https'] }), | ||
tokenPath: Joi.string().default('/oauth/token'), | ||
revokePath: Joi.string().default('/oauth/revoke'), | ||
authorizeHost: Joi.string().uri({ scheme: ['http', 'https'] }).default(Joi.ref('tokenHost')), | ||
authorizePath: Joi.string().default('/oauth/authorize'), | ||
}).required(); | ||
class ClientCredentials extends ClientCredentialsGrant { | ||
constructor(options) { | ||
const config = Config.apply(options); | ||
const client = new Client(config); | ||
const optionsSchema = Joi.object().keys({ | ||
scopeSeparator: Joi.string().default(' '), | ||
credentialsEncodingMode: Joi | ||
.string() | ||
.valid(...Object.values(encodingModeEnum)) | ||
.default(encodingModeEnum.STRICT), | ||
bodyFormat: Joi | ||
.string() | ||
.valid(...Object.values(bodyFormatEnum)) | ||
.default(bodyFormatEnum.FORM), | ||
authorizationMethod: Joi | ||
.string() | ||
.valid(...Object.values(authorizationMethodEnum)) | ||
.default(authorizationMethodEnum.HEADER), | ||
}).default(); | ||
super(config, client); | ||
} | ||
} | ||
const moduleOptionsSchema = Joi.object().keys({ | ||
client: clientSchema, | ||
auth: authSchema, | ||
http: Joi.object().unknown(true), | ||
options: optionsSchema, | ||
}); | ||
class ResourceOwnerPassword extends ResourceOwnerPasswordGrant { | ||
constructor(options) { | ||
const config = Config.apply(options); | ||
const client = new Client(config); | ||
super(config, client); | ||
} | ||
} | ||
module.exports = { | ||
/** | ||
* Creates a new simple-oauth2 client with the provided configuration | ||
* @param {Object} opts Module options as defined in schema | ||
* @returns {Object} The simple-oauth2 client | ||
*/ | ||
create(opts = {}) { | ||
const options = Joi.attempt(opts, moduleOptionsSchema, 'Invalid options provided to simple-oauth2'); | ||
const client = new Client(options); | ||
return { | ||
accessToken: { | ||
create: AccessToken.factory(options, client), | ||
}, | ||
ownerPassword: new PasswordOwner(options, client), | ||
authorizationCode: new AuthorizationCode(options, client), | ||
clientCredentials: new ClientCredentials(options, client), | ||
}; | ||
}, | ||
ResourceOwnerPassword, | ||
ClientCredentials, | ||
AuthorizationCode, | ||
}; |
@@ -11,6 +11,5 @@ 'use strict'; | ||
class AccessToken { | ||
static factory(config, client) { | ||
return (token) => new AccessToken(config, client, token); | ||
} | ||
module.exports = class AccessToken { | ||
#config = null; | ||
#client = null; | ||
@@ -22,5 +21,5 @@ constructor(config, client, token) { | ||
this.config = config; | ||
this.client = client; | ||
this.token = parseToken(token); | ||
this.#config = config; | ||
this.#client = client; | ||
this.token = Object.freeze(parseToken(token)); | ||
} | ||
@@ -46,10 +45,11 @@ | ||
async refresh(params = {}) { | ||
const refreshParams = Object.assign({}, params, { | ||
const refreshParams = { | ||
...params, | ||
refresh_token: this.token.refresh_token, | ||
}); | ||
}; | ||
const parameters = GrantParams.forGrant(REFRESH_TOKEN_PROPERTY_NAME, this.config.options, refreshParams); | ||
const response = await this.client.request(this.config.auth.tokenPath, parameters.toObject()); | ||
const parameters = GrantParams.forGrant(REFRESH_TOKEN_PROPERTY_NAME, this.#config.options, refreshParams); | ||
const response = await this.#client.request(this.#config.auth.tokenPath, parameters.toObject()); | ||
return new AccessToken(this.config, this.client, response); | ||
return new AccessToken(this.#config, this.#client, response); | ||
} | ||
@@ -66,3 +66,3 @@ | ||
tokenType === ACCESS_TOKEN_PROPERTY_NAME || tokenType === REFRESH_TOKEN_PROPERTY_NAME, | ||
`Invalid token type. Only ${ACCESS_TOKEN_PROPERTY_NAME} or ${REFRESH_TOKEN_PROPERTY_NAME} are valid values` | ||
`Invalid token type. Only ${ACCESS_TOKEN_PROPERTY_NAME} or ${REFRESH_TOKEN_PROPERTY_NAME} are valid values`, | ||
); | ||
@@ -75,3 +75,3 @@ | ||
return this.client.request(this.config.auth.revokePath, options); | ||
return this.#client.request(this.#config.auth.revokePath, options); | ||
} | ||
@@ -81,2 +81,3 @@ | ||
* Revokes both the current access and refresh tokens | ||
* | ||
* @returns {Promise} | ||
@@ -88,4 +89,2 @@ */ | ||
} | ||
} | ||
module.exports = AccessToken; | ||
}; |
@@ -38,5 +38,8 @@ 'use strict'; | ||
return Object.assign({}, token, tokenProperties); | ||
return { | ||
...token, | ||
...tokenProperties, | ||
}; | ||
} | ||
module.exports = { parseToken }; |
@@ -19,2 +19,5 @@ 'use strict'; | ||
module.exports = class Client { | ||
#config = null; | ||
#client = null; | ||
constructor(config) { | ||
@@ -27,8 +30,8 @@ const configHttpOptions = Hoek.applyToDefaults(config.http || {}, { | ||
this.config = config; | ||
this.client = Wreck.defaults(httpOptions); | ||
this.#config = config; | ||
this.#client = Wreck.defaults(httpOptions); | ||
} | ||
async request(url, params, opts) { | ||
const requestOptions = new RequestOptions(this.config, params); | ||
const requestOptions = new RequestOptions(this.#config, params); | ||
const options = requestOptions.toObject(opts); | ||
@@ -39,3 +42,3 @@ | ||
const response = await this.client.post(url, options); | ||
const response = await this.#client.post(url, options); | ||
@@ -42,0 +45,0 @@ return response.payload; |
@@ -20,2 +20,6 @@ 'use strict'; | ||
module.exports = class GrantParams { | ||
#params = null; | ||
#baseParams = null; | ||
#options = null; | ||
static forGrant(grantType, options, params) { | ||
@@ -30,12 +34,12 @@ const baseParams = { | ||
constructor(options, baseParams, params) { | ||
this.options = options; | ||
this.params = Object.assign({}, params); | ||
this.baseParams = Object.assign({}, baseParams); | ||
this.#options = { ...options }; | ||
this.#params = { ...params }; | ||
this.#baseParams = { ...baseParams }; | ||
} | ||
toObject() { | ||
const scopeParams = getScopeParam(this.params.scope, this.options.scopeSeparator); | ||
const scopeParams = getScopeParam(this.#params.scope, this.#options.scopeSeparator); | ||
return Object.assign(this.baseParams, this.params, scopeParams); | ||
return Object.assign(this.#baseParams, this.#params, scopeParams); | ||
} | ||
}; |
@@ -5,8 +5,12 @@ 'use strict'; | ||
const querystring = require('querystring'); | ||
const AccessToken = require('../access-token'); | ||
const GrantParams = require('../grant-params'); | ||
module.exports = class AuthorizationCode { | ||
#config = null; | ||
#client = null; | ||
constructor(config, client) { | ||
this.config = config; | ||
this.client = client; | ||
this.#config = config; | ||
this.#client = client; | ||
} | ||
@@ -27,7 +31,7 @@ | ||
response_type: 'code', | ||
[this.config.client.idParamName]: this.config.client.id, | ||
[this.#config.client.idParamName]: this.#config.client.id, | ||
}; | ||
const url = new URL(this.config.auth.authorizePath, this.config.auth.authorizeHost); | ||
const parameters = new GrantParams(this.config.options, baseParams, params); | ||
const url = new URL(this.#config.auth.authorizePath, this.#config.auth.authorizeHost); | ||
const parameters = new GrantParams(this.#config.options, baseParams, params); | ||
@@ -41,12 +45,13 @@ return `${url}?${querystring.stringify(parameters.toObject())}`; | ||
* @param {String} params.code Authorization code (from previous step) | ||
* @param {String} params.redirecURI String representing the registered application URI where the user is redirected after authentication | ||
* @param {String} params.redirectURI String representing the registered application URI where the user is redirected after authentication | ||
* @param {String|Array<String>} [params.scope] String or array of strings representing the application privileges | ||
* @param {Object} [httpOptions] Optional http options passed through the underlying http library | ||
* @return {Promise} | ||
* @return {Promise<AccessToken>} | ||
*/ | ||
async getToken(params, httpOptions) { | ||
const parameters = GrantParams.forGrant('authorization_code', this.config.options, params); | ||
const parameters = GrantParams.forGrant('authorization_code', this.#config.options, params); | ||
const response = await this.#client.request(this.#config.auth.tokenPath, parameters.toObject(), httpOptions); | ||
return this.client.request(this.config.auth.tokenPath, parameters.toObject(), httpOptions); | ||
return new AccessToken(this.#config, this.#client, response); | ||
} | ||
}; |
'use strict'; | ||
const GrantParams = require('../grant-params'); | ||
const AccessToken = require('../access-token'); | ||
module.exports = class ClientCredentials { | ||
#config = null; | ||
#client = null; | ||
constructor(config, client) { | ||
this.config = config; | ||
this.client = client; | ||
this.#config = config; | ||
this.#client = client; | ||
} | ||
@@ -17,9 +21,10 @@ | ||
* @param {Object} [httpOptions] Optional http options passed through the underlying http library | ||
* @return {Promise} | ||
* @return {Promise<AccessToken>} | ||
*/ | ||
async getToken(params, httpOptions) { | ||
const parameters = GrantParams.forGrant('client_credentials', this.config.options, params); | ||
const parameters = GrantParams.forGrant('client_credentials', this.#config.options, params); | ||
const response = await this.#client.request(this.#config.auth.tokenPath, parameters.toObject(), httpOptions); | ||
return this.client.request(this.config.auth.tokenPath, parameters.toObject(), httpOptions); | ||
return new AccessToken(this.#config, this.#client, response); | ||
} | ||
}; |
@@ -28,14 +28,17 @@ 'use strict'; | ||
class RequestOptions { | ||
#config = null; | ||
#requestOptions = null; | ||
constructor(config, params) { | ||
this.config = config; | ||
this.requestOptions = this.createOptions(params); | ||
this.#config = config; | ||
this.#requestOptions = this.createOptions(params); | ||
} | ||
createOptions(params) { | ||
const parameters = Object.assign({}, params); | ||
const parameters = { ...params }; | ||
const requestOptions = getDefaultRequestOptions(); | ||
if (this.config.options.authorizationMethod === authorizationMethodEnum.HEADER) { | ||
const encoding = new Encoding(this.config.options.credentialsEncodingMode); | ||
const credentials = encoding.getAuthorizationHeaderToken(this.config.client.id, this.config.client.secret); | ||
if (this.#config.options.authorizationMethod === authorizationMethodEnum.HEADER) { | ||
const encoding = new Encoding(this.#config.options.credentialsEncodingMode); | ||
const credentials = encoding.getAuthorizationHeaderToken(this.#config.client.id, this.#config.client.secret); | ||
@@ -48,7 +51,7 @@ debug('Using header authentication. Authorization header set to %s', credentials); | ||
parameters[this.config.client.idParamName] = this.config.client.id; | ||
parameters[this.config.client.secretParamName] = this.config.client.secret; | ||
parameters[this.#config.client.idParamName] = this.#config.client.id; | ||
parameters[this.#config.client.secretParamName] = this.#config.client.secret; | ||
} | ||
if (this.config.options.bodyFormat === bodyFormatEnum.FORM) { | ||
if (this.#config.options.bodyFormat === bodyFormatEnum.FORM) { | ||
debug('Using form request format'); | ||
@@ -69,3 +72,3 @@ | ||
toObject(requestOptions = {}) { | ||
return Hoek.applyToDefaults(requestOptions, this.requestOptions); | ||
return Hoek.applyToDefaults(requestOptions, this.#requestOptions); | ||
} | ||
@@ -72,0 +75,0 @@ } |
{ | ||
"name": "simple-oauth2", | ||
"version": "3.4.0", | ||
"version": "4.0.0", | ||
"description": "Node.js client for OAuth2", | ||
@@ -20,3 +20,3 @@ "author": "Andrea Reginato <andrea.reginato@gmail.com>", | ||
"engine": { | ||
"node": ">=8" | ||
"node": ">=12" | ||
}, | ||
@@ -49,20 +49,21 @@ "scripts": { | ||
"dependencies": { | ||
"@hapi/hoek": "^8.5.0", | ||
"@hapi/joi": "^16.1.8", | ||
"@hapi/wreck": "^15.1.0", | ||
"date-fns": "^2.9.0", | ||
"@hapi/hoek": "^9.0.4", | ||
"@hapi/joi": "^17.1.1", | ||
"@hapi/wreck": "^17.0.0", | ||
"date-fns": "^2.14.0", | ||
"debug": "^4.1.1" | ||
}, | ||
"devDependencies": { | ||
"@hapi/boom": "^8.0.1", | ||
"ava": "^3.1.0", | ||
"chance": "^1.1.4", | ||
"@hapi/boom": "^9.1.0", | ||
"ava": "^3.8.2", | ||
"babel-eslint": "^10.1.0", | ||
"chance": "^1.1.6", | ||
"chance-access-token": "^2.0.0", | ||
"doctoc": "^1.4.0", | ||
"eslint": "^6.8.0", | ||
"eslint-config-airbnb-base": "^14.0.0", | ||
"eslint-plugin-import": "^2.20.0", | ||
"nock": "^11.7.2", | ||
"nyc": "^15.0.0" | ||
"eslint-config-airbnb-base": "^14.1.0", | ||
"eslint-plugin-import": "^2.20.2", | ||
"nock": "^12.0.3", | ||
"nyc": "^15.0.1" | ||
} | ||
} |
137
README.md
# Simple OAuth2 | ||
[![NPM Package Version](https://img.shields.io/npm/v/simple-oauth2.svg?style=flat-square)](https://www.npmjs.com/package/simple-oauth2) | ||
[![Build Status](https://img.shields.io/travis/lelylan/simple-oauth2.svg?style=flat-square)](https://travis-ci.org/lelylan/simple-oauth2) | ||
[![Build Status](https://github.com/lelylan/simple-oauth2/workflows/Node.js%20CI/badge.svg)](https://github.com/lelylan/simple-oauth2/actions) | ||
[![Dependency Status](https://img.shields.io/david/lelylan/simple-oauth2.svg?style=flat-square)](https://david-dm.org/lelylan/simple-oauth2) | ||
Node.js client library for [OAuth2](http://oauth.net/2/). OAuth2 allows users to grant access to restricted resources by third party applications. | ||
[Simple OAuth2](#simple-oauth2) is a Node.js client library for the [OAuth 2.0](http://oauth.net/2/) authorization framework. [OAuth 2.0](http://oauth.net/2/) is the industry-standard protocol for authorization, enabling third-party applications to obtain limited access to an HTTP service, either on behalf of a resource owner or by allowing the third-party application to obtain access on it's own behalf. | ||
@@ -20,11 +19,11 @@ ## Table of Contents | ||
- [Usage](#usage) | ||
- [OAuth2 Supported grants](#oauth2-supported-grants) | ||
- [Authorization Code](#authorization-code) | ||
- [Password Credentials Flow](#password-credentials-flow) | ||
- [Client Credentials Flow](#client-credentials-flow) | ||
- [Access Token object](#access-token-object) | ||
- [Supported Grant Types](#supported-grant-types) | ||
- [Authorization Code Grant](#authorization-code-grant) | ||
- [Resource Owner Password Credentials Grant](#resource-owner-password-credentials-grant) | ||
- [Client Credentials Grant](#client-credentials-grant) | ||
- [Access Token](#access-token) | ||
- [Refresh an access token](#refresh-an-access-token) | ||
- [Revoke an access or refresh token](#revoke-an-access-or-refresh-token) | ||
- [Errors](#errors) | ||
- [Debugging the module](#debugging-the-module) | ||
- [API](#api) | ||
- [Usage examples](#usage-examples) | ||
- [Contributing](#contributing) | ||
@@ -41,3 +40,3 @@ - [Authors](#authors) | ||
The node client library is tested against Node 8 LTS and newer versions. Older node versions are unsupported. | ||
The node client library is tested against Node 12 LTS and newer versions. Older node versions are unsupported. | ||
@@ -52,6 +51,6 @@ ## Usage | ||
Create a new instance by specifying the minimal configuration | ||
With a minimal configuration, create an client instace of any supported [grant type](#supported-grant-types). | ||
```javascript | ||
const credentials = { | ||
const config = { | ||
client: { | ||
@@ -66,19 +65,20 @@ id: '<client-id>', | ||
const oauth2 = require('simple-oauth2').create(credentials); | ||
const { ClientCredentials, ResourceOwnerPassword, AuthorizationCode } = require('simple-oauth2'); | ||
``` | ||
For more detailed configuration information see [API Documentation](./API.md) | ||
### OAuth2 Supported grants | ||
For a complete reference of configuration options, see the [API Options](./API.md#options) | ||
Depending on your use case, any of the following supported grant types may be useful: | ||
### Supported Grant Types | ||
#### Authorization Code | ||
Depending on your use-case, any of the following supported grant types may be useful: | ||
The [Authorization Code](http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.1) grant type is made up from two parts. At first your application asks to the user the permission to access their data. If the user approves the OAuth2 server sends to the client an authorization code. In the second part, the client POST the authorization code along with its client secret to the oauth server in order to get the access token. | ||
#### Authorization Code Grant | ||
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 oauth2 = require('simple-oauth2').create(credentials); | ||
const client = new AuthorizationCode(config); | ||
const authorizationUri = oauth2.authorizationCode.authorizeURL({ | ||
const authorizationUri = client.authorizeURL({ | ||
redirect_uri: 'http://localhost:3000/callback', | ||
@@ -92,3 +92,3 @@ scope: '<scope>', | ||
const tokenConfig = { | ||
const tokenParams = { | ||
code: '<code>', | ||
@@ -100,4 +100,3 @@ redirect_uri: 'http://localhost:3000/callback', | ||
try { | ||
const result = await oauth2.authorizationCode.getToken(tokenConfig); | ||
const accessToken = oauth2.accessToken.create(result); | ||
const accessToken = await client.getToken(tokenParams); | ||
} catch (error) { | ||
@@ -111,11 +110,13 @@ console.log('Access Token Error', error.message); | ||
#### Password Credentials Flow | ||
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). | ||
The [Password Owner](http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.3) grant type is suitable when the resource owner has a trust relationship with the client, such as its computer operating system or a highly privileged application. Use this flow only when other flows are not viable or when you need a fast way to test your application. | ||
#### Resource Owner Password Credentials Grant | ||
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 oauth2 = require('simple-oauth2').create(credentials); | ||
const client = new ResourceOwnerPassword(config); | ||
const tokenConfig = { | ||
const tokenParams = { | ||
username: 'username', | ||
@@ -127,4 +128,3 @@ password: 'password', | ||
try { | ||
const result = await oauth2.ownerPassword.getToken(tokenConfig); | ||
const accessToken = oauth2.accessToken.create(result); | ||
const accessToken = await client.getToken(tokenParams); | ||
} catch (error) { | ||
@@ -138,11 +138,13 @@ console.log('Access Token Error', error.message); | ||
#### Client Credentials Flow | ||
See the [API reference](./API.md#new-resourceownerpasswordoptions) for a complete reference of available options. | ||
The [Client Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.4) grant type is suitable when client is requesting access to the protected resources under its control. | ||
#### Client Credentials Grant | ||
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 oauth2 = require('simple-oauth2').create(credentials); | ||
const client = new ClientCredentials(config); | ||
const tokenConfig = { | ||
const tokenParams = { | ||
scope: '<scope>', | ||
@@ -152,4 +154,3 @@ }; | ||
try { | ||
const result = await oauth2.clientCredentials.getToken(tokenConfig); | ||
const accessToken = oauth2.accessToken.create(result); | ||
const accessToken = await client.getToken(tokenParams); | ||
} catch (error) { | ||
@@ -163,23 +164,21 @@ console.log('Access Token error', error.message); | ||
### Access Token object | ||
See the [API reference](./API.md#new-clientcredentialsoptions) for a complete reference of available options. | ||
When a token expires we need to refresh it. Simple OAuth2 offers the AccessToken class that add a couple of useful methods to refresh the access token when it is expired. | ||
### Access Token | ||
On completion of any [supported grant type](#supported-grant-types) an access token will be obtained. A list of supported operations can be found below. | ||
#### Refresh an access token | ||
When a token expires we need a mechanism to obtain a new access token. The [AccessToken](./API.md#accesstoken) methods can be used to perform the token refresh process. | ||
```javascript | ||
async function run() { | ||
const tokenObject = { | ||
'access_token': '<access-token>', | ||
'refresh_token': '<refresh-token>', | ||
'expires_in': '7200' | ||
}; | ||
let accessToken = oauth2.accessToken.create(tokenObject); | ||
if (accessToken.expired()) { | ||
try { | ||
const params = { | ||
const refreshParams = { | ||
scope: '<scope>', | ||
}; | ||
accessToken = await accessToken.refresh(params); | ||
accessToken = await accessToken.refresh(refreshParams); | ||
} catch (error) { | ||
@@ -202,3 +201,3 @@ console.log('Error refreshing access token: ', error.message); | ||
if (token.expired(EXPIRATION_WINDOW_IN_SECONDS)) { | ||
if (accessToken.expired(EXPIRATION_WINDOW_IN_SECONDS)) { | ||
try { | ||
@@ -215,4 +214,10 @@ accessToken = await accessToken.refresh(); | ||
When you've done with the token or you want to log out, you can revoke the access and refresh tokens. | ||
**Warning:** Tokens obtained with the Client Credentials grant may not be refreshed. Fetch a new token when it's expired. | ||
See the [API reference](./API.md#accesstoken) for a complete reference of available options. | ||
#### Revoke an access or refresh token | ||
When you've done with the token or you want to log out, you can revoke both access and refresh tokens. | ||
```javascript | ||
@@ -235,3 +240,2 @@ async function run() { | ||
async function run() { | ||
// Revoke both access and refresh tokens | ||
try { | ||
@@ -248,16 +252,16 @@ // Revokes both tokens, refresh token is only revoked if the access_token is properly revoked | ||
See the [API reference](./API.md#accesstoken) for a complete reference of available options. | ||
### Errors | ||
Errors are returned when a 4xx or 5xx status code is received. | ||
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. | ||
BoomError | ||
As a standard [boom](https://github.com/hapijs/boom) error you can access any of the boom error properties. The total amount of information varies according to the generated status code. | ||
```javascript | ||
async function run() { | ||
const client = new ClientCredentials(config); | ||
try { | ||
await oauth2.authorizationCode.getToken(); | ||
await client.getToken(); | ||
} catch(error) { | ||
console.log(error); | ||
console.log(error.output); | ||
} | ||
@@ -267,7 +271,9 @@ } | ||
run(); | ||
// => { | ||
// "statusCode": 401, | ||
// "error": "Unauthorized", | ||
// "message": "invalid password" | ||
// } | ||
// { statusCode: 401, | ||
// payload: | ||
// { statusCode: 401, | ||
// error: 'Unauthorized', | ||
// message: 'Response Error: 401 Unauthorized' }, | ||
// headers: {} } | ||
``` | ||
@@ -282,9 +288,2 @@ | ||
## API | ||
For a complete reference, see the module [API](./API.md). | ||
## Usage examples | ||
For complete reference examples, see the [example folder](./example). | ||
## Contributing | ||
@@ -291,0 +290,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
40201
14
457
0
0
11
300
+ Added@hapi/address@4.1.0(transitive)
+ Added@hapi/formula@2.0.0(transitive)
+ Added@hapi/hoek@9.3.0(transitive)
+ Added@hapi/joi@17.1.1(transitive)
+ Added@hapi/pinpoint@2.0.1(transitive)
+ Added@hapi/topo@5.1.0(transitive)
- Removed@hapi/address@2.1.4(transitive)
- Removed@hapi/formula@1.2.0(transitive)
- Removed@hapi/hoek@8.5.1(transitive)
- Removed@hapi/joi@16.1.8(transitive)
- Removed@hapi/pinpoint@1.0.2(transitive)
- Removed@hapi/topo@3.1.6(transitive)
Updated@hapi/hoek@^9.0.4
Updated@hapi/joi@^17.1.1
Updated@hapi/wreck@^17.0.0
Updateddate-fns@^2.14.0