Node.js client for OAuth2
—
The Client Credentials Grant is used for service-to-service authentication where no user interaction is required. This flow is typically used for server-to-server communications, background jobs, or microservices.
This grant type implements the OAuth 2.0 Client Credentials flow, which directly exchanges client credentials for an access token without user involvement. The client authenticates using its own credentials rather than acting on behalf of a user.
const { ClientCredentials } = require('simple-oauth2');constructor(options: OAuth2Config): ClientCredentialsCreates a new ClientCredentials instance with OAuth 2.0 configuration validation.
Parameters:
options - OAuth 2.0 configuration object (see main documentation)Example:
const client = new ClientCredentials({
client: {
id: 'your-client-id',
secret: 'your-client-secret'
},
auth: {
tokenHost: 'https://oauth-provider.com',
tokenPath: '/oauth/token'
}
});getToken(params?: ClientCredentialsParams, httpOptions?: any): Promise<AccessToken>Requests an access token using client credentials.
Parameters:
params.scope (string | string[], optional) - Application scopes to requesthttpOptions (object, optional) - HTTP options passed to underlying request libraryReturns: Promise resolving to AccessToken instance
Example:
// Basic token request
const accessToken = await client.getToken();
// Token request with specific scopes
const accessToken = await client.getToken({
scope: ['read:users', 'write:data']
});
// Token request with custom HTTP options
const accessToken = await client.getToken({
scope: 'api:access'
}, {
timeout: 10000,
headers: {
'User-Agent': 'MyApp/1.0'
}
});
console.log('Access token:', accessToken.token.access_token);
console.log('Expires at:', accessToken.token.expires_at);createToken(token: any): AccessTokenCreates an AccessToken instance from a plain token object (e.g., from storage).
Parameters:
token - Plain object representing an access token conforming to RFC 6750Returns: AccessToken instance with full token management capabilities
Example:
// Restore token from database
const storedToken = await database.getToken('client-credentials-token');
const accessToken = client.createToken(storedToken);
// Check if token is still valid
if (!accessToken.expired()) {
// Use existing token
console.log('Using cached token');
} else {
// Get new token
const newToken = await client.getToken();
await database.saveToken('client-credentials-token', newToken.token);
}interface ClientCredentialsParams {
scope?: string | string[];
[key: string]: any;
}const { ClientCredentials } = require('simple-oauth2');
const client = new ClientCredentials({
client: {
id: process.env.CLIENT_ID,
secret: process.env.CLIENT_SECRET
},
auth: {
tokenHost: 'https://api.example.com',
tokenPath: '/oauth/token'
}
});
// Get token for API access
const accessToken = await client.getToken({
scope: 'api:read api:write'
});
// Use token for API requests
const response = await fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${accessToken.token.access_token}`,
'Content-Type': 'application/json'
}
});class APIClient {
constructor(clientConfig) {
this.oauth = new ClientCredentials(clientConfig);
this.cachedToken = null;
}
async getValidToken() {
// Check if we have a cached token that's not expired
if (this.cachedToken && !this.cachedToken.expired(300)) { // 5 min buffer
return this.cachedToken;
}
// Get new token
this.cachedToken = await this.oauth.getToken({
scope: 'api:access'
});
return this.cachedToken;
}
async makeAPIRequest(endpoint, options = {}) {
const token = await this.getValidToken();
return fetch(endpoint, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token.token.access_token}`
}
});
}
}
// Usage
const apiClient = new APIClient({
client: {
id: process.env.CLIENT_ID,
secret: process.env.CLIENT_SECRET
},
auth: {
tokenHost: 'https://api.example.com'
}
});
const userData = await apiClient.makeAPIRequest('https://api.example.com/users');// Microservice A authenticating to Microservice B
const serviceAuth = new ClientCredentials({
client: {
id: 'microservice-a-id',
secret: process.env.SERVICE_SECRET
},
auth: {
tokenHost: 'https://auth.company.com',
tokenPath: '/oauth/token'
},
options: {
bodyFormat: 'json', // Some services prefer JSON
authorizationMethod: 'body' // Some services require credentials in body
}
});
async function callMicroserviceB(data) {
const token = await serviceAuth.getToken({
scope: 'microservice-b:access'
});
return fetch('https://service-b.company.com/api/process', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token.token.access_token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
}Install with Tessl CLI
npx tessl i tessl/npm-simple-oauth2