Node.js client library for OAuth2. OAuth2 allows users to grant access to restricted resources by third party applications.
The node client library is tested against Node 8 LTS and newer versions. Older node versions are unsupported.
Install the client library using npm:
npm install --save simple-oauth2
Create a new instance by specifying the minimal configuration
const credentials = {
client: {
id: '<client-id>',
secret: '<client-secret>'
},
auth: {
tokenHost: 'https://api.oauth.com'
}
};
const oauth2 = require('simple-oauth2').create(credentials);
Depending on your use case, any of the following supported grant types may be useful:
The Authorization Code 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.
async function run() {
const oauth2 = require('simple-oauth2').create(credentials);
const authorizationUri = oauth2.authorizationCode.authorizeURL({
redirect_uri: 'http://localhost:3000/callback',
scope: '<scope>',
state: '<state>'
});
// Redirect example using Express (see http://expressjs.com/api.html#res.redirect)
res.redirect(authorizationUri);
const tokenConfig = {
code: '<code>',
redirect_uri: 'http://localhost:3000/callback',
scope: '<scope>',
};
try {
const result = await oauth2.authorizationCode.getToken(tokenConfig);
const accessToken = oauth2.accessToken.create(result);
} catch (error) {
console.log('Access Token Error', error.message);
}
}
run();
The Password Owner 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.
async function run() {
const oauth2 = require('simple-oauth2').create(credentials);
const tokenConfig = {
username: 'username',
password: 'password',
scope: '<scope>',
};
try {
const result = await oauth2.ownerPassword.getToken(tokenConfig);
const accessToken = oauth2.accessToken.create(result);
} catch (error) {
console.log('Access Token Error', error.message);
}
}
run();
The Client Credentials grant type is suitable when client is requesting access to the protected resources under its control.
async function run() {
const oauth2 = require('simple-oauth2').create(credentials);
const tokenConfig = {
scope: '<scope>',
};
try {
const result = await oauth2.clientCredentials.getToken(tokenConfig);
const accessToken = oauth2.accessToken.create(result);
} catch (error) {
console.log('Access Token error', error.message);
}
}
run();
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.
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 = {
scope: '<scope>',
};
accessToken = await accessToken.refresh(params);
} catch (error) {
console.log('Error refreshing access token: ', error.message);
}
}
}
run();
The expired
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.
These come down to factors such as network and processing latency and can be worked around by preemptively refreshing the access token:
async function run() {
const EXPIRATION_WINDOW_IN_SECONDS = 300; // Window of time before the actual expiration to refresh the token
if (token.expired(EXPIRATION_WINDOW_IN_SECONDS)) {
try {
accessToken = await accessToken.refresh();
} catch (error) {
console.log('Error refreshing access token: ', error.message);
}
}
}
run();
When you've done with the token or you want to log out, you can revoke the access and refresh tokens.
async function run() {
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:
async function run() {
// Revoke both access and refresh tokens
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();
Errors are returned when a 4xx or 5xx status code is received.
BoomError
As a standard boom error you can access any of the boom error properties. The total amount of information varies according to the generated status code.
async function run() {
try {
await oauth2.authorizationCode.getToken();
} catch(error) {
console.log(error);
}
}
run();
// => {
// "statusCode": 401,
// "error": "Unauthorized",
// "message": "invalid password"
// }
This module uses the debug module to help on error diagnosis. Use the following environment variable to help in your debug journey:
DEBUG=*simple-oauth2*
For a complete reference, see the module API.
For complete reference examples, see the example folder.
See CONTRIBUTING
Special thanks to the following people for submitting patches.
See CHANGELOG
Simple OAuth 2.0 is licensed under the Apache License, Version 2.0
Simple OAuth 2.0 come to life thanks to the work I've made in Lelylan, an open source microservices architecture for the Internet of Things. If this project helped you in any way, think about giving us a star on Github.