Getting Started: New Calimatic App
Quick start guide for integrating a new Calimatic application with the Calimatic Auth platform.
This guide is for Category 1 apps: greenfield Calimatic products with few or no users that need to integrate with centralized authentication from day one.
Prerequisites
- Access to the Calimatic Auth admin dashboard, or credentials for the dynamic registration endpoint
- Your application's callback URL(s) (production + localhost for development)
- Node.js 18+ (for Next.js/React examples)
- Familiarity with OAuth 2.0 / OpenID Connect concepts
1. Register Your App Client
You need an OAuth client registration before your app can authenticate users. There are two ways to get one.
Option A: Request from Calimatic Admin
Ask a Calimatic Auth administrator to create your app client via the admin dashboard at https://auth.calimatic.com/admin/app-clients. They will provide you with:
client_id(prefixedcca_)client_secret(prefixedccas_, shown only once)
Option B: Dynamic Registration
Call the registration endpoint directly:
curl -X POST https://auth.calimatic.com/api/v1/oidc/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My New App",
"redirect_uris": [
"https://myapp.calimatic.com/auth/callback",
"http://localhost:3001/auth/callback"
],
"grant_types": ["authorization_code", "refresh_token"],
"scope": "openid profile email organization permissions"
}'
Response (201 Created):
{
"client_id": "cca_aBcDeFgHiJkL...",
"client_secret": "ccas_xYzAbCdEfGhI...",
"client_secret_expires_at": 0,
"client_name": "My New App",
"redirect_uris": [
"https://myapp.calimatic.com/auth/callback",
"http://localhost:3001/auth/callback"
],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "client_secret_post",
"scope": "openid profile email organization permissions"
}
Store the client_secret securely. It is returned exactly once and cannot be retrieved again.
Configure Redirect URIs
Redirect URIs are validated with exact string match. Register all environments:
| Environment | Example URI |
|---|---|
| Production | https://myapp.calimatic.com/auth/callback |
| Staging | https://staging-myapp.calimatic.com/auth/callback |
| Development | http://localhost:3001/auth/callback |
Choose Your Scopes
| Scope | Purpose | Recommended For |
|---|---|---|
openid | Required for OIDC | All apps |
profile | Name, avatar | All apps |
email | Email address | All apps |
organization | Org ID, memberships, user type | Calimatic apps that need org context |
permissions | Platform permissions, roles | Apps that enforce platform-level permissions |
For most Calimatic apps, use: openid profile email organization
Apps that need permission-gated features should add permissions.
2. Configure OIDC with Next.js
The recommended integration uses NextAuth.js v5 with the Calimatic OIDC provider.
Install NextAuth
npm install next-auth
Create src/auth.ts
import NextAuth from "next-auth";
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
{
id: "calimatic",
name: "Calimatic",
type: "oidc",
issuer: "https://auth.calimatic.com",
clientId: process.env.CALIMATIC_CLIENT_ID!,
clientSecret: process.env.CALIMATIC_CLIENT_SECRET!,
authorization: {
params: {
scope: "openid profile email organization",
code_challenge_method: "S256",
},
},
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture,
};
},
},
],
callbacks: {
async jwt({ token, account, profile }) {
if (account) {
token.accessToken = account.access_token;
token.refreshToken = account.refresh_token;
token.expiresAt = account.expires_at;
token.idToken = account.id_token;
}
if (profile) {
token.organizationId = profile.organization_id;
token.organizationMemberships = profile.organization_memberships;
token.userType = profile.user_type;
}
return token;
},
async session({ session, token }) {
session.accessToken = token.accessToken as string;
session.user.organizationId = token.organizationId as string;
session.user.organizationMemberships = token.organizationMemberships;
session.user.userType = token.userType as string;
return session;
},
},
});
Create the Route Handler
src/app/api/auth/[...nextauth]/route.ts:
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
Set Environment Variables
.env.local:
CALIMATIC_CLIENT_ID=cca_your_client_id
CALIMATIC_CLIENT_SECRET=ccas_your_client_secret
NEXTAUTH_URL=http://localhost:3001
NEXTAUTH_SECRET=generate-a-random-secret-here
Use in Server Components
import { auth } from "@/auth";
import { redirect } from "next/navigation";
export default async function Dashboard() {
const session = await auth();
if (!session) {
redirect("/api/auth/signin");
}
return (
<div>
<h1>Welcome, {session.user.name}</h1>
<p>Organization: {session.user.organizationId}</p>
</div>
);
}
Use in Client Components
"use client";
import { useSession, signIn, signOut } from "next-auth/react";
export function AuthButton() {
const { data: session, status } = useSession();
if (status === "loading") return <div>Loading...</div>;
if (session) {
return (
<div>
<p>Signed in as {session.user.email}</p>
<button onClick={() => signOut()}>Sign out</button>
</div>
);
}
return (
<button onClick={() => signIn("calimatic")}>
Sign in with Calimatic
</button>
);
}
For the full integration guide including manual OAuth flows, React SPA integration, and backend/server-side examples, see the Integration Guide.
3. Create Your Organization
Before provisioning users, your app needs to create its organization on the auth platform. Organizations originate at the app level -- when a customer subscribes, your app registers their org.
Create Organization via API
curl -X POST https://auth.calimatic.com/api/v1/organizations \
-H "Content-Type: application/json" \
-H "x-client-id: cca_your_client_id" \
-H "x-client-secret: ccas_your_client_secret" \
-d '{
"name": "Acme Corp",
"slug": "acme-corp",
"type": "customer"
}'
const response = await fetch("https://auth.calimatic.com/api/v1/organizations", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-client-id": process.env.CALIMATIC_CLIENT_ID!,
"x-client-secret": process.env.CALIMATIC_CLIENT_SECRET!,
},
body: JSON.stringify({
name: "Acme Corp",
slug: "acme-corp",
type: "customer",
}),
});
const { data: org } = await response.json();
// org.id is the organization UUID to use when provisioning users
The endpoint is idempotent -- if the slug already exists, it returns the existing organization (409 status) with its ID. Your app is automatically enabled for any organization it creates.
Required Permission
Your app client needs the org:manage permission. This is separate from org:users:manage (needed for user provisioning).
4. Provision Users with the Provisioning API
New apps typically need to create or invite users into their organization. Use the Provisioning API to do this programmatically.
Single User Provisioning
curl -X POST https://auth.calimatic.com/api/v1/users/provision \
-H "Content-Type: application/json" \
-H "x-client-id: cca_your_client_id" \
-H "x-client-secret: ccas_your_client_secret" \
-d '{
"email": "jane@school.edu",
"firstName": "Jane",
"lastName": "Smith",
"organizationId": "org-uuid-here",
"role": "member",
"sendInviteEmail": true
}'
const response = await fetch("https://auth.calimatic.com/api/v1/users/provision", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-client-id": process.env.CALIMATIC_CLIENT_ID!,
"x-client-secret": process.env.CALIMATIC_CLIENT_SECRET!,
},
body: JSON.stringify({
email: "jane@school.edu",
firstName: "Jane",
lastName: "Smith",
organizationId: "org-uuid-here",
role: "member",
sendInviteEmail: true,
}),
});
const { data } = await response.json();
// data.userId, data.keycloakUserId, data.email, data.isNewUser
Bulk Provisioning
For creating multiple users at once (up to 500 per batch):
curl -X POST https://auth.calimatic.com/api/v1/users/provision/bulk \
-H "Content-Type: application/json" \
-H "x-client-id: cca_your_client_id" \
-H "x-client-secret: ccas_your_client_secret" \
-d '{
"users": [
{ "email": "user1@school.edu", "firstName": "User", "lastName": "One" },
{ "email": "user2@school.edu", "firstName": "User", "lastName": "Two" }
],
"defaultOrganizationId": "org-uuid-here",
"sendInviteEmails": true
}'
For full API reference, see the User Management API.
5. Auto-Licensing
When your app client invites a user via the Provisioning API, the platform automatically assigns a license for your application. No extra configuration is needed.
How It Works
The platform follows a three-layer licensing model:
| Layer | What | How |
|---|---|---|
| App Registration | Register your app as an OAuth client | Admin creates via dashboard, or dynamic registration |
| Org Enablement | Enable the app for a specific organization | Admin creates organization_app_access record with isEnabled: true |
| User Assignment | Grant a user access to the app | user_app_licenses record created automatically when user is provisioned by the app |
Auto-Assignment Rules
-
App client calls the provisioning API: The calling app's identity (
requestor.application) is automatically included in the license list. The user gets a license for the calling app. -
Explicit
applicationsarray: If you pass anapplicationsarray, only those apps (that are enabled on the organization) are assigned. -
No apps specified and no app client context: The user receives licenses for all apps enabled on the organization.
Verify a User's License
After OIDC login, call the resolve endpoint to check if the user has a license for your app:
curl "https://auth.calimatic.com/api/v1/users/resolve?email=jane@school.edu" \
-H "x-client-id: cca_your_client_id" \
-H "x-client-secret: ccas_your_client_secret"
The response includes a hasLicense boolean when called with app client credentials, plus the full list of all the user's licenses.
6. Integration Checklist
Use this checklist to verify your OIDC integration is complete:
- Client registration —
client_idandclient_secretobtained and stored securely - Redirect URIs — All environments registered (production, staging, localhost)
- Login Page URL — Set
loginUrlon your app client so the platform can redirect users to your login page (e.g., after email verification) - Organization created — Your app's organization exists on the auth platform (via
POST /api/v1/organizations) - Scopes — Selected appropriate scopes for your app's needs
- OIDC config — NextAuth (or manual OIDC) configured and connecting to
https://auth.calimatic.com - Login flow — Users can log in and are redirected back to your app with a valid session
- Organization context — If using
organizationscope, verifyorganizationIdis present in the session - User provisioning — App can create/invite users via the Provisioning API
- Auto-licensing — Provisioned users receive a license for your app
- Token refresh — Access tokens are refreshed before expiry (NextAuth handles this automatically)
- Logout — Sign-out clears the session and redirects to the Calimatic end-session endpoint
- Webhook subscriptions — Subscribe to
user.deleted,user.suspended,user.updated,license.revokedevents to keep your app in sync - User lifecycle sync — When users/orgs are deleted in your app, notify the auth platform via the API
- Error handling —
invalid_token,access_denied, and other OAuth errors are handled gracefully - Test with real users — End-to-end test with at least one user going through login, consent, and accessing your app
For the complete integration checklist covering all integration methods (OIDC, Headless API, SDK), email verification, MFA, security, and more, see the Integration Checklist.
Next Steps
- Integration Guide -- Full OIDC integration reference with examples for Next.js, React SPA, Python, PHP, and more
- User Management API -- Complete API reference for provisioning and managing users
- User Provisioning Guide -- Conceptual guide covering provisioning methods, organization membership, and password handling
- OIDC API Reference -- Full reference for all OIDC endpoints