obsidiane/auth-sdk
最新稳定版本:1.0.11
Composer 安装命令:
composer require obsidiane/auth-sdk
包简介
Symfony bundle fournissant un client Obsidiane Auth orienté API (bridge + facades, Bearer token)
README 文档
README
SDK PHP orienté API pour consommer Obsidiane Auth avec une logique proche du SDK JS (bridge + facades). Authentification via Bearer token (optionnel), pas de cookies.
Features
✅ Bridge API-first (get/getCollection/post/patch/put/delete + request)
✅ Facades ressources avec modèles hydratés via Symfony Serializer
✅ JSON-LD par défaut (Accept: application/ld+json)
✅ Content-Type auto (POST/PUT: application/ld+json, PATCH: application/merge-patch+json)
✅ Exceptions structurées via ApiErrorException sur erreurs HTTP
✅ Configuration Symfony simple et explicite
Installation
composer require obsidiane/auth-sdk
Configuration Symfony
config/bundles.php
return [ // ... Obsidiane\AuthBundle\ObsidianeAuthBundle::class => ['all' => true], ];
config/packages/obsidiane_auth.yaml
obsidiane_auth: base_url: '%env(OBSIDIANE_AUTH_BASE_URL)%' token: '%env(OBSIDIANE_AUTH_TOKEN)%' # optionnel defaults: headers: { } timeout_ms: 10000 # optionnel debug: false
.env
OBSIDIANE_AUTH_BASE_URL=https://auth.example.com OBSIDIANE_AUTH_TOKEN=your-static-bearer-token
Le token est optionnel : s'il est absent ou vide, aucun header Authorization n'est ajouté (utile pour les endpoints publics).
base_url est requis et peut inclure ou non /api selon votre usage (adaptez vos routes en conséquence).
Utilisation
FacadeFactory (ressources)
use Obsidiane\AuthBundle\Bridge\FacadeFactory; final class UsersService { public function __construct( private readonly FacadeFactory $factory, ) {} public function listUsers(): array { $users = $this->factory->create('/api/users', \App\Dto\UserRead::class); $result = $users->getCollection(); return $result->items; // list<UserRead> } }
BridgeFacade (endpoints custom)
use Obsidiane\AuthBundle\Bridge\BridgeFacade; final class AuthService { public function __construct( private readonly BridgeFacade $bridge, ) {} public function me(): array { return $this->bridge->get('/api/auth/me'); } }
Requête custom avec HttpRequestConfig
use Obsidiane\AuthBundle\Bridge\Http\HttpRequestConfig; $req = new HttpRequestConfig( method: 'GET', url: '/api/users', query: ['page' => 1, 'itemsPerPage' => 20], headers: ['X-Request-ID' => 'req_123'], timeoutMs: 5000, ); $response = $bridge->request($req);
Hydratation des modèles
Les facades utilisent Symfony\Component\Serializer\Normalizer\NormalizerInterface et DenormalizerInterface pour la sérialisation/désérialisation.
Les modèles du SDK exposent @id via la propriété $iri.
Si vous utilisez vos propres modèles, mappez @id avec #[SerializedName('@id')].
Note technique : Le SDK nécessite que le SerializerInterface implémente aussi NormalizerInterface et DenormalizerInterface (ce qui est le cas avec le Serializer standard de Symfony). Le FacadeFactory vérifie automatiquement ces interfaces au runtime.
API publique
Classes principales
BridgeFacade: appels HTTP bas niveau (GET, GET collection, POST, PUT, PATCH, DELETE, request)FacadeFactory: création deResourceFacade<T>avec hydratation automatiqueResourceFacade<T>: CRUD + collections hydratées (generic type-safe)Collection<T>: items + metadata JSON-LD (totalItems,id,type,context,view,search)
Modèles
Les modèles exposent les propriétés JSON-LD standard :
Item: classe de base avec$iri(@id),$type(@type),$context(@context)- Tous les modèles générés héritent de
Itemou exposent ces propriétés
Paramètres de configuration
Clés principales
base_url: URL de base du service Auth (requis).token: Bearer token optionnel, ajouté si non vide.debug: active les logs debug du bridge HTTP.
defaults (dans obsidiane_auth.yaml)
headers: headers HTTP appliqués à toutes les requêtes (peuvent être surchargés par appel)timeout_ms: timeout en millisecondes (par défaut: aucun)
Options par requête
Toutes les méthodes de ResourceFacade et BridgeFacade acceptent un paramètre HttpCallOptions optionnel :
use Obsidiane\AuthBundle\Bridge\Http\HttpCallOptions; $options = new HttpCallOptions( headers: ['X-Custom-Header' => 'value'], timeoutMs: 5000, // en ms responseType: 'text', ); $users->getCollection([], $options);
responseType: 'text' retourne la réponse brute (string). Par défaut, la réponse est décodée en JSON.
Exemples avancés
Filtrage et pagination
$users = $factory->create('/api/users', UserRead::class); // Pagination $result = $users->getCollection([ 'page' => 2, 'itemsPerPage' => 10, ]); // Filtres $result = $users->getCollection([ 'filters' => [ 'email' => 'user@example.com', 'role' => 'ROLE_ADMIN', ], ]); // Metadata echo $result->totalItems; // Nombre total d'items echo $result->id; // IRI de la collection (@id)
Headers personnalisés
use Obsidiane\AuthBundle\Bridge\Http\HttpCallOptions; $options = new HttpCallOptions( headers: [ 'X-Request-ID' => uniqid(), 'Accept-Language' => 'fr-FR', ], ); $user = $users->get('/api/users/1', $options);
Gestion d'erreurs
use Obsidiane\AuthBundle\Exception\ApiErrorException; try { $user = $users->get('/api/users/999'); } catch (ApiErrorException $e) { // Erreur HTTP (404, 500, etc.) error_log($e->getMessage()); error_log('Status code: ' . $e->getStatusCode()); error_log('Error code: ' . $e->getErrorCode()); }
ApiErrorException expose aussi getDetails() et getPayload() pour inspecter la réponse.
Codes d’erreur (API)
Statuts HTTP exposés par l’API Auth :
| HTTP | Cas principaux | Détails |
|---|---|---|
| 400 | Requête invalide, token invalide | verify-email (id manquant), reset/verify token invalide, invitation sans token (details.token = INVALID_INVITATION). |
| 401 | Non authentifié | me, JWT invalide/expiré, service token invalide, login refusé. |
| 403 | Accès refusé | Origin/Referer non autorisé, endpoints admin sans rôle. |
| 404 | Introuvable | Invitation inconnue, user introuvable, inscription désactivée. |
| 409 | Conflit | Email déjà utilisé, invitation déjà acceptée, bootstrap requis ou déjà fait. |
| 410 | Expiré | Invitation expirée, lien de vérification expiré, reset token expiré. |
| 422 | Validation | Email/mot de passe invalides, champs requis, INVALID_ROLES, confirmation mot de passe. |
| 423 | Verrouillé | Email non vérifié lors du login. |
| 429 | Rate limit | Login, register, invite, invite/complete, password/forgot/reset, setup/admin. |
| 500 | Erreur interne | Échec de reset password non géré (ResetRequestFailedException). |
| 503 | Service indisponible | Échec d’envoi d’email (MailDispatchException). |
Identifiants d’erreurs utiles dans les payloads/validations :
INVALID_INVITATIONINVALID_ROLES
Invitation (règles métiers)
- Un utilisateur déjà vérifié ne peut pas être ré-invité.
- Un utilisateur non vérifié peut être ré-invité : l’email est renvoyé si l’invitation est encore valide, sinon elle est régénérée.
Qualité du code
Le SDK maintient une qualité de code stricte :
- ✅ PHPStan Level 6 : Zero erreur d'analyse statique
- ✅ Types stricts :
declare(strict_types=1)dans tous les fichiers - ✅ Generics :
ResourceFacade<T>,Collection<T>pour type-safety - ✅ Readonly : Classes immuables avec
readonly - ✅ PSR-12 : Standard de code PHP
Troubleshooting
Erreur "Serializer must implement NormalizerInterface"
Si vous obtenez cette erreur, assurez-vous que votre SerializerInterface est bien le Serializer standard de Symfony (pas un mock ou une implémentation custom sans normalizer).
Timeout des requêtes
Par défaut, aucun timeout n'est appliqué. Pour en définir un :
# config/packages/obsidiane_auth.yaml obsidiane_auth: defaults: timeout_ms: 30000 # 30 secondes
Ou par requête :
use Obsidiane\AuthBundle\Bridge\Http\HttpCallOptions; $options = new HttpCallOptions(timeoutMs: 30000); $result = $users->getCollection([], $options);
统计信息
- 总下载量: 125
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-15