RelyKit is a white-label, provider-neutral OpenID Connect toolkit for relying applications. It handles authentication plumbing; your application keeps ownership of users, account status, roles, permissions, pages, wording, and branding.
Release status:
0.1.1is the current coordinated stable version. It preserves token-bearing provider logout as POST and uses standards-defined GET only when no ID-token hint exists so the provider can require confirmation with its Lax session cookie.
@relykit/oidcprovides framework-independent server-side discovery, Authorization Code + S256 PKCE, state and nonce protection, token verification, optional UserInfo, identity-profile strategies, structured RP-initiated logout, and pure access decisions.@relykit/nuxtadapts those primitives to Nuxt 4 and Nitro with configurable routes, sealed sessions, page middleware, protected APIs, and an application principal adapter.
IdFabric is the identity provider: it owns authentication, accounts, MFA, recovery, realms, organizations, teams, invitations, bans, and OAuth clients. RelyKit is installed in each website or SaaS and owns only that application's OIDC flow and local application session. The application remains responsible for its own active-account decision, roles, permissions, and resource authorization.
- Choose the IdFabric realm for this application and note its exact issuer, such as
https://identity.example.com/api/auth. - In that realm, sign in as an administrator and open
/admin/oauth-clients. - Create a confidential web client with a stable client ID, the exact callback
https://app.example.com/api/auth/callback, the exact post-logout callbackhttps://app.example.com/api/auth/logout/callback, andopenid profile emailscopes. Addoffline_accessortenantonly when needed. - Save the generated client secret immediately. IdFabric shows it only once.
- Confirm
<issuer>/.well-known/openid-configurationis reachable from the application server.
Callback and logout URLs are exact-match values. Register separate clients for local development and production instead of weakening redirect validation.
Install both coordinated packages at the same exact stable version:
npm install --save-exact @relykit/oidc@0.1.0 @relykit/nuxt@0.1.0Configure the module and server-only runtime values:
// nuxt.config.ts
export default defineNuxtConfig({
modules: [[
'@relykit/nuxt',
{
principalAdapter: './server/auth/principal-adapter.ts',
loginPage: '/sign-in',
accessDeniedPage: '/not-authorized',
defaultPageAccess: 'authenticated',
requiredApiPermission: 'app:access',
sessionCookieName: 'my-app-session',
flowCookieName: 'my-app-login-flow',
logoutCookieName: 'my-app-logout-flow',
clientStateKey: 'my-app-auth',
},
]],
runtimeConfig: {
auth: {
issuer: '',
clientId: '',
clientSecret: '',
clientAuthenticationMethod: 'client_secret_basic',
redirectUri: '',
postLogoutRedirectUri: '',
scopes: 'openid profile email',
idTokenAlgorithms: 'RS256 ES256 EdDSA',
requestTimeoutMs: 5_000,
sessionPassword: '',
sessionMaxAgeSeconds: 28_800,
secureCookies: 'auto',
},
},
})Use server-only environment variables. Never expose these values through runtimeConfig.public:
NUXT_AUTH_ISSUER=https://identity.example.com/api/auth
NUXT_AUTH_CLIENT_ID=my-saas
NUXT_AUTH_CLIENT_SECRET=<the-secret-shown-once-by-idfabric>
NUXT_AUTH_CLIENT_AUTHENTICATION_METHOD=client_secret_basic
NUXT_AUTH_REDIRECT_URI=https://app.example.com/api/auth/callback
NUXT_AUTH_POST_LOGOUT_REDIRECT_URI=https://app.example.com/api/auth/logout/callback
NUXT_AUTH_SCOPES=openid profile email
NUXT_AUTH_SESSION_PASSWORD=<at-least-32-characters-of-independent-random-data>The RelyKit session password is not the IdFabric client secret. Generate and rotate it independently, keep both values in the application's secret manager, and use HTTPS outside loopback development.
The principal adapter maps a verified external identity to the application's authoritative local principal. Bind it by immutable identity.issuer plus identity.subject, then reload active state and product permissions on protected requests. Email and name are display snapshots, not authorization keys. See the working principal-adapter example.
The application owns its sign-in page. Link it to RelyKit's login handler and keep returnTo local:
<script setup lang="ts">
import { safeReturnPath } from '@relykit/oidc/access'
definePageMeta({ auth: 'guest-only' })
const route = useRoute()
const loginHref = computed(() => `/api/auth/login?${new URLSearchParams({
returnTo: safeReturnPath(route.query.returnTo),
}).toString()}`)
</script>
<template>
<a :href="loginHref">Continue with identity provider</a>
</template>Pages are protected by default. Override a page deliberately:
definePageMeta({ auth: 'public' })
definePageMeta({ auth: 'guest-only' })
definePageMeta({ auth: { permission: 'calendar:write' } })Start the application and verify this sequence:
- A protected page redirects to the application sign-in page.
- Continue redirects to the expected IdFabric realm.
- IdFabric returns to
/api/auth/callback, and RelyKit creates the application session. - A protected API succeeds only for an active local principal with the required application permission.
- Logout clears the local session, then sends a state-bound request to IdFabric's advertised end-session endpoint: form POST when an ID-token hint exists, or top-level GET without a token when the provider must confirm a legacy hintless session. RelyKit validates the callback and returns to the application sign-in page.
- An authenticated IdFabric identity with no active local principal reaches the application's access-denied page.
If the callback fails, compare the configured issuer, client ID, callback URL, authentication method, and scopes character-for-character with the IdFabric client. See the private IdFabric README for the provider side of the same handoff.
- The issuer is server-owned configuration; browser input cannot select discovery endpoints.
- State, nonce, S256 PKCE, exact issuer/audience checks, allowed signing algorithms, bounded responses, and safe local return paths fail closed.
- Access and refresh tokens stay server-side. The verified ID token used for logout is retained only in a dedicated sealed, HttpOnly cookie and appears transiently in the no-store, no-referrer, CSP-constrained provider POST form—not in URLs, logs, JSON, or application state. Hintless logout uses a top-level GET containing only the client ID, exact callback, and one-time state so the provider's Lax session cookie reaches its confirmation flow.
- RelyKit renders no UI and grants no application permission by itself.
Read architecture, configuration, Nuxt integration, security policy, and testing before production use.
The supported stable range is Node.js >=22.18 and <27, npm >=10 and <12, and Nuxt >=4.4 and <5. CI validates Node.js 22.18, 24, and 26 with the pinned Nuxt fixture.
npm ci
npm run check
npm run check:packages
npm run build --workspace @relykit/example-nuxt
npm audit --omit=devSee CONTRIBUTING.md, the MIT license, and docs/releasing.md. Every future publication remains an explicit owner action through the protected release workflow.