01Environment Config
Add these infrastructure variables to the root .env or .env.local file in your application repository:
# Plannorium ID OAuth Credentials
PLANNORIUM_CLIENT_ID=your_client_id_here
PLANNORIUM_CLIENT_SECRET=your_client_secret_here
NEXTAUTH_URL=http://localhost:3001
NEXTAUTH_SECRET=your_nextauth_secret_here02NextAuth Provider
Configure the custom Plannorium Identity Provider in your NextAuth config as follows:
import { NextAuthOptions } from "next-auth";
export const authOptions: NextAuthOptions = {
providers: [
{
id: "plannorium",
name: "Plannorium ID",
type: "oauth",
issuer: "https://identity.plannorium.com",
authorization: {
url: "https://identity.plannorium.com/oauth/authorize",
params: { scope: "openid email profile" },
},
token: "https://identity.plannorium.com/api/oauth/token",
userinfo: "https://identity.plannorium.com/api/oauth/userinfo",
checks: ["pkce", "state"],
idToken: true,
client: {
id_token_signed_response_alg: "HS256",
},
profile: (profile: any) => ({
id: profile.sub || profile.id,
name: profile.name,
email: profile.email,
image: profile.picture || profile.image,
}),
clientId: process.env.PLANNORIUM_CLIENT_ID,
clientSecret: process.env.PLANNORIUM_CLIENT_SECRET,
},
],
};Security Specs
- Checks: Both pkce and state checks are strictly required by the identity backend.
- Algorithm: Tokens are signed using HS256 symmetric keys.
03Handling User Flows
Add callback logic within NextAuth configuration to auto-create users and link social SSO accounts:
callbacks: {
async signIn({ user, account }) {
if (account?.provider === "plannorium") {
const existingUser = await User.findOne({ email: user.email.toLowerCase() });
if (existingUser) {
// Link to existing credential structure
return true;
}
// Automate new user registration/provisioning
return true;
}
return true;
}
}04Installing the SDK
Install the Plannorium Client SDK library in your web applications using your package manager:
# Install via npm
npm install @plannorium/identity-sdk
# Or install via yarn
yarn add @plannorium/identity-sdkThen, import and initialize the client SDK in your application logic:
import { PlannoriumSDK } from "@plannorium/identity-sdk";
const plannorium = new PlannoriumSDK({
clientId: "your_client_id_here"
});05Popup Sign-In SDK
Plannorium supports popup-based authentication so users can log in seamlessly without being redirected away from your website:
import { PlannoriumSDK } from "@plannorium/identity-sdk";
const plannorium = new PlannoriumSDK({
clientId: "your_client_id_here",
});
async function handlePopupSignIn() {
try {
// 1. Trigger the popup sign-in flow
const { code } = await plannorium.signInWithPopup();
// 2. Exchange authorization code for session tokens on your backend
const res = await fetch("/api/auth/callback/plannorium", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ code })
});
if (res.ok) {
window.location.reload(); // Authentication successful
}
} catch (error) {
console.error("Popup authentication failed:", error);
}
}How it works: The SDK opens a secure popup for authentication, and returns the authorization code to your window once completed.
06Local Session Conflicts
CRITICAL DEVELOPER CONFLICT
Because all applications run on localhost (regardless of port) in developer environments, they share cookies. If multiple applications use the default NextAuth cookie name (next-auth.session-token), they will constantly overwrite each other and fail with Invalid Compact JWE errors in client middlewares.
To resolve this, every application must configure a distinct cookie name. Configure your client application like this:
const useSecureCookies = process.env.NEXTAUTH_URL?.startsWith("https://");
export const authOptions: NextAuthOptions = {
// ... providers config ...
cookies: {
sessionToken: {
name: useSecureCookies
? "__Secure-your-app.session-token"
: "your-app.session-token",
options: {
httpOnly: true,
sameSite: "lax",
path: "/",
secure: useSecureCookies
}
}
}
};import { withAuth } from "next-auth/middleware";
const useSecureCookies = process.env.NEXTAUTH_URL?.startsWith("https://");
export default withAuth(
function middleware(req) { /* ... */ },
{
secret: process.env.NEXTAUTH_SECRET,
cookies: {
sessionToken: {
name: useSecureCookies
? `__Secure-your-app.session-token`
: `your-app.session-token`,
},
},
}
);Critical Fail-Safes
Issuer Mismatch
Ensure the issuer URI in your config matches the iss claim in the Plannorium ID token exactly to avoid validation rejection.
Callback URI
The redirect URI registered on the Developer Console must strictly match your application's actual NextAuth callback endpoint structure.