@mbsoftlabs/nuxt-oidc-auth
v1.0.28
Published
Nuxt 4 module for OIDC/SSO authentication with Laravel Passport or any OIDC provider
Maintainers
Readme
@mbsoftlabs/nuxt-oidc-auth
Nuxt 4 module for OIDC/SSO authentication with Laravel Passport or any OIDC provider
Features
- ✅ Zero-config setup - Just add environment variables and you're done
- ✅ PKCE flow - Secure OAuth 2.0 authorization with PKCE
- ✅ Auto-registered routes -
/auth/login,/auth/callback,/auth/logout, etc. - ✅ Composable API - Use
useAuth()in your components - ✅ Route middleware - Protect routes with
definePageMeta({ middleware: ['auth'] }) - ✅ Session management - Configurable Redis or memory storage
- ✅ TypeScript - Full type safety
- ✅ Token refresh - Automatic token refresh before expiration
- ✅ Flexible - Works with any OIDC provider (Laravel Passport, Keycloak, Auth0, etc.)
Quick Start
1. Install the module
npm i @mbsoftlabs/nuxt-oidc-auth2. Add to nuxt.config.ts
export default defineNuxtConfig({
modules: ['@mbsoftlabs/nuxt-oidc-auth'],
oidcAuth: {
issuer: process.env.NUXT_OIDC_ISSUER,
clientId: process.env.NUXT_OIDC_CLIENT_ID,
clientSecret: process.env.NUXT_OIDC_CLIENT_SECRET,
redirectUri: process.env.NUXT_OIDC_REDIRECT_URI,
postLogoutRedirectUri: process.env.NUXT_OIDC_POST_LOGOUT_REDIRECT_URI,
sessionSecret: process.env.NUXT_OIDC_SESSION_SECRET
},
nitro: {
storage: {
session: {
driver: process.env.NUXT_SESSION_STORAGE_DRIVER || 'memory',
url: process.env.NUXT_SESSION_STORAGE_URL || 'redis://localhost:6379',
},
},
},
})3. Configure environment variables
Create a .env file:
# OIDC Provider Configuration
NUXT_OIDC_ISSUER=https://id.example.test
NUXT_OIDC_CLIENT_ID=your-client-id
NUXT_OIDC_CLIENT_SECRET=your-client-secret
NUXT_OIDC_REDIRECT_URI=http://localhost:3000/auth/callback
NUXT_OIDC_POST_LOGOUT_REDIRECT_URI=http://localhost:3000
# Session Configuration
NUXT_OIDC_SESSION_SECRET=your-super-secret-key-generate-with-openssl-rand-hex-32
# Optional: Session Storage (default: memory)
NUXT_SESSION_STORAGE_DRIVER=redis
# NUXT_SESSION_STORAGE_URL=redis://localhost:63794. Generate session secret
openssl rand -hex 325. Use in your pages
<script setup lang="ts">
const { user, authenticated, login, logout } = useAuth()
</script>
<template>
<div>
<div v-if="authenticated">
<h1>Welcome, {{ user?.name }}</h1>
<p>Email: {{ user?.email }}</p>
<button @click="logout">Logout</button>
</div>
<div v-else>
<button @click="login">Login with SSO</button>
</div>
</div>
</template>Configuration
Module Options
export default defineNuxtConfig({
modules: ['@mbsoftlabs/nuxt-oidc-auth'],
oidcAuth: {
// OIDC Provider
issuer: 'https://id.example.test', // Required: OIDC issuer URL
clientId: 'your-client-id', // Required: OAuth client ID
clientSecret: 'your-client-secret', // Optional: OAuth client secret
redirectUri: 'http://localhost:3000/auth/callback', // Required: Callback URL
postLogoutRedirectUri: 'http://localhost:3000', // Optional: Post-logout redirect
// Session Configuration
sessionSecret: 'your-secret-key', // Required: Session encryption secret
sessionCookieName: 'nuxt_oidc_session', // Optional: Cookie name
sessionCookieSecure: false, // Optional: Cookie secure flag (production: true)
sessionStorageDriver: 'memory', // Optional: 'memory' or 'redis'
redisUrl: 'redis://localhost:6379', // Optional: Redis URL for session storage
// Routes
routePrefix: '/auth' // Optional: Prefix for auth routes
}
})Environment Variables
The module reads from these environment variables (fallback to runtime config):
| Variable | Required | Description | Default |
|----------|----------|-------------|---------|
| NUXT_OIDC_ISSUER | ✅ | OIDC issuer URL | - |
| NUXT_OIDC_CLIENT_ID | ✅ | OAuth client ID | - |
| NUXT_OIDC_CLIENT_SECRET | ❌ | OAuth client secret | - |
| NUXT_OIDC_REDIRECT_URI | ✅ | OAuth redirect URI | - |
| NUXT_OIDC_POST_LOGOUT_REDIRECT_URI | ❌ | Post-logout redirect URI | - |
| NUXT_OIDC_SESSION_SECRET | ✅ | Session encryption secret | - |
| NUXT_OIDC_SESSION_COOKIE_NAME | ❌ | Session cookie name | nuxt_oidc_session |
| NUXT_OIDC_SESSION_COOKIE_SECURE | ❌ | Cookie secure flag | false |
| NUXT_SESSION_STORAGE_DRIVER | ❌ | Session storage driver | memory |
| NUXT_SESSION_STORAGE_URL | ❌ | Redis URL | redis://localhost:6379 |
Usage
Protecting Routes
Add the auth middleware to any page you want to protect:
<script setup lang="ts">
definePageMeta({
middleware: ['auth']
})
</script>
<template>
<div>
<h1>Protected Page</h1>
<p>Only authenticated users can see this.</p>
</div>
</template>Guest-Only Routes (e.g., Login Page)
Use the guest middleware to redirect authenticated users away:
<script setup lang="ts">
definePageMeta({
middleware: ['guest']
})
</script>
<template>
<div>
<h1>Login Page</h1>
<p>Authenticated users will be redirected to home.</p>
</div>
</template>Accessing User Data
<script setup lang="ts">
const { user, authenticated, loading } = useAuth()
watchEffect(() => {
if (authenticated.value) {
console.log('User:', user.value)
console.log('User roles:', user.value?.roles)
console.log('User modules:', user.value?.modules)
console.log('Tenant ID:', user.value?.tenant_id)
}
})
</script>Manual Login/Logout
<script setup lang="ts">
const { login, logout } = useAuth()
const handleLogin = () => {
// Redirect to /auth/login
login()
// Or with custom return URL
login('/dashboard')
}
const handleLogout = () => {
// Redirect to /auth/logout
logout()
}
</script>Checking Session Status
<script setup lang="ts">
const { authenticated, accessTokenExpiresAt, sessionExpiresAt, checkSession } = useAuth()
// Manually refresh session data
const refreshSession = () => {
checkSession()
}
// Check if token is about to expire
const isTokenExpiringSoon = computed(() => {
if (!accessTokenExpiresAt.value) return false
const timeUntilExpiry = accessTokenExpiresAt.value - Date.now()
return timeUntilExpiry < 5 * 60 * 1000 // Less than 5 minutes
})
</script>Available Routes
The module automatically registers these server routes:
| Route | Method | Description |
|-------|--------|-------------|
| /auth/login | GET | Initiates OIDC login flow |
| /auth/callback | GET | Handles OAuth callback |
| /auth/logout | GET | Logs out user and redirects |
| /auth/refresh | POST | Refreshes access token |
| /auth/session | GET | Returns current session data |
User Data Structure
The session user object contains:
interface SessionUser {
sub: string // Unique user ID
name?: string // User's name
email?: string // User's email
email_verified?: boolean // Email verification status
roles?: string[] // User roles (from OIDC claims)
modules?: string[] // User modules (from OIDC claims)
tenant_id?: string // Tenant ID (from OIDC claims)
}Session Storage
Memory Storage (Development)
NUXT_SESSION_STORAGE_DRIVER=memorySessions are stored in memory and are lost on server restart. Suitable for development only.
Redis Storage (Production)
NUXT_SESSION_STORAGE_DRIVER=redis
NUXT_SESSION_STORAGE_URL=redis://localhost:6379Sessions are stored in Redis and persist across server restarts. Recommended for production.
Token Management
The module automatically handles:
- Token Exchange - Exchanges authorization code for access/refresh tokens
- ID Token Validation - Validates ID token using JWKS from issuer
- Token Refresh - Automatically refreshes access tokens before expiration
- Session Expiration - Handles session expiration and cleanup
Tokens are refreshed 5 minutes before expiration to ensure uninterrupted access.
Security Features
- ✅ PKCE (Proof Key for Code Exchange) - Prevents authorization code interception
- ✅ State & Nonce - Prevents CSRF and replay attacks
- ✅ Secure Session Storage - Encrypted session data with AES-GCM
- ✅ HTTP-Only Cookies - Prevents XSS attacks on session cookies
- ✅ ID Token Validation - Verifies JWT signature and claims
- ✅ JWKS Caching - Efficient JWT key verification
Identity Server Setup
Laravel Passport (OIDC)
Make sure your Laravel Passport server is configured with:
- Enable OIDC: Ensure Passport's OIDC features are enabled
- Grant Type: Enable
authorization_codegrant with PKCE - Scopes: Enable
openid,profile,email,offline_accessscopes - Claims: Add custom claims to your token endpoint if needed
Other OIDC Providers
This module works with any standard OIDC provider:
- Keycloak - Open source identity provider
- Auth0 - Commercial authentication service
- Okta - Enterprise identity management
- Azure AD - Microsoft's identity platform
- Google Identity Platform - Google's OAuth/OIDC service
- Custom - Any provider implementing OIDC standard
Example Projects
With Laravel Passport
# .env
NUXT_OIDC_ISSUER=https://identity-server.example.test
NUXT_OIDC_CLIENT_ID=your-laravel-passport-client-id
NUXT_OIDC_CLIENT_SECRET=your-laravel-passport-client-secret
NUXT_OIDC_REDIRECT_URI=http://localhost:3000/auth/callback
NUXT_OIDC_SESSION_SECRET=your-secret-keyWith Keycloak
# .env
NUXT_OIDC_ISSUER=https://keycloak.example.test/realms/your-realm
NUXT_OIDC_CLIENT_ID=your-keycloak-client-id
NUXT_OIDC_CLIENT_SECRET=your-keycloak-client-secret
NUXT_OIDC_REDIRECT_URI=http://localhost:3000/auth/callback
NUXT_OIDC_SESSION_SECRET=your-secret-keyWith Auth0
# .env
NUXT_OIDC_ISSUER=https://your-tenant.auth0.com
NUXT_OIDC_CLIENT_ID=your-auth0-client-id
NUXT_OIDC_CLIENT_SECRET=your-auth0-client-secret
NUXT_OIDC_REDIRECT_URI=http://localhost:3000/auth/callback
NUXT_OIDC_SESSION_SECRET=your-secret-keyTypeScript Support
The module is written in TypeScript and provides full type safety:
import type { SessionUser, AuthState, UseAuthReturn } from '@mbsoftlabs/nuxt-oidc-auth'
// Types are available globally in your Nuxt app
const auth: UseAuthReturn = useAuth()
const user: SessionUser | null = auth.user.valueDevelopment
# Install dependencies
npm install
# Run playground
npm run dev
# Build module
npm run build
# Prepare for publish
npm run prepareContributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details.
Support
For issues and questions, please use the GitHub Issues.
Credits
Built with ❤️ for the Nuxt.js community
