Introduction
Introduction
ioserver-oidc is a middleware package that adds OIDC/OAuth2 JWT authentication to IOServer applications. It provides ready-to-use classes that slot directly into IOServer's middleware system without requiring changes to your business logic.
IOServer primer
If you are not familiar with IOServer, the key concept to understand is the middleware chain. Every addController and addService call accepts an optional middlewares array. Middlewares run before each HTTP handler or WebSocket connection is established. ioserver-oidc provides middleware classes designed to live in that array.
import { IOServer } from "ioserver";
import { OidcHttpMiddleware, OidcSocketMiddleware } from "ioserver-oidc";
const server = new IOServer({ port: 3000 });
// HTTP: OidcHttpMiddleware runs before every route in ApiController
server.addController({
name: "api",
controller: ApiController,
middlewares: [OidcHttpMiddleware],
});
// WebSocket: OidcSocketMiddleware runs before each new connection to ChatService
server.addService({
name: "chat",
service: ChatService,
middlewares: [OidcSocketMiddleware],
});
await server.start();
The IOServer component model and middleware documentation are the recommended starting point if this is your first time working with the framework.
What ioserver-oidc provides
| Export | Type | Role |
|---|---|---|
OidcConfigManager | BaseManager | Reads environment variables, exposes OidcConfig to sibling middlewares |
OidcHttpMiddleware | BaseMiddleware | Verifies JWT Bearer tokens on HTTP requests |
OidcSocketMiddleware | BaseMiddleware | Verifies JWT tokens on Socket.IO connections |
OidcSocketAdminMiddleware | BaseMiddleware | Role guard — rejects non-admin Socket.IO connections |
verifyOidcToken | function | Low-level JWT verification helper |
OidcConfig | interface | Configuration shape |
OidcUserContext | interface | Auth context injected onto request/socket |
OidcFeatures | type | Feature flags decoded from the features JWT claim |
Authentication flow
Client IOServer auth-service
│ │ │
│ POST /api/resource │ │
│ Authorization: Bearer … │ │
│────────────────────────►│ │
│ │ OidcHttpMiddleware │
│ │ verifyOidcToken() │
│ │ getJwks(jwksUri) ───────► GET /api/auth/jwks
│ │ jwtVerify(token, keyset) ◄──── { keys: [...] }
│ │ → OidcUserContext │
│ │ users.findOrCreate(sub) │
│ │ handler(request, reply) │
│ 200 OK │ │
│◄────────────────────────│ │
JWKS keys are cached in-process per URI. jose refreshes them automatically on signature failure (key rotation) with a minimum 5-minute cooldown, so normal traffic does not trigger repeated round-trips to auth-service.
auth-service compatibility
The package is designed to work with BetterAuth acting as an OAuth2 provider. It expects:
iss— set toAUTH_SERVICE_URLaud— set to the OAuth2client_id(=AUTH_SERVICE_APP_SLUG)sub— stable user identifier- Custom claims:
roles,permissions,features(all optional; default to empty array/object) - JWKS endpoint available at
<AUTH_SERVICE_URL>/api/auth/jwks(or overridden viaAUTH_SERVICE_JWKS_URI)
The verification logic in jwks.ts uses jose.jwtVerify with issuer + audience validation.