Documentation API
KonnectID est un provider OAuth2 qui permet aux utilisateurs de contrôler finement quelles données ils partagent avec votre app. L'API est exposée via tRPC sous /api/trpc/*.
Base URL
https://konnectid.meEnveloppe tRPC — toutes les réponses sont encapsulées par tRPC. Les corps de réponse montrés dans cette doc correspondent à result.data dans la réponse JSON réelle : { "result": { "data": { … } } }
Authentification
Flow OAuth2 Authorization Code + PKCE recommandé:
- Redirigez l'utilisateur vers
/oauth/authorize - L'utilisateur accepte (ou révoque) les scopes demandés
- Récupérez le
codesur votreredirect_uri - Échangez le code contre des tokens via
/api/trpc/oauth2.token - Appelez
/api/trpc/oauth2.userInfoavec l'access token
2. Token Exchange
Échange le code contre access_token + refresh_token.
Body
{
"grantType": "authorization_code",
"code": "auth_code_returned_by_authorize",
"clientId": "app_xxxxxxxxxxxxxxxxxxxxxx",
"clientSecret": "secret_xxxxxxxxxxxxxxxxxxxxxx",
"redirectUri": "https://yourapp.com/callback",
"codeVerifier": "PKCE_verifier_max_128_chars"
}Réponse
{
"access_token": "at_...",
"refresh_token": "rt_...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "email profile"
}Le client secret est hashé en DB. KonnectID le retourne une seule fois à la création/régénération via le dashboard dev.
3. UserInfo
Retourne les fields consentis par l'utilisateur.
Réponse
{
"sub": 42,
"email": "user@example.com",
"first_name": "Marie",
"ville": "Lyon",
"google_email": "marie@gmail.com",
"discord_connections": ["github", "spotify"]
}sub (numeric user id KonnectID) toujours présent. Le reste dépend strictement des consents accordés.
4. Refresh Token
{
"grantType": "refresh_token",
"refreshToken": "rt_...",
"clientId": "app_...",
"clientSecret": "secret_..."
}Nouvelle paire renvoyée. L'ancien refresh est révoqué. Refresh expire après 30 jours.
Scopes disponibles
Les scopes correspondent aux data_fields configurés par l'admin KonnectID. Chaque field a un basePrice qui détermine le revenu par accès.
Champs standard
| Scope | Label | Prix | Catégorie |
|---|---|---|---|
| Aucun scope publié. | |||
Champs provider (OAuth chaîné)
Préfixés par le nom du provider, ex: google_email, discord_connections. Disponibles uniquement si l'utilisateur a lié le compte correspondant via /dashboard/trust.
Champs requis (login bloqué)
Préfixez un scope par required: pour le rendre obligatoire. L'utilisateur ne pourra pas désélectionner ce champ et devra le renseigner (saisie possible directement sur l'écran de consentement) avant d'autoriser. Sans cela, l'autorisation est refusée.
scope=required:email required:phone profile
Ici email et phone sont obligatoires, tandis que profile reste facultatif. Le préfixe est retiré côté serveur (les consentements sont tracés par field).
Webhooks
Si vous configurez une webhookUrl sur votre app, KonnectID notifie chaque première autorisation utilisateur.
Payload (POST)
{
"event": "user.authorized",
"appId": 12,
"userId": 42,
"scope": "email profile",
"grantedAt": "2026-05-11T08:42:00.000Z"
} SSRF guard côté serveur: refus de toute URL loopback / IPs privées (RFC 1918 / CGNAT) / link-local / metadata cloud. Use HTTPS public uniquement. redirect: 'manual' côté fetch.
Erreurs
Codes tRPC retournés via TRPCError:
| Code | Sens |
|---|---|
BAD_REQUEST | Input invalide / Zod schema rejet |
UNAUTHORIZED | Token manquant ou expiré |
FORBIDDEN | App désactivée / scope révoqué / cross-user |
NOT_FOUND | Client ID inconnu / consent introuvable |
CONFLICT | Identité non sellable / collision |
INTERNAL_SERVER_ERROR | Erreur serveur inattendue |
PKCE
Recommandé pour tous les clients publics (SPA, mobile, etc.).
# 1. Générer le verifier (43-128 chars URL-safe) verifier = base64url(random(32)) # 2. Calculer le challenge challenge = base64url(sha256(verifier)) # 3. Envoyer dans authorize: codeChallenge = challenge codeChallengeMethod = "S256" # 4. Au token exchange, envoyer le verifier: codeVerifier = verifier
Consentements granulaires
Chaque scope est tracé individuellement dans consents: {userId, appId, fieldId | providerScope, granted, grantedAt, revokedAt}.
L'utilisateur peut révoquer un scope à tout moment depuis /dashboard/consents. Effet immédiat: tokens marqués isRevoked: true, userInfo ne retourne plus le field.
Côté dev: votre app peut révoquer un user via apps.disconnectUser({ appId, userId }) (vérifie ownership).
