Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
simple-oauth2
Advanced tools
The simple-oauth2 npm package is a straightforward and flexible library for implementing OAuth2 authentication in Node.js applications. It provides a simple API to handle the OAuth2 authorization flows, including obtaining access tokens, refreshing tokens, and revoking tokens.
Authorization Code Flow
This feature allows you to generate an authorization URL for the Authorization Code Flow. Users can visit this URL to authorize your application and obtain an authorization code.
const { AuthorizationCode } = require('simple-oauth2');
const client = new AuthorizationCode({
client: {
id: 'your-client-id',
secret: 'your-client-secret',
},
auth: {
tokenHost: 'https://authorization-server.com',
tokenPath: '/oauth/token',
authorizePath: '/oauth/authorize',
},
});
const authorizationUri = client.authorizeURL({
redirect_uri: 'http://localhost:3000/callback',
scope: 'user_profile',
state: 'random-string',
});
console.log('Visit this URL to authorize:', authorizationUri);
Obtaining Access Token
This feature allows you to exchange an authorization code for an access token. The access token can then be used to access protected resources on behalf of the user.
const tokenParams = {
code: 'authorization-code',
redirect_uri: 'http://localhost:3000/callback',
scope: 'user_profile',
};
client.getToken(tokenParams)
.then((result) => {
const accessToken = client.createToken(result);
console.log('Access Token:', accessToken.token);
})
.catch((error) => {
console.error('Access Token Error', error.message);
});
Refreshing Access Token
This feature allows you to refresh an expired access token using a refresh token. The new access token can then be used to continue accessing protected resources.
const token = client.createToken({
access_token: 'existing-access-token',
refresh_token: 'existing-refresh-token',
expires_in: '3600',
});
token.refresh()
.then((result) => {
const refreshedToken = client.createToken(result);
console.log('Refreshed Token:', refreshedToken.token);
})
.catch((error) => {
console.error('Refresh Token Error', error.message);
});
Revoking Access Token
This feature allows you to revoke an access token, making it invalid for further use. This is useful for logging out users or invalidating tokens for security reasons.
const token = client.createToken({
access_token: 'existing-access-token',
refresh_token: 'existing-refresh-token',
expires_in: '3600',
});
token.revoke('access_token')
.then(() => {
console.log('Access Token Revoked');
})
.catch((error) => {
console.error('Revoke Token Error', error.message);
});
passport-oauth2 is a strategy for the Passport authentication middleware that implements OAuth 2.0. It is highly configurable and can be used with various OAuth 2.0 providers. Compared to simple-oauth2, passport-oauth2 is more integrated with the Passport ecosystem, making it a good choice if you are already using Passport for authentication.
client-oauth2 is a lightweight and flexible library for OAuth 2.0 in JavaScript. It supports multiple OAuth 2.0 flows and is easy to use in both Node.js and browser environments. Compared to simple-oauth2, client-oauth2 offers a more minimalistic approach and can be a good choice for developers looking for a smaller library.
axios-oauth-client is a library that integrates OAuth 2.0 with the popular Axios HTTP client. It simplifies the process of making authenticated HTTP requests using OAuth 2.0 tokens. Compared to simple-oauth2, axios-oauth-client is more focused on integrating OAuth 2.0 with Axios, making it a good choice if you are already using Axios for HTTP requests.
Node.js client library for OAuth2.
OAuth2 lets users grant the access to the desired resources to third party applications, giving them the possibility to enable and disable those accesses whenever they want.
Simple OAuth2 supports the following flows.
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.
The node client library is tested against the latest Node 8 LTS and newer versions.
To use in node 4, 5 or 6, please use simple-oauth2@1.x. Older node versions are unsupported.
Install the client library using npm:
npm install --save simple-oauth2
Simple OAuth2 accepts an object with the following valid params.
client
- required object with the following properties:
id
- Service registered client id. When required by the spec this value will be automatically encoded. Required.secret
- Service registered client secret. When required by the spec this value will be automatically encoded. Required.secretParamName
- Parameter name used to send the client secret. Default to client_secret.idParamName
- Parameter name used to send the client id. Default to client_id.auth
- required object with the following properties.
tokenHost
- String used to set the host to request the tokens to. Required.tokenPath
- String path to request an access token. Default to /oauth/token.revokePath
- String path to revoke an access token. Default to /oauth/revoke.authorizeHost
- String used to set the host to request an "authorization code". Default to the value set on auth.tokenHost
.authorizePath
- String path to request an authorization code. Default to /oauth/authorize.http
optional object used to set global options to the internal http library (wreck).
headers.authorization
will always be overriden by the library to properly send the required credentials on each scenario. Default to headers.Accept = application/json
.options
optional object to setup the module.
bodyFormat
- Format of data sent in the request body. Valid options are form
or json
. Defaults to form.authorizationMethod
- Indicates the method used to send the client.id/client.secret authorization params at the token request. Valid options are header
or body
. If set to body, the bodyFormat option will be used to format the credentials. Defaults to header.// Set the configuration settings
const credentials = {
client: {
id: '<client-id>',
secret: '<client-secret>'
},
auth: {
tokenHost: 'https://api.oauth.com'
}
};
// Initialize the OAuth2 Library
const oauth2 = require('simple-oauth2').create(credentials);
See the example folder.
The Authorization Code flow 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.
const oauth2 = require('simple-oauth2').create(credentials);
// Authorization oauth2 URI
const authorizationUri = oauth2.authorizationCode.authorizeURL({
redirect_uri: 'http://localhost:3000/callback',
scope: '<scope>', // also can be an array of multiple scopes, ex. ['<scope1>, '<scope2>', '...']
state: '<state>'
});
// Redirect example using Express (see http://expressjs.com/api.html#res.redirect)
res.redirect(authorizationUri);
// Get the access token object (the authorization code is given from the previous step).
const tokenConfig = {
code: '<code>',
redirect_uri: 'http://localhost:3000/callback',
scope: '<scope>', // also can be an array of multiple scopes, ex. ['<scope1>, '<scope2>', '...']
};
// Optional per-call http options
const httpOptions = {};
// Save the access token
try {
const result = await oauth2.authorizationCode.getToken(tokenConfig, httpOptions);
const accessToken = oauth2.accessToken.create(result);
} catch (error) {
console.log('Access Token Error', error.message);
}
This flow 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.
const oauth2 = require('simple-oauth2').create(credentials);
// Get the access token object.
const tokenConfig = {
username: 'username',
password: 'password',
scope: '<scope>', // also can be an array of multiple scopes, ex. ['<scope1>, '<scope2>', '...']
};
// Optional per-call http options
const httpOptions = {};
// Save the access token
try {
const result = await oauth2.ownerPassword.getToken(tokenConfig, httpOptions);
const accessToken = oauth2.accessToken.create(result);
} catch (error) {
console.log('Access Token Error', error.message);
}
This flow is suitable when client is requesting access to the protected resources under its control.
const oauth2 = require('simple-oauth2').create(credentials);
const tokenConfig = {
scope: '<scope>', // also can be an array of multiple scopes, ex. ['<scope1>, '<scope2>', '...']
};
// Optional per-call http options
const httpOptions = {};
// Get the access token object for the client
try {
const result = await oauth2.clientCredentials.getToken(tokenConfig, httpOptions);
const accessToken = oauth2.accessToken.create(result);
} catch (error) {
console.log('Access Token error', error.message);
}
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.
// Sample of a JSON access token (you got it through previous steps)
const tokenObject = {
'access_token': '<access-token>',
'refresh_token': '<refresh-token>',
'expires_in': '7200'
};
// Create the access token wrapper
let accessToken = oauth2.accessToken.create(tokenObject);
// Check if the token is expired. If expired it is refreshed.
if (accessToken.expired()) {
try {
const params = {
scope: '<scope>', // also can be an array of multiple scopes, ex. ['<scope1>, '<scope2>', '...']
};
accessToken = await accessToken.refresh(params);
} catch (error) {
console.log('Error refreshing access token: ', error.message);
}
}
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. This can be
worked around by preemptively refreshing the access token:
// Provide a window of time before the actual expiration to refresh the token
const EXPIRATION_WINDOW_IN_SECONDS = 300;
const { token } = accessToken;
const expirationTimeInSeconds = token.expires_at.getTime() / 1000;
const expirationWindowStart = expirationTimeInSeconds - EXPIRATION_WINDOW_IN_SECONDS;
// If the start of the window has passed, refresh the token
const nowInSeconds = (new Date()).getTime() / 1000;
const shouldRefresh = nowInSeconds >= expirationWindowStart;
if (shouldRefresh) {
try {
accessToken = await accessToken.refresh();
} catch (error) {
console.log('Error refreshing access token: ', error.message);
}
}
When you've done with the token or you want to log out, you can revoke the access token and refresh token.
// Revoke both access and refresh tokens
try {
// Revoke only the access token
await accessToken.revoke('access_token');
// Session ended. But the refresh_token is still valid.
// Revoke the refresh token
await accessToken.revoke('refresh_token');
} catch (error) {
console.log('Error revoking token: ', error.message);
}
As a convenience method, you can also revoke both tokens in a single call:
// 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);
}
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.
try {
await oauth2.authorizationCode.getToken();
} catch(error) {
console.log(error);
}
// => {
// "statusCode": 401,
// "error": "Unauthorized",
// "message": "invalid password"
// }
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
3.0.0
#260 Use @hapi/wreck v15. This version changes how a baseUrl is resolved against a path, affecting how auth.tokenHost
, auth.tokenPath
, auth.authorizeHost
and auth.authorizePath
are resolved when using the .getToken
methods. See @hapi/wreck breaking changes to better understand potential issues that may arise.
#260 Use new Node.js WHATWG URL api instead of the legacy url module. This change affects how auth.authorizeHost
and auth.authorizePath
are resolved when using the authorizationCode.authorizeURL
method.
#256 Users can override the grant_type
parameter when performing a token exchange throught the .getToken
method. Useful in cases where the auth server uses a value different from the standard.
#256 Token exchange methods no longer mutate provided arguments
#255 Follow up to 20 redirects by default
#200 #256 Change default multiple scope encoding from using comma to spaces on all token exchange methods
#88 Change JSON response parsing mode from smart
to strict
. Since the OAuth2 specification indicates only JSON responses are valid, any non-JSON response throws an error instead of resolving into a Buffer. Use http.json = true
to restore the previous behavior.
#270 All token exchange methods now accept an optional argument to override non-essential http options or read parsing options.
#268 All token exchange methods can be called without arguments
#263 Use @hapi/joi v16. No breaking changes are expected.
FAQs
Node.js client for OAuth2
The npm package simple-oauth2 receives a total of 158,901 weekly downloads. As such, simple-oauth2 popularity was classified as popular.
We found that simple-oauth2 demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.