oidc-hosted-page-nextjs
Implement SSOJet OIDC (Next.js)
This expert AI assistant guide walks you through integrating "Sign in with SSO" functionality into an existing login page in a Next.js application using SSOJet as an OIDC identity provider. The goal is to modify the existing login flow to add SSO support without disrupting the current traditional login functionality (e.g., email/password).
1. Prerequisites
- An existing Next.js application with a login page.
- Basic knowledge of Next.js and its common tools (e.g., App Router).
- An active SSOJet account.
- SSO Connection Setup Guide
- Required libraries:
openid-client(standard for Node.js OIDC integration).
2. Implementation Steps
Step 1: Create Application in SSOJet
- Log in to the SSOJet Dashboard.
- Navigate to Applications.
- Create a new application (e.g., "MyNextjsApp", type Regular Web App).
- Configure the callback URI (e.g.,
http://localhost:3000/api/auth/callback). - Retrieve Client ID and Client Secret.
- Copy the Issuer URL from the Advanced > Endpoints section.

Step 2: Modify the Existing Next.js Project
Substep 2.1: Install Dependencies
Run the following command to install the required OIDC library:
npm install openid-client
Substep 2.2: Configure OIDC
Configure the OIDC provider with your SSOJet credentials. It is recommended to create a dedicated utility file for this configuration (e.g., lib/oidc.ts).
// lib/oidc.ts
import { Issuer } from 'openid-client';
export async function getClient() {
const ssojetIssuer = await Issuer.discover('${ISSUER_URL}'); // e.g. https://auth.ssojet.com
return new ssojetIssuer.Client({
client_id: '${cli_curf51oulvtc716e50eg.ad4a67ec19ac4507b744a1686ec9bff8.MGMpt3uV99Lftv5KkHF7pk}',
client_secret: '${CLIENT_SECRET}',
redirect_uris: ['http://localhost:3000/api/auth/callback'],
response_types: ['code'],
});
}
Substep 2.3: Update Login Page/UI
Modify your existing login component (e.g., app/login/page.tsx) to include the "Sign in with SSO" toggle.
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
export default function LoginPage() {
const [isSSO, setIsSSO] = useState(false);
const [email, setEmail] = useState('');
const router = useRouter();
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
if (isSSO) {
// Trigger SSO login by redirecting to our API route
window.location.href = `/api/auth/login?login_hint=${encodeURIComponent(email)}`;
} else {
// Existing password login logic here
console.log('Processing traditional login...');
}
};
return (
<div className="login-container">
<h1>Sign In</h1>
<form onSubmit={handleLogin} className="flex flex-col gap-4">
<div>
<label>Email</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
className="border p-2 rounded"
/>
</div>
{!isSSO && (
<div>
<label>Password</label>
<input type="password" required className="border p-2 rounded" />
</div>
)}
<button type="submit" className="bg-blue-600 text-white p-2 rounded">
{isSSO ? 'Continue with SSO' : 'Sign In'}
</button>
<button
type="button"
onClick={() => setIsSSO(!isSSO)}
className="text-sm text-blue-500 underline"
>
{isSSO ? 'Back to Password Login' : 'Sign in with SSO'}
</button>
</form>
</div>
);
}
Substep 2.4: Update Backend Logic
Create the necessary API routes to handle the OIDC flow.
1. Login Initiation Route (app/api/auth/login/route.ts):
import { NextResponse } from 'next/server';
import { getClient } from '@/lib/oidc';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const login_hint = searchParams.get('login_hint');
const client = await getClient();
// Generate a random state for CSRF protection
const state = Math.random().toString(36).substring(2, 15);
const authorizationUrl = client.authorizationUrl({
scope: 'openid profile email',
login_hint: login_hint || undefined,
state,
});
const response = NextResponse.redirect(authorizationUrl);
// Store state in a cookie to verify in the callback
response.cookies.set('oidc_state', state, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 3600
});
return response;
}
2. Callback Handler Route (app/api/auth/callback/route.ts):
import { NextRequest, NextResponse } from 'next/server';
import { getClient } from '@/lib/oidc';
export async function GET(request: NextRequest) {
const client = await getClient();
const params = client.callbackParams(request.url);
try {
const storedState = request.cookies.get('oidc_state')?.value;
const tokenSet = await client.callback('http://localhost:3000/api/auth/callback', params, { state: storedState });
const userinfo = await client.userinfo(tokenSet.access_token!);
// TODO: Create a session for the user based on `userinfo`
console.log('Authenticated User:', userinfo);
// Redirect to the dashboard or intended page
return NextResponse.redirect(new URL('/dashboard', request.url));
} catch (error) {
console.error('OIDC Callback Error:', error);
return NextResponse.redirect(new URL('/login?error=oidc_failed', request.url));
}
}
Step 3: Test the Modified Connection
- Start your application:
npm run dev. - Navigate to your login page (e.g.,
/login). - Verify that the traditional login form (Email + Password) is visible by default.
- Click "Sign in with SSO" and ensure:
- The password field disappears.
- The submit button changes to "Continue with SSO".
- Enter a test email and submit.
- You should be redirected to the SSOJet login page.
- Authenticate with SSOJet.
- You should be redirected back to
/api/auth/callbackand then to/dashboard.
- You should be redirected back to
3. Additional Considerations
- Error Handling: Enhance the callback route to handle specific OIDC errors gracefully.
- Styling: Adapt the example CSS classes to match your application's design system.
- Security: Integrate the user information returned in the callback with your existing session management system (e.g., setting cookies or JWTs).
- Environment Variables: Store sensitive values like
CLIENT_SECRETandISSUER_URLin.env.localand access them viaprocess.env.
4. Support
- Contact SSOJet support: Reach out if you have integration questions.
- Check application logs: Use server-side logging to debug OIDC flow issues.
- Library Documentation: Refer to the openid-client documentation for advanced configuration.