Kinde
Kinde is an Auth0-style identity platform: hosted login pages,
OAuth 2.0 / OIDC under the hood, plus organizations (multi-tenancy),
roles + permissions (RBAC), feature flags, billing, and a REST
management API. This skill covers the integration patterns the agent
needs most: Go and TypeScript (Node, Next.js App Router,
plain TS server, browser SPA).
How to pick a path
| You are building... |
Load this reference |
| A Go web service or CLI (auth code or device flow) |
references/go.md |
| A Go service calling the Kinde management API or other M2M |
references/go.md (client credentials section) |
| A TypeScript / Node backend (Express, Hono, vanilla) |
references/typescript.md |
| A Next.js 13+ App Router app |
references/nextjs.md |
| Anything in a language without an SDK, or you need the raw protocol |
references/oauth-without-sdk.md |
| Calling the Kinde management API (any language) |
references/management-api.md |
The references are self-contained — load only what the current task
needs. The summary below is enough to scope work and pick the right
flow.
Concepts in 60 seconds
- Issuer / domain — every Kinde tenant has a subdomain like
your-tenant.kinde.com. That URL is the OIDC issuer; everything
hangs off it (/oauth2/auth, /oauth2/token, /logout,
/.well-known/openid-configuration, /.well-known/jwks,
/oauth2/user_profile).
- Applications — credentials live on an "application" in the
Kinde dashboard. Three kinds you'll see:
- Back-end web (confidential, has
client_secret) — auth code
flow with a server.
- Front-end / SPA / mobile (public, no secret) — auth code +
PKCE.
- Machine-to-machine (M2M) — client credentials flow, no user.
- Grants Kinde supports — authorization code (with optional
PKCE), authorization code + PKCE for SPAs, device authorization
for CLIs and TVs, client credentials for M2M, refresh token.
Implicit flow is not supported.
- Tokens — three of them, all JWTs:
id_token — user identity (sub, email, name). Validate, don't
send to APIs.
access_token — what your APIs receive in Authorization: Bearer …. Validate signature via JWKS, plus iss, aud, exp.
refresh_token — only issued when the offline scope is
requested. Store httpOnly and server-side.
- Scopes —
openid profile email offline is the typical set.
Use offline (not offline_access).
- Organizations — Kinde's multi-tenancy primitive. Identified
by
org_code like org_1234. A user can belong to many; pass
org_code=… on the authorize URL to log them into a specific one.
- RBAC — define permissions (e.g.
create:todos) and roles in
the dashboard, assign to users per-org. Permissions land on the
access token as the permissions claim and a roles claim.
- Feature flags — boolean / string / integer / JSON, evaluated
business → environment → org → user. Read via SDK helpers or the
feature_flags claim on the access token.
Required configuration
Whatever the language, you need:
| Setting |
Where to find it |
Issuer URL (https://<tenant>.kinde.com) |
Settings → Applications → your app |
client_id |
same |
client_secret |
same (back-end / M2M only — never ship to a browser) |
| Allowed callback URL(s) |
Settings → Applications → your app → View details. Must match exactly. |
| Allowed logout redirect URL(s) |
same |
| Audience (optional) |
Set to your API's identifier when you want access tokens scoped to it |
Hardcoding any of these is a smell — load from env (KINDE_DOMAIN,
KINDE_CLIENT_ID, KINDE_CLIENT_SECRET, KINDE_REDIRECT_URL,
KINDE_LOGOUT_REDIRECT_URL are the names the official SDKs expect).
Go — the short version
The official Go SDK lives at github.com/kinde-oss/kinde-go
(requires Go 1.24+) and ships three packages:
oauth2/authorization_code — browser auth code flow and
device authorization flow (CLIs).
oauth2/client_credentials — M2M.
jwt — parse and validate tokens from headers, strings, sessions,
or OAuth2 tokens, with JWKS-based signature verification.
Minimal auth code setup:
import (
"github.com/kinde-oss/kinde-go/oauth2/authorization_code"
"github.com/kinde-oss/kinde-go/jwt"
)
flow, err := authorization_code.NewAuthorizationCodeFlow(
issuerURL, clientID, clientSecret, callbackURL,
authorization_code.WithSessionHooks(sessionStore),
authorization_code.WithOffline(),
authorization_code.WithAudience(apiAudience),
authorization_code.WithTokenValidation(
true,
jwt.WillValidateAlgorithm(),
jwt.WillValidateAudience(apiAudience),
),
)
Full reference in references/go.md: PKCE option, prompt option,
device flow, M2M, JWT validation helpers, middleware patterns
(net/http and Gin).
TypeScript — the short version
Pick the package that matches the runtime:
| Stack |
Package |
| Next.js 13+ App Router |
@kinde-oss/kinde-auth-nextjs |
| Express / Hono / vanilla Node |
@kinde-oss/kinde-typescript-sdk |
| React SPA |
@kinde-oss/kinde-auth-react |
| Browser-only JS |
@kinde-oss/kinde-auth-pkce-js |
| Management API client |
@kinde/management-api-js |
Vanilla TS server (Express-style):
import { createKindeServerClient, GrantType }
from "@kinde-oss/kinde-typescript-sdk";
const kinde = createKindeServerClient(GrantType.AUTHORIZATION_CODE, {
authDomain: process.env.KINDE_DOMAIN!,
clientId: process.env.KINDE_CLIENT_ID!,
clientSecret: process.env.KINDE_CLIENT_SECRET!,
redirectURL: process.env.KINDE_REDIRECT_URL!,
logoutRedirectURL: process.env.KINDE_LOGOUT_REDIRECT_URL!,
});
Then expose /login, /register, /callback, /logout handlers,
each operating on a per-request SessionManager. Full code,
session-manager interface, and helper APIs (getUserProfile,
getPermission, getBooleanFlag, createOrg, …) in
references/typescript.md. Next.js specifics — route handler,
proxy middleware, server vs. client helpers, <LoginLink> /
<LogoutLink> components — are in references/nextjs.md.
When in doubt: use the raw protocol
Kinde is standards-compliant OAuth 2.0 / OIDC. If a language has no
SDK, or a use case doesn't fit one, fall back to the protocol:
- Authorize:
GET https://<tenant>.kinde.com/oauth2/auth?…
- Token:
POST https://<tenant>.kinde.com/oauth2/token
- User profile:
GET /oauth2/user_profile
(Bearer access token)
- JWKS:
GET /.well-known/jwks
- Logout:
GET /logout?redirect=<url>
- Discovery:
GET /.well-known/openid-configuration
Endpoints, parameter tables, PKCE recipe, and security checklist in
references/oauth-without-sdk.md.
Pitfalls the agent should call out
- Scope is
offline, not offline_access. Kinde explicitly
does not support offline_access. If a refresh token is missing,
that's the first thing to check.
- Callback URLs must match exactly. Trailing slash, scheme,
port — all part of the match. Errors usually surface as
invalid_request on the authorize endpoint.
client_secret is server-only. SPAs and mobile use PKCE.
If a user pastes a SPA snippet that includes a secret, flag it.
- Validate JWTs, don't just decode them. Verify signature via
JWKS, plus
iss, aud, exp. Both Go (jwt.WillValidateWith…)
and TS SDKs do this automatically when configured; raw-protocol
integrations must do it explicitly.
- Org context comes from a claim, not the URL. After login,
read
org_code off the access token; trusting a query string is
the standard tenant-mix-up bug.
- Implicit flow is not supported. Don't try to wire up
response_type=token.
- Pages Router vs App Router in Next.js use different SDK
surface area. The App Router patterns in
references/nextjs.md
do not transfer one-for-one to the Pages Router SDK.
Reference guides
references/go.md — authorization code, device, client
credentials, JWT validation, middleware. Full APIs.
references/typescript.md — server SDK, session manager,
organizations, flags, permissions, refresh.
references/nextjs.md — App Router integration: route handler,
proxy/middleware, server + client helpers, components.
references/oauth-without-sdk.md — endpoints, parameters,
PKCE, refresh, logout, security checklist.
references/management-api.md — calling the management API
(users, orgs, roles, permissions, flags) from any language.
MCP
Use Context7 MCP (resolve-library-id then query-docs) to pull
the freshest official docs for kinde-typescript-sdk,
kinde-auth-nextjs, or kinde-go when version-specific behaviour
matters.
1---2name: kinde3description: Integrate the Kinde auth platform (single sign-on, OAuth 2.0 / OIDC, organizations, RBAC, feature flags, M2M, management API) into Go and TypeScript applications. ALWAYS use this skill when the user mentions Kinde, docs.kinde.com, a kinde.com subdomain, the @kinde-oss or @kinde packages, kinde-typescript-sdk, kinde-auth-nextjs, kinde-oss/kinde-go, or asks to wire up login/logout/callback, validate Kinde JWTs, call the Kinde management API, gate features on Kinde flags, or build machine-to-machine auth against Kinde. Covers the Authorization Code (+ PKCE) flow, Client Credentials (M2M) flow, Device flow, token refresh, JWKS validation, organizations and multi-tenancy, roles and permissions, and feature flags. Go and TypeScript are first-class; the OAuth-without-an-SDK guidance also applies to any language that speaks HTTP and JWT.4---56# Kinde78Kinde is an Auth0-style identity platform: hosted login pages,9OAuth 2.0 / OIDC under the hood, plus organizations (multi-tenancy),10roles + permissions (RBAC), feature flags, billing, and a REST11management API. This skill covers the integration patterns the agent12needs most: **Go** and **TypeScript** (Node, Next.js App Router,13plain TS server, browser SPA).1415## How to pick a path1617| You are building... | Load this reference |18|---|---|19| A Go web service or CLI (auth code or device flow) | `references/go.md` |20| A Go service calling the Kinde management API or other M2M | `references/go.md` (client credentials section) |21| A TypeScript / Node backend (Express, Hono, vanilla) | `references/typescript.md` |22| A Next.js 13+ App Router app | `references/nextjs.md` |23| Anything in a language without an SDK, or you need the raw protocol | `references/oauth-without-sdk.md` |24| Calling the Kinde management API (any language) | `references/management-api.md` |2526The references are self-contained — load only what the current task27needs. The summary below is enough to scope work and pick the right28flow.2930## Concepts in 60 seconds3132- **Issuer / domain** — every Kinde tenant has a subdomain like33 `your-tenant.kinde.com`. That URL is the OIDC issuer; everything34 hangs off it (`/oauth2/auth`, `/oauth2/token`, `/logout`,35 `/.well-known/openid-configuration`, `/.well-known/jwks`,36 `/oauth2/user_profile`).37- **Applications** — credentials live on an "application" in the38 Kinde dashboard. Three kinds you'll see:39 - **Back-end web** (confidential, has `client_secret`) — auth code40 flow with a server.41 - **Front-end / SPA / mobile** (public, no secret) — auth code +42 PKCE.43 - **Machine-to-machine (M2M)** — client credentials flow, no user.44- **Grants Kinde supports** — authorization code (with optional45 PKCE), authorization code + PKCE for SPAs, device authorization46 for CLIs and TVs, client credentials for M2M, refresh token.47 Implicit flow is **not supported**.48- **Tokens** — three of them, all JWTs:49 - `id_token` — user identity (sub, email, name). Validate, don't50 send to APIs.51 - `access_token` — what your APIs receive in `Authorization:52 Bearer …`. Validate signature via JWKS, plus `iss`, `aud`, `exp`.53 - `refresh_token` — only issued when the `offline` scope is54 requested. Store httpOnly and server-side.55- **Scopes** — `openid profile email offline` is the typical set.56 Use `offline` (not `offline_access`).57- **Organizations** — Kinde's multi-tenancy primitive. Identified58 by `org_code` like `org_1234`. A user can belong to many; pass59 `org_code=…` on the authorize URL to log them into a specific one.60- **RBAC** — define permissions (e.g. `create:todos`) and roles in61 the dashboard, assign to users per-org. Permissions land on the62 access token as the `permissions` claim and a `roles` claim.63- **Feature flags** — boolean / string / integer / JSON, evaluated64 business → environment → org → user. Read via SDK helpers or the65 `feature_flags` claim on the access token.6667## Required configuration6869Whatever the language, you need:7071| Setting | Where to find it |72|---|---|73| Issuer URL (`https://<tenant>.kinde.com`) | Settings → Applications → your app |74| `client_id` | same |75| `client_secret` | same (back-end / M2M only — never ship to a browser) |76| Allowed callback URL(s) | Settings → Applications → your app → View details. Must match exactly. |77| Allowed logout redirect URL(s) | same |78| Audience (optional) | Set to your API's identifier when you want access tokens scoped to it |7980Hardcoding any of these is a smell — load from env (`KINDE_DOMAIN`,81`KINDE_CLIENT_ID`, `KINDE_CLIENT_SECRET`, `KINDE_REDIRECT_URL`,82`KINDE_LOGOUT_REDIRECT_URL` are the names the official SDKs expect).8384## Go — the short version8586The official Go SDK lives at `github.com/kinde-oss/kinde-go`87(requires Go 1.24+) and ships three packages:8889- `oauth2/authorization_code` — browser auth code flow **and**90 device authorization flow (CLIs).91- `oauth2/client_credentials` — M2M.92- `jwt` — parse and validate tokens from headers, strings, sessions,93 or OAuth2 tokens, with JWKS-based signature verification.9495Minimal auth code setup:9697```go98import (99 "github.com/kinde-oss/kinde-go/oauth2/authorization_code"100 "github.com/kinde-oss/kinde-go/jwt"101)102103flow, err := authorization_code.NewAuthorizationCodeFlow(104 issuerURL, clientID, clientSecret, callbackURL,105 authorization_code.WithSessionHooks(sessionStore),106 authorization_code.WithOffline(),107 authorization_code.WithAudience(apiAudience),108 authorization_code.WithTokenValidation(109 true,110 jwt.WillValidateAlgorithm(),111 jwt.WillValidateAudience(apiAudience),112 ),113)114```115116Full reference in `references/go.md`: PKCE option, prompt option,117device flow, M2M, JWT validation helpers, middleware patterns118(net/http and Gin).119120## TypeScript — the short version121122Pick the package that matches the runtime:123124| Stack | Package |125|---|---|126| Next.js 13+ App Router | `@kinde-oss/kinde-auth-nextjs` |127| Express / Hono / vanilla Node | `@kinde-oss/kinde-typescript-sdk` |128| React SPA | `@kinde-oss/kinde-auth-react` |129| Browser-only JS | `@kinde-oss/kinde-auth-pkce-js` |130| Management API client | `@kinde/management-api-js` |131132Vanilla TS server (Express-style):133134```ts135import { createKindeServerClient, GrantType }136 from "@kinde-oss/kinde-typescript-sdk";137138const kinde = createKindeServerClient(GrantType.AUTHORIZATION_CODE, {139 authDomain: process.env.KINDE_DOMAIN!,140 clientId: process.env.KINDE_CLIENT_ID!,141 clientSecret: process.env.KINDE_CLIENT_SECRET!,142 redirectURL: process.env.KINDE_REDIRECT_URL!,143 logoutRedirectURL: process.env.KINDE_LOGOUT_REDIRECT_URL!,144});145```146147Then expose `/login`, `/register`, `/callback`, `/logout` handlers,148each operating on a per-request `SessionManager`. Full code,149session-manager interface, and helper APIs (`getUserProfile`,150`getPermission`, `getBooleanFlag`, `createOrg`, …) in151`references/typescript.md`. Next.js specifics — route handler,152proxy middleware, server vs. client helpers, `<LoginLink>` /153`<LogoutLink>` components — are in `references/nextjs.md`.154155## When in doubt: use the raw protocol156157Kinde is standards-compliant OAuth 2.0 / OIDC. If a language has no158SDK, or a use case doesn't fit one, fall back to the protocol:159160- Authorize: `GET https://<tenant>.kinde.com/oauth2/auth?…`161- Token: `POST https://<tenant>.kinde.com/oauth2/token`162- User profile: `GET /oauth2/user_profile`163 (Bearer access token)164- JWKS: `GET /.well-known/jwks`165- Logout: `GET /logout?redirect=<url>`166- Discovery: `GET /.well-known/openid-configuration`167168Endpoints, parameter tables, PKCE recipe, and security checklist in169`references/oauth-without-sdk.md`.170171## Pitfalls the agent should call out1721731. **Scope is `offline`, not `offline_access`.** Kinde explicitly174 does not support `offline_access`. If a refresh token is missing,175 that's the first thing to check.1762. **Callback URLs must match exactly.** Trailing slash, scheme,177 port — all part of the match. Errors usually surface as178 `invalid_request` on the authorize endpoint.1793. **`client_secret` is server-only.** SPAs and mobile use PKCE.180 If a user pastes a SPA snippet that includes a secret, flag it.1814. **Validate JWTs, don't just decode them.** Verify signature via182 JWKS, plus `iss`, `aud`, `exp`. Both Go (`jwt.WillValidateWith…`)183 and TS SDKs do this automatically when configured; raw-protocol184 integrations must do it explicitly.1855. **Org context comes from a claim, not the URL.** After login,186 read `org_code` off the access token; trusting a query string is187 the standard tenant-mix-up bug.1886. **Implicit flow is not supported.** Don't try to wire up189 `response_type=token`.1907. **Pages Router vs App Router** in Next.js use *different* SDK191 surface area. The App Router patterns in `references/nextjs.md`192 do not transfer one-for-one to the Pages Router SDK.193194## Reference guides195196- `references/go.md` — authorization code, device, client197 credentials, JWT validation, middleware. Full APIs.198- `references/typescript.md` — server SDK, session manager,199 organizations, flags, permissions, refresh.200- `references/nextjs.md` — App Router integration: route handler,201 proxy/middleware, server + client helpers, components.202- `references/oauth-without-sdk.md` — endpoints, parameters,203 PKCE, refresh, logout, security checklist.204- `references/management-api.md` — calling the management API205 (users, orgs, roles, permissions, flags) from any language.206207## MCP208209Use Context7 MCP (`resolve-library-id` then `query-docs`) to pull210the freshest official docs for `kinde-typescript-sdk`,211`kinde-auth-nextjs`, or `kinde-go` when version-specific behaviour212matters.