A JWT-based SSO bridge client for Nuxt 3 applications. This module connects your Nuxt app to an external JWT authentication server with a specific authentication flow:
- 🌉 Bridge Pattern: Uses a bridge page on the auth domain for token exchange
- 🔑 JWT Token Relay: Exchanges provider tokens for app-specific JWTs
- 🔄 Automatic Refresh: Heartbeat mechanism for session management
- 🎯 Specific Flow: Designed for
/auth/login
,/auth/verify
,/auth/heartbeat
endpoints
- 🔐 JWT-based authentication
- 🔄 Automatic session refresh
- 🛡️ Route protection middleware
- 🎯 Zero-config setup (almost)
- 📦 TypeScript support
- 🚀 SSR compatible
npm install sg-nuxt-jwt-sso-bridge
# or
yarn add sg-nuxt-jwt-sso-bridge
# or
pnpm add sg-nuxt-jwt-sso-bridge
# .env
SSO_BASE_URL=https://auth.example.com
SSO_APP_URL=https://myapp.example.com
export default defineNuxtConfig({
modules: ['sg-nuxt-jwt-sso-bridge'],
// Optional: Override default settings
sso: {
heartbeatInterval: 840000, // Session refresh interval (ms)
tokenCookieName: 'auth-token', // Cookie name for token storage
protectedRoutes: ['/dashboard', '/admin'], // Routes requiring auth
publicRoutes: ['/', '/login', '/about'], // Public routes
// Default login page settings (optional)
useDefaultLoginPage: true, // Use built-in login page (default: true)
loginPagePath: '/login', // Path for login page (default: '/login')
loginPageOptions: {
title: 'Sign in to continue',
subtitle: 'Welcome to our application',
buttonText: 'Sign in with Google',
organizationName: 'Your Company'
},
// Token expiration handling (optional)
onTokenExpired: 'redirect', // 'redirect' | 'reload' | 'none' (default: 'redirect')
tokenExpiredRedirectPath: '/login', // Redirect path for expired tokens
tokenExpiredMessage: 'Your session has expired', // Optional message to show
// Callback redirect (optional)
callbackRedirectPath: '/' // Default redirect after successful login (default: '/')
}
})
The module automatically provides:
- A beautiful default login page at
/login
- Protected route middleware (
sso-auth
) - Auto-imported
useSSO()
composable - Automatic session management
No additional code required!
Just add the module to your config and protect your routes:
<script setup>
// pages/dashboard.vue - This page is protected
definePageMeta({
middleware: 'sso-auth' // Users will be redirected to /login if not authenticated
})
const { user } = useSSO()
</script>
<template>
<div>
<h1>Welcome, {{ user?.name }}!</h1>
</div>
</template>
<script setup>
const { user, isAuthenticated, login, logout } = useSSO()
</script>
<template>
<div>
<div v-if="isAuthenticated">
Welcome, {{ user?.name }}!
<button @click="logout">Logout</button>
</div>
<div v-else>
<button @click="login">Login</button>
</div>
</div>
</template>
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['sg-nuxt-jwt-sso-bridge'],
sso: {
loginPageOptions: {
title: 'Welcome Back',
subtitle: 'Sign in to access your dashboard',
buttonText: 'Continue with Google',
customLogo: '/logo.png',
organizationName: 'Acme Corp'
}
}
})
<script setup>
// This page requires authentication
definePageMeta({
middleware: 'sso-auth'
})
const { user } = useSSO()
</script>
<template>
<div>
<h1>Dashboard</h1>
<p>Hello, {{ user?.email }}</p>
</div>
</template>
const { verifyToken } = useSSO()
// Verify a token manually
const isValid = await verifyToken(token)
The module provides a simple verifyJWT
function for server-side token verification:
// server/api/protected.get.ts
export default defineEventHandler(async (event) => {
// Get token from header or cookie
const token = getHeader(event, 'authorization')?.replace('Bearer ', '')
// or: getCookie(event, 'auth-token')
// Verify token
const result = await verifyJWT(token)
if (!result.valid) {
throw createError({
statusCode: 401,
statusMessage: result.error || 'Unauthorized'
})
}
return {
user: result.user,
data: 'Protected data'
}
})
The verifyJWT
function is automatically available in your server routes - no import needed:
export default defineEventHandler(async (event) => {
const token = getCookie(event, 'auth-token')
const { valid, user } = await verifyJWT(token)
if (!valid) {
return { error: 'Please login' }
}
return { user, data: '...' }
})
export default defineEventHandler(async (event) => {
const token = getCookie(event, 'auth-token')
const { valid, user } = await verifyJWT(token)
return {
publicData: 'Everyone can see this',
...(user && { userData: user })
}
})
If auto-import doesn't work, you can import it directly:
import { verifyJWT } from '@securegraph/sg-nuxt-jwt-sso-bridge/runtime/server/utils/verifyJWT'
interface VerifyResponse {
valid: boolean
user?: any // User object from JWT
error?: string // Error message if invalid
}
<script setup>
const { user, loading, checked } = useSSO()
</script>
<template>
<div>
<!-- Show loading while authentication is being checked -->
<div v-if="loading">Checking authentication...</div>
<!-- Show content only after check is complete -->
<div v-else>
<div v-if="user">
Welcome, {{ user.name }}!
</div>
<div v-else>
Please login to continue
</div>
</div>
</div>
</template>
Configure how the module handles expired tokens:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['sg-nuxt-jwt-sso-bridge'],
sso: {
// Redirect to login page on token expiration (default)
onTokenExpired: 'redirect',
tokenExpiredRedirectPath: '/login',
tokenExpiredMessage: 'Session expired, please login again',
// OR: Reload the page
// onTokenExpired: 'reload',
// OR: Do nothing (handle manually)
// onTokenExpired: 'none'
}
})
The main composable for authentication operations.
-
user
- Reactive reference to current user object -
isAuthenticated
- Reactive reference to authentication state -
checked
- Reactive reference to authentication check completion status -
loading
- Reactive reference to loading state (inverse of checked) -
login(returnTo?: string)
- Function to initiate login flow with optional return URL -
logout()
- Function to logout user -
verifyToken(token: string)
- Function to verify a JWT token -
heartbeat()
- Function to refresh session -
handleCallback(token: string, returnTo?: string)
- Function to handle OAuth callback with optional return URL
This module is designed to work with a specific JWT-based SSO server architecture that implements:
-
GET /auth/login?return_to={url}
- Initiates OAuth login flow -
POST /auth/verify
- Verifies JWT tokens- Request:
{ token: string }
- Response:
{ valid: boolean, user: object }
- Request:
-
GET /auth/heartbeat
- Refreshes session tokens- Header:
Authorization: Bearer {token}
- Response:
{ success: boolean, token: string, user: object }
- Header:
-
GET /auth/callback
- Handles OAuth provider callbacks -
GET /auth/bridge
- Bridge page for cross-domain token exchange
- User visits protected page → Middleware redirects to
/login?return_to=/original-page
- User clicks login → Redirect to SSO server with callback URL containing return_to
- SSO server handles OAuth (Google, GitHub, etc.)
- Bridge page exchanges provider token for app JWT
- Returns to
/auth/callback?token=xxx&return_to=/original-page
- Callback verifies token and redirects to original page
- Heartbeat keeps session alive
- Token expires (401 error) during API call or heartbeat
- Based on
onTokenExpired
setting:-
redirect
: Navigate to login page with optional message -
reload
: Refresh the entire page -
none
: Clear auth state, let app handle it
-
- After re-authentication, user returns to their intended destination
- Direct OAuth providers (use
@nuxtjs/oauth
instead) - SAML providers (use
nuxt-saml
instead) - Simple API key auth
- Firebase Auth, Auth0, Clerk direct integration
Variable | Required | Description |
---|---|---|
SSO_BASE_URL |
Yes | Base URL of your SSO service |
SSO_APP_URL |
No | Your application URL (default: http://localhost:3000) |
# Install dependencies
yarn install
# Run tests
yarn test
# Build module
yarn prepack
# Run dev server
yarn dev
UNLICENSED - This package is proprietary software. All rights reserved.
For questions about this module, please contact your system administrator or the package maintainer.
This module is specifically designed for JWT-based SSO bridge architecture.
For other authentication needs, consider:
-
Direct OAuth:
@nuxtjs/oauth
-
Auth0:
@nuxtjs/auth-next
-
Clerk:
@clerk/nuxt
-
Supabase:
@nuxtjs/supabase
-
Firebase:
@nuxtjs/firebase
-
Generic SSO:
@nuxtjs/auth-next