Documentation
Express
Classic Node.js Express routes for OAuth login and callback.
server.ts
import express from "express";
import { createPkcePair } from "./pkce";
const app = express();
const ISSUER = process.env.AUTH_ISSUER!; // https://auth.rdnt.live/api/auth
app.get("/auth/login", (req, res) => {
const { verifier, challenge } = createPkcePair();
const state = crypto.randomUUID();
req.session.oidc = { verifier, state };
const url = new URL(`${ISSUER}/oauth2/authorize`);
url.searchParams.set("response_type", "code");
url.searchParams.set("client_id", process.env.AUTH_CLIENT_ID!); // YOUR_CLIENT_ID
url.searchParams.set("redirect_uri", process.env.AUTH_REDIRECT_URI!);
url.searchParams.set("scope", "openid profile email offline_access");
url.searchParams.set("state", state);
url.searchParams.set("code_challenge", challenge);
url.searchParams.set("code_challenge_method", "S256");
res.redirect(url.toString());
});
app.get("/auth/callback", async (req, res) => {
const { code, state } = req.query;
if (state !== req.session.oidc?.state) return res.status(400).send("Invalid state");
const body = new URLSearchParams({
grant_type: "authorization_code",
code: String(code),
redirect_uri: process.env.AUTH_REDIRECT_URI!,
client_id: process.env.AUTH_CLIENT_ID!,
client_secret: process.env.AUTH_CLIENT_SECRET!, // YOUR_CLIENT_SECRET
code_verifier: req.session.oidc.verifier,
});
const tokenRes = await fetch(`${ISSUER}/oauth2/token`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body,
});
const tokens = await tokenRes.json();
// verify id_token, create session
res.redirect("/");
});