Kinde
Build with Kinde for authentication and user management. Use this skill when the
You are an auth specialist who integrates Kinde into projects. Kinde is a modern
auth platform that combines authentication, authorization (roles/permissions),
feature flags, and organization multi-tenancy in a single service with a generous
free tier.
## Key Points
- Use `getKindeServerSession()` in Server Components — no client-side token exposure
- Use middleware for blanket route protection
- Use permissions over roles for fine-grained access control
- Use feature flags for gradual rollouts — they're built into the auth session
- Use organizations for B2B multi-tenancy
- Sync users to your database via webhooks for app-specific data
- Checking auth in every component instead of using middleware
- Not handling the `isLoading` state in client components
- Using roles for fine-grained checks — use permissions instead
- Not setting up webhooks — your database won't know about Kinde users
- Hardcoding org codes — fetch them dynamically from the session
- Using client-side auth checks for security — always verify server-side
## Quick Example
```bash
npm install @kinde-oss/kinde-auth-nextjs
```
```typescript
// app/api/auth/[kindeAuth]/route.ts
import { handleAuth } from '@kinde-oss/kinde-auth-nextjs/server';
export const GET = handleAuth();
```skilldb get auth-services-skills/KindeFull skill: 262 linesKinde Authentication Integration
You are an auth specialist who integrates Kinde into projects. Kinde is a modern auth platform that combines authentication, authorization (roles/permissions), feature flags, and organization multi-tenancy in a single service with a generous free tier.
Core Philosophy
Auth + feature flags + billing in one
Kinde isn't just authentication — it includes role-based access control, feature flags, and organization management. Instead of stitching together separate services, Kinde provides the full user management stack.
Developer-first pricing
Kinde's free tier supports up to 10,500 MAU. No per-user pricing surprises. This makes it viable for side projects and startups without auth costs eating into early revenue.
Framework-native SDKs
Kinde provides framework-specific SDKs (Next.js, Remix, SvelteKit, etc.) that follow each framework's conventions. The Next.js SDK uses App Router patterns, middleware, and Server Components natively.
Setup
Install (Next.js)
npm install @kinde-oss/kinde-auth-nextjs
Environment variables
KINDE_CLIENT_ID=your-client-id
KINDE_CLIENT_SECRET=your-client-secret
KINDE_ISSUER_URL=https://your-app.kinde.com
KINDE_SITE_URL=http://localhost:3000
KINDE_POST_LOGOUT_REDIRECT_URL=http://localhost:3000
KINDE_POST_LOGIN_REDIRECT_URL=http://localhost:3000/dashboard
Route handler
// app/api/auth/[kindeAuth]/route.ts
import { handleAuth } from '@kinde-oss/kinde-auth-nextjs/server';
export const GET = handleAuth();
Key Techniques
Authentication links
import { LoginLink, RegisterLink, LogoutLink } from '@kinde-oss/kinde-auth-nextjs/components';
function AuthNav() {
return (
<nav>
<LoginLink>Sign in</LoginLink>
<RegisterLink>Sign up</RegisterLink>
<LogoutLink>Log out</LogoutLink>
</nav>
);
}
Server-side auth
import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server';
export default async function DashboardPage() {
const { getUser, isAuthenticated } = getKindeServerSession();
if (!(await isAuthenticated())) {
redirect('/api/auth/login');
}
const user = await getUser();
return <div>Welcome {user?.given_name}</div>;
}
// API route
export async function GET() {
const { getUser, isAuthenticated } = getKindeServerSession();
if (!(await isAuthenticated())) {
return new Response('Unauthorized', { status: 401 });
}
const user = await getUser();
return Response.json({ user });
}
Client-side auth
'use client';
import { useKindeBrowserClient } from '@kinde-oss/kinde-auth-nextjs';
function Profile() {
const { user, isAuthenticated, isLoading } = useKindeBrowserClient();
if (isLoading) return <div>Loading...</div>;
if (!isAuthenticated) return <div>Not signed in</div>;
return (
<div>
<p>{user?.email}</p>
<p>{user?.given_name} {user?.family_name}</p>
</div>
);
}
Middleware protection
// middleware.ts
import { withAuth } from '@kinde-oss/kinde-auth-nextjs/middleware';
export default withAuth;
export const config = {
matcher: ['/dashboard/:path*', '/api/protected/:path*'],
};
Roles and permissions
import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server';
export default async function AdminPage() {
const { getPermission, getPermissions } = getKindeServerSession();
const canManageUsers = await getPermission('manage:users');
if (!canManageUsers?.isGranted) {
redirect('/dashboard');
}
const allPermissions = await getPermissions();
// allPermissions.permissions = ['manage:users', 'edit:posts', ...]
return <div>Admin Panel</div>;
}
Organizations
import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server';
export default async function OrgPage() {
const { getOrganization, getUserOrganizations } = getKindeServerSession();
const org = await getOrganization();
// org.orgCode = 'org_abc123'
const allOrgs = await getUserOrganizations();
// allOrgs.orgCodes = ['org_abc123', 'org_def456']
return <div>Current org: {org?.orgCode}</div>;
}
// Login to specific org
import { LoginLink } from '@kinde-oss/kinde-auth-nextjs/components';
<LoginLink orgCode="org_abc123">Sign in to Acme</LoginLink>
Feature flags
import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server';
export default async function PricingPage() {
const { getFlag } = getKindeServerSession();
const newPricing = await getFlag('new-pricing-page', false, 'b');
if (newPricing?.value) {
return <NewPricingPage />;
}
return <CurrentPricingPage />;
}
// Client-side
'use client';
import { useKindeBrowserClient } from '@kinde-oss/kinde-auth-nextjs';
function Feature() {
const { getFlag } = useKindeBrowserClient();
const betaFeature = getFlag('beta-editor', false, 'b');
if (!betaFeature?.value) return null;
return <BetaEditor />;
}
Webhooks
// app/api/webhooks/kinde/route.ts
import { NextRequest } from 'next/server';
import jwksClient from 'jwks-rsa';
import jwt from 'jsonwebtoken';
const client = jwksClient({
jwksUri: `${process.env.KINDE_ISSUER_URL}/.well-known/jwks.json`,
});
export async function POST(req: NextRequest) {
const token = await req.text();
const { header } = jwt.decode(token, { complete: true })!;
const key = await client.getSigningKey(header.kid);
const event = jwt.verify(token, key.getPublicKey()) as any;
switch (event.type) {
case 'user.created':
await db.insert(users).values({
id: event.data.user.id,
email: event.data.user.email,
name: `${event.data.user.first_name} ${event.data.user.last_name}`,
});
break;
case 'user.updated':
await db.update(users).set({
email: event.data.user.email,
}).where(eq(users.id, event.data.user.id));
break;
}
return new Response('OK');
}
Best Practices
- Use
getKindeServerSession()in Server Components — no client-side token exposure - Use middleware for blanket route protection
- Use permissions over roles for fine-grained access control
- Use feature flags for gradual rollouts — they're built into the auth session
- Use organizations for B2B multi-tenancy
- Sync users to your database via webhooks for app-specific data
Anti-Patterns
- Checking auth in every component instead of using middleware
- Not handling the
isLoadingstate in client components - Using roles for fine-grained checks — use permissions instead
- Not setting up webhooks — your database won't know about Kinde users
- Hardcoding org codes — fetch them dynamically from the session
- Using client-side auth checks for security — always verify server-side
Install this skill directly: skilldb add auth-services-skills
Related Skills
Auth0
Build with Auth0 for enterprise authentication and identity. Use this skill when
Clerk
Build with Clerk for authentication and user management. Use this skill when the
Cognito
Build with Amazon Cognito for authentication and user management. Use this skill
Descope
Integrate Descope to add secure, no-code/low-code authentication and user management to your applications.
Firebase Auth
Build with Firebase Authentication for user sign-in. Use this skill when the
Hanko
Integrate Hanko for modern, passwordless authentication in your web applications.