Simple OAuth2 Node.js Client
raw JSON →Simple OAuth2 is a robust Node.js client library that provides a straightforward interface for interacting with OAuth 2.0 authorization servers. It supports various standard grant types including Authorization Code, Resource Owner Password Credentials, and Client Credentials, making it adaptable for diverse application architectures from web services to CLI tools. The package is currently stable at version 5.1.0, which mandates Node.js 14.x or higher, with a development branch (6.x) targeting Node.js 16.x and above. While a strict release cadence is not published, active development and maintenance are evident. Its primary differentiator lies in simplifying complex OAuth2 flows into an easy-to-use, promise-based API specifically for Node.js environments.
Common errors
error TypeError: (0 , simple_oauth2__WEBPACK_IMPORTED_MODULE_0__.create) is not a function ↓
import { AuthorizationCode } from 'simple-oauth2'; const client = new AuthorizationCode(config); error Error: tokenHost is required. Set `auth.tokenHost` in the configuration. ↓
tokenHost: 'https://your-oauth-server.com' to the auth section of your configuration object. error Access Token Error [OAuth2Error: invalid_client] The client ID provided is not valid. ↓
client.id and client.secret against your OAuth2 provider's registration details. Ensure they are correctly set in your config object or environment variables. error Error refreshing access token: The refresh token provided is invalid or has expired. ↓
Warnings
breaking Version 5.x introduced significant breaking changes. The primary export switched from a default export (e.g., `require('simple-oauth2').create`) to named exports for each grant type (e.g., `{ AuthorizationCode, ClientCredentials }`). The `create` factory method was removed. ↓
breaking The `tokenHost` configuration option is now strictly required in the client configuration object for `simple-oauth2` v5.x and above. ↓
breaking The library now explicitly requires Node.js 14.x or higher for 5.x releases, and Node.js 16.x or higher for the 6.x development branch. Older Node.js versions are no longer supported. ↓
gotcha Always validate the `state` parameter received in the OAuth2 callback URL against the one you sent. This is crucial for preventing Cross-Site Request Forgery (CSRF) attacks. ↓
gotcha Access tokens have a limited lifetime. It's essential to implement refresh token logic to obtain new access tokens without re-authenticating the user once the current one expires. ↓
Install
npm install simple-oauth2 yarn add simple-oauth2 pnpm add simple-oauth2 Imports
- { AuthorizationCode, ClientCredentials, ResourceOwnerPassword } wrong
const { AuthorizationCode } = require('simple-oauth2').create(config);correctimport { AuthorizationCode, ClientCredentials, ResourceOwnerPassword } from 'simple-oauth2'; - AuthorizationCode (constructor) wrong
const oauth2 = require('simple-oauth2').create(config);correctconst client = new AuthorizationCode(config); - AccessToken wrong
const token = await client.getToken(tokenParams); // then trying to call token.refresh()correctconst accessToken = await client.getToken(tokenParams);
Quickstart
import { AuthorizationCode } from 'simple-oauth2';
import express from 'express';
import 'dotenv/config'; // For process.env
const app = express();
const port = process.env.PORT || 3000;
// Basic configuration for the OAuth2 client
const config = {
client: {
id: process.env.OAUTH_CLIENT_ID ?? 'YOUR_CLIENT_ID',
secret: process.env.OAUTH_CLIENT_SECRET ?? 'YOUR_CLIENT_SECRET'
},
auth: {
tokenHost: process.env.OAUTH_TOKEN_HOST ?? 'https://oauth.example.com',
authorizePath: process.env.OAUTH_AUTHORIZE_PATH ?? '/oauth/authorize',
tokenPath: process.env.OAUTH_TOKEN_PATH ?? '/oauth/token'
}
};
const client = new AuthorizationCode(config);
const redirect_uri = process.env.OAUTH_REDIRECT_URI ?? `http://localhost:${port}/callback`;
const scope = process.env.OAUTH_SCOPE ?? 'read write';
// Step 1: Redirect to the authorization server
app.get('/auth', (req, res) => {
const authorizationUri = client.authorizeURL({
redirect_uri,
scope,
state: 'random_state_string' // Should be a securely generated random string
});
console.log(`Redirecting to: ${authorizationUri}`);
res.redirect(authorizationUri);
});
// Step 2: Handle the callback from the authorization server
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
// You should validate the 'state' parameter here to prevent CSRF attacks
if (state !== 'random_state_string') {
return res.status(403).send('Invalid state parameter');
}
const tokenParams = {
code: code as string,
redirect_uri,
scope
};
try {
const accessToken = await client.getToken(tokenParams);
console.log('Successfully retrieved access token:');
console.log(accessToken.token);
// Example: Refresh token if expired (or near expiration)
if (accessToken.expired()) {
console.log('Access token is expired, attempting to refresh...');
const refreshedToken = await accessToken.refresh();
console.log('Refreshed token:', refreshedToken.token);
}
res.send(`Access Token: ${accessToken.token.access_token}<br/>Refresh Token: ${accessToken.token.refresh_token || 'N/A'}`);
} catch (error: any) {
console.error('Access Token Error', error.message);
res.status(500).send(`Authentication failed: ${error.message}`);
}
});
app.get('/', (req, res) => {
res.send('<a href="/auth">Login with OAuth2</a>');
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
console.log('Visit /auth to initiate the OAuth2 flow.');
});