Metadata-Version: 2.4
Name: fikiri-id-sdk
Version: 0.1.0
Summary: SDK officiel FikiriID — intégration SSO OIDC pour plateformes Python
License-Expression: MIT
Keywords: fikiri,oidc,sso,oauth2,authentication
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: respx; extra == "dev"
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.110; extra == "fastapi"
Provides-Extra: django
Requires-Dist: django>=4.2; extra == "django"

# fikiri-id-sdk

SDK officiel FikiriID pour Python. Intègre le flow OAuth2 Authorization Code + PKCE (RFC 7636) avec adaptateurs pour FastAPI et Django.

## Installation

```bash
pip install fikiri-id-sdk
# Avec FastAPI :
pip install "fikiri-id-sdk[fastapi]"
# Avec Django :
pip install "fikiri-id-sdk[django]"
```

## Usage de base

```python
from fikiri_id_sdk import FikiriIDClient

with FikiriIDClient(
    base_url="http://77.42.72.129:8094",
    client_id="fikiri-AbCdEfGhIj",
    client_secret="votre_secret",
    redirect_uri="https://market.fikiri.cd/callback",
    scopes=["openid", "profile", "email", "kyc:status"],
) as client:
    # 1. Générer l'URL de redirection (stocker code_verifier en session)
    url, code_verifier = client.get_authorization_url(state="random-state")

    # 2. Sur la route /callback
    tokens = client.exchange_code(code="<code>", code_verifier=code_verifier)
    user = client.get_userinfo(tokens["access_token"])
    # → {"sub": "d569…", "fikiri_id": "06-002-1-1-1990-0042", "kyc_verified": True}
```

---

## Intégration FastAPI

```python
from fastapi import FastAPI, Depends
from fikiri_id_sdk import FikiriIDClient
from fikiri_id_sdk.fastapi import make_require_user, make_require_kyc

app = FastAPI()

fikiri = FikiriIDClient(
    base_url="http://77.42.72.129:8094",
    client_id="fikiri-AbCdEfGhIj",
    client_secret="votre_secret",
    redirect_uri="https://market.fikiri.cd/callback",
)

require_user = make_require_user(fikiri)
require_kyc  = make_require_kyc(fikiri, min_level="verifie")

@app.get("/me")
def me(user=Depends(require_user)):
    return {"fikiri_id": user["fikiri_id"], "name": user["name"]}

@app.post("/transfert")
def transfert(user=Depends(require_kyc)):
    # Accessible uniquement aux utilisateurs KYC vérifié
    return {"ok": True}

# Callback OAuth
@app.get("/callback")
def callback(code: str, state: str, request: Request):
    code_verifier = request.session["code_verifier"]
    tokens = fikiri.exchange_code(code=code, code_verifier=code_verifier)
    return {"access_token": tokens["access_token"]}
```

---

## Intégration Django

```python
# settings.py
from fikiri_id_sdk import FikiriIDClient

FIKIRI_ID_CLIENT = FikiriIDClient(
    base_url="http://77.42.72.129:8094",
    client_id="fikiri-AbCdEfGhIj",
    client_secret="votre_secret",
    redirect_uri="https://market.fikiri.cd/callback",
)

MIDDLEWARE = [
    ...
    "fikiri_id_sdk.django.FikiriIDMiddleware",
]
```

```python
# views.py
from django.http import JsonResponse
from fikiri_id_sdk.django import fikiri_login_required

@fikiri_login_required
def profil(request):
    user = request.fikiri_user   # dict introspect — jamais None ici
    return JsonResponse({"fikiri_id": user["fikiri_id"]})

def publique(request):
    user = getattr(request, "fikiri_user", None)  # peut être None
    return JsonResponse({"connecte": user is not None})
```

---

## Client async (FastAPI / asyncio)

```python
from fikiri_id_sdk import FikiriIDAsyncClient

async with FikiriIDAsyncClient(
    base_url="http://77.42.72.129:8094",
    client_id="fikiri-AbCdEfGhIj",
    client_secret="votre_secret",
    redirect_uri="https://market.fikiri.cd/callback",
) as client:
    tokens = await client.exchange_code(code, code_verifier)
    user   = await client.get_userinfo(tokens["access_token"])
    info   = await client.introspect(tokens["access_token"])
```

---

## Méthodes disponibles

### `FikiriIDClient` (sync) / `FikiriIDAsyncClient` (async)

| Méthode | Description |
|---------|-------------|
| `get_authorization_url(state)` | Retourne `(url, code_verifier)` — stocker le verifier en session |
| `exchange_code(code, code_verifier)` | Échange le code → `access_token` + `refresh_token` |
| `get_userinfo(access_token)` | Profil complet selon les scopes accordés |
| `introspect(token)` | Validation middleware RFC 7662 — `{"active": true/false, ...}` |
| `refresh_access_token(refresh_token)` | Renouvelle l'access token |
| `revoke_token(token)` | Révoque access ou refresh token à la déconnexion |
| `get_discovery()` | Configuration OIDC `/.well-known/openid-configuration` |

### `make_require_user(client)` (FastAPI)

Retourne une dépendance FastAPI qui valide le Bearer token et injecte le profil.

### `make_require_kyc(client, min_level)` (FastAPI)

Variante avec vérification du niveau KYC (`'en_cours'` ou `'verifie'`).

### `FikiriIDMiddleware` (Django)

Injecte `request.fikiri_user` (dict introspect ou `None`) sur toutes les requêtes.

### `fikiri_login_required` (Django)

Décorateur de vue — retourne 401 JSON si `request.fikiri_user` est `None`.

---

Serveur live : **http://77.42.72.129:8094** · [Swagger UI](http://77.42.72.129:8094/docs) · [Guide d'intégration](../../docs/integration.md)
