# Node.js web application (Express)

> Add OneiD to a Node.js application with openid-client, step by step.

Source: https://oltinid.com/docs/quickstarts/node/ · Section: Quickstarts · All OneiD documentation: https://oltinid.com/llms.txt

This quickstart adds OneiD to a server web application with **openid-client**. Every file is complete and runs as it is.

> **Tip:** Using an AI coding agent? Give it this page as Markdown (add `.md` to the address) together with the [Connector specification](https://oltinid.com/docs/ai/connector-specification/). See [Build with AI coding agents](https://oltinid.com/docs/ai/build-with-ai/).

## Before you start

- A OneiD address, for example `https://YOUR_ONEID`. The code below uses the demonstration instance `https://auth.oltinid.com`; replace it with your own.
- A client registered for this application (step 1). The code uses the client ID `quickstart`; replace it with yours.
- A user who can sign in to your OneiD. For the demonstration instance, [ask for a demo account](https://oltinid.com/contact/?topic=demo).

## 1. Register the application

Ask your OneiD administrator to register a client with these settings, or register it yourself in the admin console. See [Register an application](https://oltinid.com/docs/get-started/register-an-application/).

| Setting | Value |
|---|---|
| Client type | `public` (no secret) |
| Grant types | `authorization_code` (add `refresh_token` if you request `offline_access`) |
| Redirect URI | `http://localhost:3000/callback` |
| Post-logout redirect URI | `http://localhost:3000` |
| Allowed scopes | `openid profile email` |

## 2. Install

```bash
npm install express express-session openid-client
```

## 3. Add the code

`server.js`

```js
import express from 'express';
import session from 'express-session';
import * as client from 'openid-client';

const redirectUri = 'http://localhost:3000/callback';

// Reads the endpoints and signing keys from OneiD. `None` = a public client without a secret.
const oneid = await client.discovery(
  new URL('https://auth.oltinid.com'),
  'quickstart',
  undefined,
  client.None(),
);

const app = express();
app.use(session({ secret: 'change-me', resave: false, saveUninitialized: false }));

app.get('/', (req, res) => {
  const user = req.session.user;
  res.send(user ? `Hello, ${user.name}. <a href="/logout">Sign out</a>` : '<a href="/login">Sign in with OneiD</a>');
});

app.get('/login', async (req, res) => {
  const codeVerifier = client.randomPKCECodeVerifier();
  const state = client.randomState();
  req.session.oidc = { codeVerifier, state };

  res.redirect(
    client.buildAuthorizationUrl(oneid, {
      redirect_uri: redirectUri,
      scope: 'openid profile email',
      code_challenge: await client.calculatePKCECodeChallenge(codeVerifier),
      code_challenge_method: 'S256',
      state,
    }).href,
  );
});

app.get('/callback', async (req, res) => {
  const { codeVerifier, state } = req.session.oidc ?? {};
  const tokens = await client.authorizationCodeGrant(oneid, new URL(req.originalUrl, redirectUri), {
    pkceCodeVerifier: codeVerifier,
    expectedState: state,
  });

  req.session.user = tokens.claims(); // the checked ID token: sub, name, email
  req.session.idToken = tokens.id_token;
  res.redirect('/');
});

app.get('/logout', (req, res) => {
  const idToken = req.session.idToken;
  req.session.destroy(() => {
    res.redirect(
      client.buildEndSessionUrl(oneid, {
        id_token_hint: idToken,
        post_logout_redirect_uri: 'http://localhost:3000',
      }).href,
    );
  });
});

app.listen(3000, () => console.log('http://localhost:3000'));
```

## 4. Run it

Set "type": "module" in package.json, then run: node server.js.

The example uses a public client so that it runs without a secret. For your own server application, use a confidential client and pass its secret to the library.

> **Checkpoint:** Open http://localhost:3000 and select Sign in with OneiD. After you sign in, the page shows Hello, followed by the user’s name, and a Sign out link.

## Common issues

- **OneiD shows an error page about the redirect address** (`invalid_request`). The redirect URI the code sends is not registered on the client exactly as written. Register it, including scheme and port.
- **`invalid_grant` from the token endpoint.** The code was used before or expired. Start the sign-in again; do not reload the callback page.
- More errors and fixes: [Errors and troubleshooting](https://oltinid.com/docs/reference/errors/).

## Learn more

- [Authorization code flow with PKCE](https://oltinid.com/docs/guides/authorization-code-pkce/)
- [Sign-out](https://oltinid.com/docs/guides/logout/)
- [Scopes, claims and roles](https://oltinid.com/docs/guides/scopes-claims-roles/)
- [Refresh tokens](https://oltinid.com/docs/guides/refresh-tokens/)
