{"id":17949,"library":"simple-oauth2","title":"Simple OAuth2 Node.js Client","description":"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.","status":"active","version":"5.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/lelylan/simple-oauth2","tags":["javascript","oauth2","authorization","password","client","credentials"],"install":[{"cmd":"npm install simple-oauth2","lang":"bash","label":"npm"},{"cmd":"yarn add simple-oauth2","lang":"bash","label":"yarn"},{"cmd":"pnpm add simple-oauth2","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Since v5.0.0, the package primarily uses named exports for grant types. The `.create()` method from v4.x was removed.","wrong":"const { AuthorizationCode } = require('simple-oauth2').create(config);","symbol":"{ AuthorizationCode, ClientCredentials, ResourceOwnerPassword }","correct":"import { AuthorizationCode, ClientCredentials, ResourceOwnerPassword } from 'simple-oauth2';"},{"note":"Instantiate the desired grant type class directly after importing it. The factory function `create()` was removed in v5.x.","wrong":"const oauth2 = require('simple-oauth2').create(config);","symbol":"AuthorizationCode (constructor)","correct":"const client = new AuthorizationCode(config);"},{"note":"The `getToken` method returns an `AccessToken` instance, which has helper methods like `refresh()` and `revoke()`.","wrong":"const token = await client.getToken(tokenParams); // then trying to call token.refresh()","symbol":"AccessToken","correct":"const accessToken = await client.getToken(tokenParams);"}],"quickstart":{"code":"import { AuthorizationCode } from 'simple-oauth2';\nimport express from 'express';\nimport 'dotenv/config'; // For process.env\n\nconst app = express();\nconst port = process.env.PORT || 3000;\n\n// Basic configuration for the OAuth2 client\nconst config = {\n  client: {\n    id: process.env.OAUTH_CLIENT_ID ?? 'YOUR_CLIENT_ID',\n    secret: process.env.OAUTH_CLIENT_SECRET ?? 'YOUR_CLIENT_SECRET'\n  },\n  auth: {\n    tokenHost: process.env.OAUTH_TOKEN_HOST ?? 'https://oauth.example.com',\n    authorizePath: process.env.OAUTH_AUTHORIZE_PATH ?? '/oauth/authorize',\n    tokenPath: process.env.OAUTH_TOKEN_PATH ?? '/oauth/token'\n  }\n};\n\nconst client = new AuthorizationCode(config);\nconst redirect_uri = process.env.OAUTH_REDIRECT_URI ?? `http://localhost:${port}/callback`;\nconst scope = process.env.OAUTH_SCOPE ?? 'read write';\n\n// Step 1: Redirect to the authorization server\napp.get('/auth', (req, res) => {\n  const authorizationUri = client.authorizeURL({\n    redirect_uri,\n    scope,\n    state: 'random_state_string' // Should be a securely generated random string\n  });\n  console.log(`Redirecting to: ${authorizationUri}`);\n  res.redirect(authorizationUri);\n});\n\n// Step 2: Handle the callback from the authorization server\napp.get('/callback', async (req, res) => {\n  const { code, state } = req.query;\n  \n  // You should validate the 'state' parameter here to prevent CSRF attacks\n  if (state !== 'random_state_string') {\n    return res.status(403).send('Invalid state parameter');\n  }\n\n  const tokenParams = {\n    code: code as string,\n    redirect_uri,\n    scope\n  };\n\n  try {\n    const accessToken = await client.getToken(tokenParams);\n    console.log('Successfully retrieved access token:');\n    console.log(accessToken.token);\n    \n    // Example: Refresh token if expired (or near expiration)\n    if (accessToken.expired()) {\n      console.log('Access token is expired, attempting to refresh...');\n      const refreshedToken = await accessToken.refresh();\n      console.log('Refreshed token:', refreshedToken.token);\n    }\n    \n    res.send(`Access Token: ${accessToken.token.access_token}<br/>Refresh Token: ${accessToken.token.refresh_token || 'N/A'}`);\n  } catch (error: any) {\n    console.error('Access Token Error', error.message);\n    res.status(500).send(`Authentication failed: ${error.message}`);\n  }\n});\n\napp.get('/', (req, res) => {\n  res.send('<a href=\"/auth\">Login with OAuth2</a>');\n});\n\napp.listen(port, () => {\n  console.log(`Server running at http://localhost:${port}`);\n  console.log('Visit /auth to initiate the OAuth2 flow.');\n});\n","lang":"typescript","description":"This quickstart demonstrates the Authorization Code grant type, covering redirecting a user for authorization, handling the callback, exchanging the authorization code for an access token, and refreshing an expired token. It uses environment variables for sensitive configuration and basic error handling."},"warnings":[{"fix":"Update import statements and instantiation patterns. Instead of `const oauth2 = require('simple-oauth2').create(config);`, use `const { AuthorizationCode } = require('simple-oauth2'); const client = new AuthorizationCode(config);` or `import { AuthorizationCode } from 'simple-oauth2'; const client = new AuthorizationCode(config);`.","message":"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.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Ensure your configuration object includes `auth: { tokenHost: 'https://your-oauth-server.com' }`. This was optional or handled differently in earlier versions.","message":"The `tokenHost` configuration option is now strictly required in the client configuration object for `simple-oauth2` v5.x and above.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Upgrade your Node.js runtime to at least version 14.x. For future compatibility, consider Node.js 16.x or later.","message":"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.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Generate a unique, cryptographically secure random string for the `state` parameter when initiating the authorization flow, store it (e.g., in a session), and verify it upon callback before exchanging the code for a token.","message":"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.","severity":"gotcha","affected_versions":"*"},{"fix":"Use the `accessToken.expired()` helper and `accessToken.refresh()` method to programmatically refresh tokens. Ensure your configuration allows for refresh tokens if needed.","message":"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.","severity":"gotcha","affected_versions":"*"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Change your import to use named exports and instantiate the grant type directly: `import { AuthorizationCode } from 'simple-oauth2'; const client = new AuthorizationCode(config);`","cause":"Attempting to use the `create` factory method from a v4.x import pattern with v5.x, which removed it.","error":"TypeError: (0 , simple_oauth2__WEBPACK_IMPORTED_MODULE_0__.create) is not a function"},{"fix":"Add `tokenHost: 'https://your-oauth-server.com'` to the `auth` section of your configuration object.","cause":"The `tokenHost` property is missing from the `auth` configuration object, which is now mandatory in v5.x.","error":"Error: tokenHost is required. Set `auth.tokenHost` in the configuration."},{"fix":"Double-check your `client.id` and `client.secret` against your OAuth2 provider's registration details. Ensure they are correctly set in your `config` object or environment variables.","cause":"The `client.id` or `client.secret` in the configuration object is incorrect or the client is not registered with the OAuth2 provider.","error":"Access Token Error [OAuth2Error: invalid_client] The client ID provided is not valid."},{"fix":"Refresh tokens can be single-use or expire. If a refresh fails, the user needs to re-authenticate through the full OAuth2 flow. Check your OAuth2 provider's policy on refresh token validity.","cause":"The refresh token used to get a new access token is no longer valid, either due to expiration, revocation, or a one-time use policy.","error":"Error refreshing access token: The refresh token provided is invalid or has expired."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}