Plannorium ID Integration Guide (NextAuth/Auth.js)
This guide documents the standardized integration of Plannorium ID into application ecosystems, based on the reference implementation in Curenium.
1. Environment Configuration
Add the following variables to your .env or .env.local file:
# Plannorium ID Configuration
PLANNORIUM_CLIENT_ID=your_client_id_here
PLANNORIUM_CLIENT_SECRET=your_client_secret_here
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your_nextauth_secret_here2. NextAuth Configuration (lib/authOptions.ts)
Plannorium ID uses a custom OAuth 2.0 / OpenID Connect (OIDC) implementation. Configure the provider as follows:
import { NextAuthOptions } from "next-auth";
export const authOptions: NextAuthOptions = {
providers: [
{
id: "plannorium",
name: "Plannorium ID",
type: "oauth",
issuer: "id.plannorium.com",
authorization: {
url: "https://id.plannorium.com/oauth/authorize",
params: { scope: "openid email profile" },
},
token: "https://id.plannorium.com/api/oauth/token",
userinfo: "https://id.plannorium.com/api/oauth/userinfo",
checks: ["pkce", "state"], // Mandatory for Plannorium Identity
idToken: true,
client: {
id_token_signed_response_alg: "HS256", // Specific requirement
},
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,
},
// ... other providers
],
// ... other settings
};Key Technical Details:
- Checks: Both
pkceandstateare required to prevent authorization code injection and CSRF attacks. - Algorithm: The Identity provider signs ID tokens using
HS256. Ensure the client object specifies this to prevent validation errors.
3. Handling User Flows (callbacks)
To ensure a seamless user experience, implement the following logic in your signIn callback to handle existing users and automatic signups.
Account Linking & Auto-Signup
When a user attempts to sign in via Plannorium ID, verify if an account already exists with that email.
callbacks: {
async signIn({ user, account, profile }) {
if (account?.provider === "plannorium") {
const dbUser = await User.findOne({ email: user.email.toLowerCase() });
if (dbUser) {
// User exists - check if Plannorium is already linked
const isLinked = dbUser.providers?.some(p => p.name === "plannorium");
if (!isLinked) {
// Redirect to a dedicated linking page for explicit opt-in
return `/auth/link-account?email=${encodeURIComponent(user.email)}&provider=plannorium&providerId=${account.providerAccountId}`;
}
return true;
}
// New User - Trigger Automatic Signup
// Create user and assign a default workspace/organization context
const newUser = await User.create({
email: user.email,
fullName: user.name,
// ... assign default role and organization
});
return true;
}
return true;
},
async redirect({ url, baseUrl }) {
// Standard secure redirect logic
if (url.startsWith("/")) return `${baseUrl}${url}`;
else if (new URL(url).origin === baseUrl) return url;
return baseUrl;
}
}4. Frontend: Account Linking Page
Create a page at /auth/link-account/page.tsx to handle the transition for existing users. This page should:
- Explain the benefits of linking (e.g., faster sign-in).
- Display the email and Plannorium Profile thumbnail.
- Provide a "Link Account" button that calls a backend API (
/api/auth/link-provider). - Trigger a re-authentication via
signIn('plannorium')upon success.
5. Backend: Linking API
The linking API should securely pair the Plannorium sub ID with the local user record.
export async function POST(req: Request) {
const { email, provider, providerId } = await req.json();
const user = await User.findOne({ email: email.toLowerCase() });
if (user) {
if (!user.providers) user.providers = [];
user.providers.push({
name: provider,
providerId: providerId,
linkedAt: new Date()
});
await user.save();
return NextResponse.json({ message: "Linked successfully" });
}
}6. Common Pitfalls to Avoid
- Issuer Mismatch: Ensure the issuer in NextAuth config exactly matches the
issclaim in the Plannorium ID token. - Callback URL: The redirect URI on the Plannorium ID Console must be
https://YOUR_DOMAIN/api/auth/callback/plannorium. - Scopes: Minimum required scopes are
openid email profile.