Node.js Quickstart
Use this guide to add ThunderID authentication to a Node.js service using the @thunderid/node SDK.
What You Will Learn
- Create a Node.js project
- Install the
@thunderid/nodepackage
- Authenticate a service with the
client_credentialsgrant
- Use the resulting access token to call business logic
Prerequisites
- About 10 minutes
- Node.js 18+ installed on your system
- npm, yarn, or pnpm
- Your preferred code editor
Run ThunderID
Start a local ThunderID instance. Pick the method that works best for you:
Requires Node.js 18+
Full install guide →Once it's running, the console is available at https://localhost:8090/console.
Create an Application
-
Sign in to the Console.
Test UserIf you used the default setup, sign in to the Console as
adminwith the password generated during setup and printed to the setup output (unless you supplied your own). -
Navigate to Applications.
-
Click Add Application.
-
From the Choose a type page, select Backend Service.
-
Enter a name (e.g.
My Node.js Service). -
Click Create.
Backend Service applications are pre-configured for the client_credentials grant with client_secret_basic authentication. No OAuth 2.0 redirect URI or extra setup is needed.
Copy the Client ID from the General tab, and the Client Secret from the window that pops up when the application is created; it's shown only once (if lost, regenerate it from the application's Credentials tab).
Create a Node.js Project
Initialize a new Node.js project:
npm
Yarn
pnpm
mkdir my-node-service
cd my-node-service
npm init -y
mkdir my-node-service
cd my-node-service
yarn init -y
mkdir my-node-service
cd my-node-service
pnpm init
Install @thunderid/node
Install the ThunderID Node.js SDK:
npm
Yarn
pnpm
npm install @thunderid/node
yarn add @thunderid/node
pnpm add @thunderid/node
Authenticate as the Service
Create an index.mjs file and initialize ThunderIDNodeClient with grantType: 'client_credentials'. With that set, getAccessToken() authenticates as the service itself, no session and no sign-in, and transparently fetches, caches, and refreshes the token.
import { ThunderIDNodeClient } from '@thunderid/node';
const client = new ThunderIDNodeClient();
await client.initialize({
baseUrl: 'https://localhost:8090',
clientId: '<your-client-id>',
clientSecret: '<your-client-secret>',
grantType: 'client_credentials',
});
const accessToken = await client.getAccessToken();
const { scope } = await client.decodeJwtToken(accessToken);
console.log(`Authenticated with scope: ${scope}`);
Replace <your-client-id> and <your-client-secret> with the Client ID and Client Secret from your ThunderID application.
Configuration Parameters
| Parameter | Description |
|---|---|
baseUrl | Your ThunderID instance URL (e.g., https://localhost:8090) |
clientId | The Client ID from your ThunderID application |
clientSecret | The Client Secret from your ThunderID application |
grantType | Set to 'client_credentials' to authenticate the service as itself, with no user and no browser redirect |
Call Business Logic With the Token
A real backend keeps authentication in its own module instead of scattering it across business logic. Update index.mjs so the rest of the app asks for a token only when it needs one, instead of handling getAccessToken() and the Authorization header directly:
import { ThunderIDNodeClient } from '@thunderid/node';
const client = new ThunderIDNodeClient();
await client.initialize({
baseUrl: 'https://localhost:8090',
clientId: '<your-client-id>',
clientSecret: '<your-client-secret>',
grantType: 'client_credentials',
});
async function getStock(sku) {
const accessToken = await client.getAccessToken();
// A real backend would attach this as `Authorization: Bearer ${accessToken}`
// on a request to a separate inventory service. This quickstart just proves
// the token was obtained before answering.
console.log(`Requesting ${sku} with a valid access token`);
return { sku, inStock: true };
}
const item = await getStock('SKU-100');
console.log(item);
Run Your Service
Start the script:
npm
Yarn
pnpm
node index.mjs
yarn node index.mjs
pnpm node index.mjs
The script authenticates once, prints the scope it received, then calls getStock() and prints the result before exiting.