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-clientInstalar as dependências
Adicione ao projeto o servidor Express, o gerenciador de sessão e a biblioteca OpenID Connect oficial do Ory/panva.
npm install openid-client express express-sessionDescobrir 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.
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.
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.
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.
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.
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.
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.
function requireAuth(req, res, next) {
if (!req.session.userInfo) {
return res.redirect('/login');
}
next();
}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.
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.