Integrar com Express.js

Adicione autenticação OpenID Connect a uma aplicação Node.js server-side em minutos usando openid-client.

panva/node-openid-client
Esta integração usa o fluxo Authorization Code com client secret — adequado para aplicações server-side onde a chave fica no backend. Registre o cliente em sentinel-admin → OAuth2 Clients → New Client.
1

Instalar as dependências

Adicione ao projeto o servidor Express, o gerenciador de sessão e a biblioteca OpenID Connect oficial do Ory/panva.

Terminal
npm install openid-client express express-session
2

Descobrir o issuer e criar o cliente

Use Issuer.discover() para carregar os metadados do servidor de autorização automaticamente. Em seguida, instancie o Client com as credenciais do seu aplicativo registrado no sentinel-admin.

src/auth.js
const { Issuer, generators } = require('openid-client');

let _client = null;

async function getClient() {
  if (_client) return _client;

  const issuer = await Issuer.discover('https://auth.sentinel-identity.com');

  _client = new issuer.Client({
    client_id: '<SEU_CLIENT_ID>',
    client_secret: '<SEU_CLIENT_SECRET>',
    redirect_uris: ['http://localhost:3000/callback'],
    response_types: ['code'],
  });

  return _client;
}

module.exports = { getClient, generators };

O resultado de Issuer.discover() é cacheado para evitar uma requisição de rede a cada request.

3

Rota de login

Gere um code_verifier PKCE, salve-o na sessão e redirecione o usuário para a URL de autorização do Sentinel.

src/index.js
const express = require('express');
const session = require('express-session');
const { getClient, generators } = require('./auth');

const app = express();

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
}));

app.get('/login', async (req, res) => {
  const client = await getClient();
  const code_verifier = generators.codeVerifier();
  const code_challenge = generators.codeChallenge(code_verifier);

  req.session.code_verifier = code_verifier;

  const authorizationUrl = client.authorizationUrl({
    scope: 'openid profile email',
    code_challenge,
    code_challenge_method: 'S256',
  });

  res.redirect(authorizationUrl);
});

Mesmo sendo uma aplicação confidencial com client_secret, o uso de PKCE é recomendado como camada extra de proteção contra interceptação de código.

4

Rota de callback

Troque o authorization code por tokens usando client.callback(), recupere as informações do usuário com client.userinfo() e armazene-as na sessão.

src/index.js
app.get('/callback', async (req, res) => {
  const client = await getClient();
  const params = client.callbackParams(req);

  const tokenSet = await client.callback(
    'http://localhost:3000/callback',
    params,
    { code_verifier: req.session.code_verifier },
  );

  const userInfo = await client.userinfo(tokenSet.access_token);
  req.session.userInfo = userInfo;
  req.session.code_verifier = undefined;

  res.redirect('/profile');
});

client.callback() valida automaticamente a assinatura do ID Token, o nonce e o code_challenge — não é necessário fazer essas verificações manualmente.

5

Middleware de proteção

Crie uma função de middleware que verifica se a sessão contém dados do usuário. Se não estiver autenticado, redireciona para o login.

src/index.js
function requireAuth(req, res, next) {
  if (!req.session.userInfo) {
    return res.redirect('/login');
  }
  next();
}
6

Rota protegida

Aplique o middleware requireAuth a qualquer rota que exija autenticação. Os dados do usuário ficam disponíveis em req.session.userInfo.

src/index.js
app.get('/profile', requireAuth, (req, res) => {
  const { sub, name, email } = req.session.userInfo;
  res.json({ sub, name, email });
});

app.get('/logout', (req, res) => {
  req.session.destroy();
  res.redirect('/');
});

app.listen(3000, () => {
  console.log('Servidor rodando em http://localhost:3000');
});

Em produção, configure express-session com um store persistente (ex.: connect-redis ou connect-pg-simple) para não perder sessões ao reiniciar o servidor.