TAJMAC Auth

Using TAJMAC Auth as an OIDC Provider

TAJMAC Auth implements OpenID Connect Core 1.0 and can act as an identity provider for any OIDC-compatible application.

Discovery URL

The OpenID Connect discovery document is served at:

http://localhost:3002/.well-known/openid-configuration

This document contains all endpoint URLs, supported scopes, and signing keys.

Register an OAuth Client

  1. 1. Open the OAuth Clients section in the admin portal.
  2. 2. Click New Client.
  3. 3. Set the Redirect URI (e.g. http://localhost:3000/auth/callback).
  4. 4. For public clients (SPAs, mobile), select Public type — no client secret required.
  5. 5. For server-side apps, select Confidential — copy the generated secret.

Authorization Code + PKCE Flow

Step 1: Redirect to authorization endpoint

import { generateCodeVerifier, generateCodeChallenge } from "pkce-challenge";

const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
sessionStorage.setItem("pkce_verifier", codeVerifier);

const params = new URLSearchParams({
  response_type: "code",
  client_id: "YOUR_CLIENT_ID",
  redirect_uri: "http://localhost:3000/auth/callback",
  scope: "openid profile email",
  code_challenge: codeChallenge,
  code_challenge_method: "S256",
  state: crypto.randomUUID(),
});

window.location.href = `http://localhost:3002/oidc/auth?${params}`;

Step 2: Exchange code for tokens

app/auth/callback/route.ts
export async function GET(req: Request) {
  const { searchParams } = new URL(req.url);
  const code = searchParams.get("code")!;
  const codeVerifier = /* retrieve from session */ "";

  const tokenRes = await fetch("http://localhost:3002/oidc/token", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      grant_type: "authorization_code",
      code,
      redirect_uri: "http://localhost:3000/auth/callback",
      client_id: "YOUR_CLIENT_ID",
      code_verifier: codeVerifier,
    }),
  });

  const tokens = await tokenRes.json();
  // tokens.access_token, tokens.id_token, tokens.refresh_token
}

Step 3: Validate the ID token

import { jwtVerify, createRemoteJWKSet } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("http://localhost:3002/.well-known/jwks.json"),
);

const { payload } = await jwtVerify(idToken, JWKS, {
  issuer: "http://localhost:3002",
  audience: "YOUR_CLIENT_ID",
});

// payload.sub = user ID
// payload.email, payload.name

Framework Examples

Next.js (next-auth / Auth.js)

auth.ts
import NextAuth from "next-auth";

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    {
      id: "tajmac",
      name: "TAJMAC Auth",
      type: "oidc",
      issuer: "http://localhost:3002",
      clientId: process.env.TAJMAC_CLIENT_ID,
      clientSecret: process.env.TAJMAC_CLIENT_SECRET,
    },
  ],
});

Express (passport-openidconnect)

const OidcStrategy = require("passport-openidconnect").Strategy;

passport.use(new OidcStrategy({
  issuer: "http://localhost:3002",
  authorizationURL: "http://localhost:3002/oidc/auth",
  tokenURL: "http://localhost:3002/oidc/token",
  userInfoURL: "http://localhost:3002/oidc/me",
  clientID: process.env.TAJMAC_CLIENT_ID,
  clientSecret: process.env.TAJMAC_CLIENT_SECRET,
  callbackURL: "http://localhost:3000/auth/callback",
  scope: "openid profile email",
}, (issuer, profile, done) => done(null, profile)));
Next: AI Instructions →Back to Docs