Auth Service Integration Guide
This page exposes the public integration surface for the central auth service. It is intended for external applications that want to use the service seamlessly as an OAuth2 / OpenID Connect (OIDC) provider.
What this service exposes
The auth service acts as an OAuth2/OpenID Connect provider for registered client applications.
Public Endpoints
{AUTH_BASE_URL}/oidc/.well-known/openid-configuration
{AUTH_BASE_URL}/oauth/.well-known/openid-configuration
{AUTH_BASE_URL}/oidc/authorize
{AUTH_BASE_URL}/oidc/token
{AUTH_BASE_URL}/oidc/userinfo
Note: Replace {AUTH_BASE_URL} with the deployed auth service production instance URL, for example: https://auth.example.com.
Supported Auth Flow
This service mandates and supports the standard OAuth2 Authorization Code Flow with PKCE (Proof Key for Code Exchange).
Authorization Request
Token Exchange Requirements
Note: The token endpoint also accepts Basic auth credentials via the Authorization header.
Redirect URI Validation rules
-
The absolute payload
redirect_uristring must explicitly match a registered callback path for the client app. -
localhostconfigurations are natively permitted to accelerate local machine testing workflows.
Vanilla JavaScript Integration
Trigger safe window routing natively to initialize client hooks, then safely offload downstream validation exchange back onto a trusted server layer.
Client-side: Start Login Flow
const authBaseUrl = 'https://auth.example.com';
const clientId = 'YOUR_CLIENT_ID';
const redirectUri = 'https://app.example.com/auth/callback';
const state = crypto.randomUUID();
const codeVerifier = crypto.randomUUID();
window.localStorage.setItem('pkce_code_verifier', codeVerifier);
async function sha256(value) {
const bytes = new TextEncoder().encode(value);
const digest = await crypto.subtle.digest('SHA-256', bytes);
return btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
async function login() {
const codeChallenge = await sha256(codeVerifier);
const authUrl = new URL(`${authBaseUrl}/oidc/authorize`);
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', clientId);
authUrl.searchParams.set('redirect_uri', redirectUri);
authUrl.searchParams.set('scope', 'openid email profile');
authUrl.searchParams.set('state', state);
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');
window.location.href = authUrl.toString();
}
Backend: Secure Code Exchange Handler
import express from 'express';
import fetch from 'node-fetch';
const app = express();
app.use(express.json());
app.post('/auth/token', async (req, res) => {
const { code, codeVerifier, redirectUri } = req.body;
const tokenResponse = await fetch('https://auth.example.com/oidc/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
code,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code_verifier: codeVerifier,
redirect_uri: redirectUri,
}),
});
const tokens = await tokenResponse.json();
return res.json(tokens);
});
app.listen(3000);
Client-side: Post-Callback UI Router Processing
const url = new URL(window.location.href);
const code = url.searchParams.get('code');
const state = url.searchParams.get('state');
const codeVerifier = window.localStorage.getItem('pkce_code_verifier');
fetch('/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
code,
codeVerifier,
redirectUri: 'https://app.example.com/auth/callback',
}),
})
.then((res) => res.json())
.then((tokens) => {
console.log('Tokens Captured Successfully', tokens);
});
Security Constraint
Never embed or compromise your production client_secret configuration within public web-browser scripts. Always encapsulate authorization code completions entirely at server-side logic points.
Next.js + NextAuth Architecture
Integrate NextAuth natively into modern applications by referencing discovery layouts dynamically.
Environment Configuration Matrix
NEXTAUTH_URL=https://app.example.com
AUTH_URL=https://auth.example.com
PRABISHA_CLIENT_ID=your-client-id
PRABISHA_CLIENT_SECRET=your-client-secret
Dynamic Provider Route Setup
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';
export default NextAuth({
providers: [
Providers.OpenIDConnect({
id: 'prabisha',
name: 'Prabisha Auth',
issuer: process.env.AUTH_URL,
clientId: process.env.PRABISHA_CLIENT_ID,
clientSecret: process.env.PRABISHA_CLIENT_SECRET,
wellKnown: `${process.env.AUTH_URL}/oidc/.well-known/openid-configuration`,
authorization: {
params: {
scope: 'openid email profile',
response_type: 'code',
},
},
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
};
},
}),
],
session: {
strategy: 'jwt',
},
});
NextAuth Parameter Reminders:
- • issuer: Standardizes internal base URL configuration mappings.
- • wellKnown: Leverages discovery profiles gracefully via target endpoints.
- • clientSecret: Encapsulated dynamically within localized server bounds.
NestJS Controller Engine Setup
Explicitly control redirection boundaries and state parameters within server systems using `openid-client` libraries.
import { Controller, Get, Query } from '@nestjs/common';
import { Issuer, generators } from 'openid-client';
@Controller('auth')
export class ExternalAuthController {
private client: any;
private codeVerifier: string;
constructor() {
this.initializeClient();
}
private async initializeClient() {
const issuer = await Issuer.discover('https://auth.example.com/oidc/.well-known/openid-configuration');
this.client = new issuer.Client({
client_id: process.env.PRABISHA_CLIENT_ID,
client_secret: process.env.PRABISHA_CLIENT_SECRET,
redirect_uris: [process.env.PRABISHA_REDIRECT_URI],
response_types: ['code'],
});
}
@Get('login')
async login() {
this.codeVerifier = generators.codeVerifier();
const codeChallenge = generators.codeChallenge(this.codeVerifier);
const url = this.client.authorizationUrl({
scope: 'openid email profile',
response_type: 'code',
code_challenge: codeChallenge,
code_challenge_method: 'S256',
state: generators.state(),
});
return { url };
}
@Get('callback')
async callback(@Query('code') code: string, @Query('state') state: string) {
const tokenSet = await this.client.callback(process.env.PRABISHA_REDIRECT_URI, { code, state }, { code_verifier: this.codeVerifier });
return tokenSet;
}
}
- 01. Server Bounds Maintain
code_verifierin memory until full callback execution returns. - 02. Direct Exchange Complete execution workflows targeting the structural
/oidc/tokenpaths directly. - 03. Payload Access Safely apply the generated tokens to build valid application sessions.
Recommended Integration Steps
Register Application
Obtain secure credentials (client_id and client_secret) from management portal.
Whitelist Callbacks
Configure permitted application destination redirect_uri pathways securely.
Validate Discovery
Verify metadata properties against standard provider discovery paths.
Initialize Redirects
Route workflows directly to /oidc/authorize alongside PKCE and state strings.
Backend Resolution
Capture dynamic parameter callbacks to clear final validation steps server-side.
Secure Token Sessions
Store returned security parameters inside high-security session targets.
Core Security Hardening Rules
-
No Secret Check-ins Never check your secret configuration parameters directly into standard Git source control systems.
-
Isolate Public Client Scripts Prevent secret parameters from emitting into customer-accessible web browser scripts.
-
Enforce Cross-Site Tokens Always require un-guessable state keys to protect application connections against injection or CSRF exploits.
-
Enforce Complete PKCE Proofs Require robust PKCE generation strategies to verify transactions originating from native browser setups.