Signup & Access ControlAI Workflow
Complete authentication pipeline: SAML SSO login, JWT token issuance, persistent sessions, and role-based access control. One flow from login to permission check.
Prerequisites
Environment variables
IDP_CERTJWT_SECRETSESSION_SECRETInstall
npx radzor@latest recipe add auth-pipelineAI Prompt
“Run `npx radzor@latest add saml-auth jwt-auth session-manager rbac` to install 4 Radzor components. Then read components/radzor/saml-auth/radzor.manifest.json, components/radzor/jwt-auth/radzor.manifest.json, components/radzor/session-manager/radzor.manifest.json, components/radzor/rbac/radzor.manifest.json and each component's llm/integration.md. Wire them together to complete authentication pipeline: SAML SSO login, JWT token issuance, persistent sessions, and role-based access control. One flow from login to permission check. Use the manifest's inputs (check envVar for required environment variables), outputs (check fields for object shapes), composability (check mapField for field extraction), and actions — don't invent custom interfaces.”
Paste this into Claude Code, Cursor, Windsurf, or any AI coding agent.
Pipeline
SamlAuth
Handles SAML SSO login
JwtAuth
Issues JWT access tokens
SessionManager
Manages server-side sessions
Rbac
Enforces role-based permissions
Scaffolded Code
// npx radzor@latest add saml-auth jwt-auth session-manager rbac
import { SamlAuth } from "./components/radzor/saml-auth"
import { JwtAuth } from "./components/radzor/jwt-auth"
import { SessionManager } from "./components/radzor/session-manager"
import { Rbac } from "./components/radzor/rbac"
const saml = new SamlAuth({
entityId: "https://myapp.com",
acsUrl: "https://myapp.com/auth/saml/callback",
idpLoginUrl: "https://idp.example.com/saml/login",
idpCert: process.env.IDP_CERT!,
})
const jwt = new JwtAuth({ secret: process.env.JWT_SECRET!, issuer: "myapp", expiresIn: 3600 })
const sessions = new SessionManager({ secret: process.env.SESSION_SECRET!, ttl: 86400 })
const rbac = new Rbac({})
rbac.defineRole("viewer", ["read:content"])
rbac.defineRole("editor", ["read:content", "write:content"], ["viewer"])
rbac.defineRole("admin", ["read:content", "write:content", "manage:users"], ["editor"])
// 1. Redirect to SAML IdP
function getLoginUrl() {
return saml.generateLoginUrl("/dashboard")
}
// 2. Handle SAML callback
async function handleSamlCallback(samlResponse: string) {
const user = await saml.validateResponse(samlResponse)
// Issue JWT
const token = jwt.sign({ sub: user.nameId, email: user.attributes?.email })
// Create session
const { sessionId, cookie } = await sessions.create({
userId: user.nameId,
email: user.attributes?.email,
token,
})
// Assign role based on IdP attributes
const role = user.attributes?.role === "admin" ? "admin" : "editor"
rbac.assignRole(user.nameId, role)
return { cookie, token }
}
// 3. Protect routes with RBAC
async function protectedHandler(req: Request, permission: string) {
const sessionId = req.headers.get("cookie") ?? ""
const data = await sessions.get(sessionId)
if (!data) throw new Error("Unauthorized")
const { allowed } = rbac.checkPermission(data.userId as string, permission)
if (!allowed) throw new Error("Forbidden")
return data
}Components used
LLM tip
Pass all 4 radzor.manifest.json files to your agent at once. It will read the outputs of each step and match them against the inputs of the next — wiring the full pipeline without any extra instructions.