Skip to main content

SSR Quickstart Next.js

Doc type: Tutorial

Goal and expected outcome

Your Next.js app integrates with Yoyo Auth using a standard OAuth2 authorization code flow. You can choose one of two approaches:

  • Cookie-based session (recommended for apps on *.yoyogroup.com subdomains): Validate shared cookies in middleware
  • Token-based session: Use OAuth to exchange tokens and set your own session

This guide covers both approaches.

Prerequisites and setup

  • Your app is hosted on a subdomain of *.yoyogroup.com (for cookie-based approach) or can handle OAuth callbacks (for token-based approach).
  • You can reach the hosted auth portal at https://auth.yoyogroup.com.
  • You know the destination URL in your app that should receive the redirect back from auth.
  • You have a registered OAuth2 client ID (for token-based approach).

Understanding the OAuth flow

Yoyo Auth uses a standard OAuth2 authorization code flow with credentialed OAuth providers (Google). The flow works as follows:

  1. User initiates authentication → redirect to hosted auth portal
  2. User authenticates via credentialed OAuth provider (Google)
  3. Auth portal redirects back to your app with authorization code (or sets cookies)
  4. Your app either validates cookies (cookie-based) or exchanges code for tokens (token-based)

Step 1: Redirect unauthenticated users to hosted auth

Add a middleware guard that checks the shared cookie and redirects to the auth portal when missing.

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

const AUTH_PORTAL = 'https://auth.yoyogroup.com';

export function middleware(request: NextRequest) {
const token = request.cookies.get('yoyo_auth_access_token')?.value;
if (!token) {
const redirectUrl = encodeURIComponent(request.nextUrl.toString());
return NextResponse.redirect(`${AUTH_PORTAL}/?redirectUrl=${redirectUrl}`);
}
return NextResponse.next();
}

Step 2: Validate cookies in middleware

The middleware must validate cookies from the domain. Ensure your middleware validates the cookie before allowing access:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

const AUTH_PORTAL = 'https://auth.yoyogroup.com';

export function middleware(request: NextRequest) {
const token = request.cookies.get('yoyo_auth_access_token')?.value;

// Validate the cookie exists and is from the correct domain
if (!token) {
const redirectUrl = encodeURIComponent(request.nextUrl.toString());
return NextResponse.redirect(`${AUTH_PORTAL}/?redirectUrl=${redirectUrl}`);
}

// Optionally validate token format or JWT claims server-side before allowing access

return NextResponse.next();
}

To fully trust the token contents, validate the JWT server-side using JWKS. For a complete example, see Validate JWTs with JWKS (Next.js).

Step 3: Read cookies server-side

Read the cookies in server components or route handlers and attach the access token to downstream API calls.

const accessToken = cookies().get('yoyo_auth_access_token')?.value;
if (accessToken) {
await fetch('https://api.yoyogroup.com/resource', {
headers: { Authorization: `Bearer ${accessToken}` }
});
}

Step 4: Handle logout

Redirect to the hosted logout endpoint to clear shared cookies.

https://auth.yoyogroup.com/logout?redirectUrl=<encoded return URL>

Approach 2: Token-based session (OAuth token exchange)

If you prefer to manage your own session or your app is not on a *.yoyogroup.com subdomain, use the OAuth flow to exchange tokens.

Step 1: Create an OAuth callback route

Create a route handler at /api/auth/callback (or your preferred path) to handle the OAuth callback:

import { NextRequest, NextResponse } from 'next/server';
import { cookies } from 'next/headers';

export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const code = searchParams.get('code');
const state = searchParams.get('state');

if (!code) {
return NextResponse.json({ error: 'Missing authorization code' }, { status: 400 });
}

// Exchange the authorization code for tokens
const tokenResponse = await fetch('https://auth.yoyogroup.com/api/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: process.env.OAUTH_CLIENT_ID!,
redirect_uri: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`,
code,
code_verifier: getCodeVerifierFromState(state), // Store verifier with state
}),
});

const tokens = await tokenResponse.json();

// Set your own session cookies or store tokens securely
const response = NextResponse.redirect('/');
response.cookies.set('session_token', tokens.access_token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: tokens.expires_in,
});

return response;
}

Step 2: Initiate OAuth flow

Redirect users to the OAuth authorization endpoint:

import { generateCodeVerifier, generateCodeChallenge } from '@/lib/oauth';

export async function initiateAuth() {
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
const state = generateState();

// Store code_verifier with state (e.g., in session or encrypted cookie)
storeCodeVerifier(state, codeVerifier);

const params = new URLSearchParams({
response_type: 'code',
client_id: process.env.OAUTH_CLIENT_ID!,
redirect_uri: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`,
code_challenge: codeChallenge,
code_challenge_method: 'S256',
state,
});

window.location.href = `https://auth.yoyogroup.com/api/oauth/authorize?${params}`;
}

Step 3: Validate your session in middleware

Validate your own session tokens in middleware:

export function middleware(request: NextRequest) {
const sessionToken = request.cookies.get('session_token')?.value;

if (!sessionToken) {
// Redirect to initiate OAuth flow
return NextResponse.redirect('/api/auth/login');
}

// Optionally validate token with auth portal
return NextResponse.next();
}

Verify the result

Cookie-based approach:

  • Visit a protected route: you should be redirected to hosted auth, then back to your app.
  • Confirm the yoyo_auth_access_token cookie exists on .yoyogroup.com.

Token-based approach:

  • Visit a protected route: you should be redirected to OAuth authorization, then back to your callback.
  • Confirm your session token is set and valid.

Example implementations

For complete working examples, see: