I IntelliAuth Docs

Five minutes from npm install to a Node API that validates IntelliAuth sessions on every request. This covers the server-side half of an IntelliAuth integration — pair it with the React quickstart for the browser side.

Before you start

  • An IntelliAuth tenant URL

  • An application registered in the tenant (the same one your frontend uses, or a separate M2M application for backend-only)

  • The application's audience identifier (the value tokens issued for your API will carry as aud)

  • Node 18+ and an Express 4 or 5 project

1. Install the SDK

bash
pnpm add @intelliauth/node-sdk express
# or: npm install @intelliauth/node-sdk express

2. Mount the session-validation middleware

The Node SDK ships an Express middleware that:

  • Reads the Authorization: Bearer <token> header.

  • Validates the token's signature against your tenant's JWKS (cached after first fetch).

  • Confirms the audience matches your API.

  • Confirms the token isn't expired or revoked.

  • Attaches the verified claims to req.user.

ts
import express from 'express'
import { requireSession } from '@intelliauth/node-sdk/express'

const app = express()

app.use(
  requireSession({
    tenantUrl: process.env.INTELLIAUTH_TENANT_URL!,
    audience: 'api.banking.cymmetri.com',
  }),
)

app.get('/me', (req, res) => {
  // req.user is fully typed and validated
  res.json({ sub: req.user.sub, email: req.user.email })
})

app.listen(3000)

That's the full server-side integration. Any route mounted after requireSession rejects requests without a valid bearer token with 401; routes get a typed req.user for the rest.

3. (Optional) Protect specific routes only

If you don't want every route to require auth, mount the middleware per-route instead of globally:

ts
import { requireSession } from '@intelliauth/node-sdk/express'

const auth = requireSession({
  tenantUrl: process.env.INTELLIAUTH_TENANT_URL!,
  audience: 'api.banking.cymmetri.com',
})

app.get('/public', (req, res) => res.send('open to anyone'))
app.get('/private', auth, (req, res) => res.json({ user: req.user }))

Both shapes are fine. App-wide is simpler when most routes need auth; per-route is clearer when you have a public-by-default API with a few protected endpoints.

4. Make programmatic calls with the management client

The session middleware validates incoming tokens. For outbound programmatic calls into the integrator REST surface — look up a user, list applications, manage groups, register a federation connection from a B2B onboarding flow — use the management client. It uses a separate machine-to-machine credential, not your end-user tokens. (Operations that are tenant-admin web-driven — suspending an account, reading audit logs, configuring flows — are not on this surface; those are done by humans in the IntelliAuth admin console.)

ts
import { ManagementClient } from '@intelliauth/node-sdk'

const mgmt = new ManagementClient({
  tenantUrl: process.env.INTELLIAUTH_TENANT_URL!,
  clientId: process.env.INTELLIAUTH_M2M_CLIENT_ID!,
  clientSecret: process.env.INTELLIAUTH_M2M_CLIENT_SECRET!,
})

const user = await mgmt.users.get('usr_01HZX...')
const apps = await mgmt.applications.list({ limit: 50 })

The client credentials grant runs at construction time; the resulting access token is cached and refreshed transparently.

Keep the M2M secret server-side

The management-client credential pair (clientId + clientSecret) is for backend use only. Never ship it to a browser bundle — anyone who reads the bundle can issue tokens against your tenant.

What's next

See also