IntegrateBackends
Express.js integration
Authenticate Express.js routes against Olympus
Express + Olympus uses standard OAuth2 introspection (or JWT validation if you've configured JWT tokens).
Setup
bun add express express-session passport openid-clientOIDC strategy (server-side login)
import express from "express";
import session from "express-session";
import passport from "passport";
import { Issuer, Strategy } from "openid-client";
const app = express();
app.use(session({ secret: process.env.SESSION_SECRET!, resave: false, saveUninitialized: false }));
app.use(passport.session());
(async () => {
const issuer = await Issuer.discover(process.env.OLYMPUS_ISSUER!);
const client = new issuer.Client({
client_id: process.env.OLYMPUS_CLIENT_ID!,
client_secret: process.env.OLYMPUS_CLIENT_SECRET!,
redirect_uris: [process.env.OLYMPUS_REDIRECT_URI!],
response_types: ["code"],
});
passport.use("olympus", new Strategy(
{ client, usePKCE: "S256" },
(tokenSet, userinfo, done) => {
done(null, { id: tokenSet.claims().sub, ...userinfo });
}
));
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((obj, done) => done(null, obj));
app.get("/auth/login", passport.authenticate("olympus"));
app.get("/auth/callback", passport.authenticate("olympus", {
successRedirect: "/",
failureRedirect: "/login-failed",
}));
})();Protect routes
function requireAuth(req, res, next) {
if (!req.user) return res.redirect("/auth/login");
next();
}
app.get("/dashboard", requireAuth, (req, res) => {
res.send(`Hello ${req.user.email}`);
});API token introspection
For API endpoints consumed by SPAs/mobile/M2M:
import express from "express";
app.use("/api", async (req, res, next) => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) return res.status(401).json({ error: "missing_token" });
const response = await fetch(`${process.env.OLYMPUS_ISSUER}/admin/oauth2/introspect`, {
method: "POST",
headers: {
"content-type": "application/x-www-form-urlencoded",
authorization: `Basic ${Buffer.from(`${process.env.HYDRA_ADMIN_USER}:${process.env.HYDRA_ADMIN_PASS}`).toString("base64")}`,
},
body: new URLSearchParams({ token }),
});
const info = await response.json();
if (!info.active) return res.status(401).json({ error: "inactive" });
req.tokenInfo = info;
next();
});Logout
app.post("/auth/logout", (req, res) => {
req.logout(() => {
res.redirect(`${process.env.OLYMPUS_ISSUER}/oauth2/sessions/logout`);
});
});