Skip to main content
DevelopersOAuth 2.0
OAuth 2.0 Guide

Konekte ak KobKlein

Flou kòd otorizasyon OAuth 2.0 · Authorization Code Flow with optional PKCE

Overview

"Sign in with KobKlein" lets your users log into your application using their KobKlein identity — verified KYC status, K-ID, and role — without your app ever touching a password. KobKlein acts as the identity provider (IdP) via standard OAuth 2.0 Authorization Code Flow.

Base URL

https://app.kobklein.com

Token URL

https://api.kobklein.com/v1/oauth/token

Userinfo

https://api.kobklein.com/v1/oauth/userinfo

Register an App

OAuth clients are created by KobKlein admins. Contact partners@kobklein.com or ask your account manager to provision a client ID + secret for your application. You will receive:

  • client_id — public identifier, safe to include in URLs
  • client_secret — keep server-side only, never in client bundles
  • Approved redirect_uri(s) — must match exactly, including trailing slash

Authorization URL

Redirect the user to the KobKlein consent screen. Build the URL with these parameters:

text
https://app.kobklein.com/oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fyourapp.com%2Fcallback
  &scope=openid%20profile%20kyc
  &state=RANDOM_CSRF_TOKEN
  &code_challenge=BASE64URL_S256_HASH   (optional — PKCE)
  &code_challenge_method=S256            (optional — PKCE)
ParameterRequiredDescription
response_typeYesAlways code
client_idYesYour app's client_id
redirect_uriYesMust match registered URI exactly
scopeYesSpace-separated list (see Scopes section)
stateRecommendedRandom string to prevent CSRF; returned in callback
code_challengeNoPKCE: BASE64URL(SHA-256(code_verifier))
code_challenge_methodNoMust be S256 when code_challenge is set

Token Exchange

After the user approves, KobKlein redirects to your redirect_uri with code and state. Exchange the code for an access token server-side:

javascript
// Node.js example
const response = await fetch("https://api.kobklein.com/v1/oauth/token", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    grant_type:    "authorization_code",
    code:          req.query.code,
    redirect_uri:  "https://yourapp.com/callback",
    client_id:     process.env.KOBKLEIN_CLIENT_ID,
    client_secret: process.env.KOBKLEIN_CLIENT_SECRET,
    code_verifier: session.codeVerifier,  // if using PKCE
  }),
});

const { access_token, token_type, expires_in, scope } = await response.json();
// access_token starts with "kk_at_"
// expires_in: 3600 (1 hour)
python
# Python example
import requests

resp = requests.post("https://api.kobklein.com/v1/oauth/token", json={
    "grant_type":    "authorization_code",
    "code":          request.args["code"],
    "redirect_uri":  "https://yourapp.com/callback",
    "client_id":     os.environ["KOBKLEIN_CLIENT_ID"],
    "client_secret": os.environ["KOBKLEIN_CLIENT_SECRET"],
})

data = resp.json()
access_token = data["access_token"]  # "kk_at_..."

Token Response

json
{
  "access_token": "kk_at_a3f9e1c7d2b8f0e4...",
  "token_type":   "Bearer",
  "expires_in":   3600,
  "scope":        "openid profile kyc"
}

Userinfo Endpoint

Fetch the authenticated user's profile using the access token:

bash
curl https://api.kobklein.com/v1/oauth/userinfo \
  -H "Authorization: Bearer kk_at_a3f9e1c7d2b8f0e4..."

The response is scoped to what the user approved. Example with openid profile kyc:

json
{
  "sub":       "cuid2_user_id",
  "kid":       "KK-HT-00042819",
  "name":      "Jean Baptiste",
  "handle":    "@jeanbaptiste",
  "role":      "CLIENT",
  "kycTier":   2,
  "kycStatus": "approved",
  "country":   "HT",
  "createdAt": "2025-11-14T09:22:00.000Z"
}

Scopes

openid

sub (cuid), kid (K-ID), role, country, createdAt

profile

name, handle, avatarUrl (added on top of openid)

kyc

kycTier (0–3), kycStatus (approved/pending/rejected)

wallet:balance

htgBalance, usdBalance (read-only, no history)

identity

trustScore, trustTier, activeCredentials[]

Request only the scopes your app needs. The consent screen shows users exactly what each scope accesses.

PKCE (Recommended for SPAs & Mobile)

Use PKCE (Proof Key for Code Exchange) when you cannot safely store a client secret — single-page apps, mobile apps, or Electron apps.

javascript
// 1. Generate code verifier (server or client-side)
const codeVerifier = crypto.randomBytes(48).toString("base64url");

// 2. Compute S256 challenge
const codeChallenge = crypto
  .createHash("sha256")
  .update(codeVerifier)
  .digest("base64url");

// 3. Include in authorization URL
const authUrl = new URL("https://app.kobklein.com/oauth/authorize");
authUrl.searchParams.set("code_challenge", codeChallenge);
authUrl.searchParams.set("code_challenge_method", "S256");
// ... other params

// 4. Include verifier in token exchange
fetch("https://api.kobklein.com/v1/oauth/token", {
  method: "POST",
  body: JSON.stringify({
    grant_type:    "authorization_code",
    code,
    redirect_uri,
    client_id,
    // no client_secret needed with PKCE!
    code_verifier: codeVerifier,
  }),
});

Token Revocation

Revoke an access token (e.g., when the user disconnects your app from their KobKlein settings):

bash
curl -X POST https://api.kobklein.com/v1/oauth/revoke \
  -H "Content-Type: application/json" \
  -d '{"token": "kk_at_a3f9e1c7d2b8f0e4..."}'

# 200 OK → { "ok": true }

Error Reference

errorHTTPCause
invalid_client401Bad client_id or client_secret
invalid_grant400Code expired (10 min TTL), already used, or PKCE mismatch
invalid_scope400Requested scope not in client's allowedScopes
redirect_uri_mismatch400redirect_uri doesn't match any registered URI
access_denied400User denied the authorization request
token_expired401Access token expired — request a new authorization