monkeyscloud / monkeyslegion-auth
High-performance authentication & authorization: multi-guard, JWT, RBAC, OAuth, 2FA, API keys, passkeys
Package info
github.com/MonkeysCloud/MonkeysLegion-Auth
pkg:composer/monkeyscloud/monkeyslegion-auth
2.1.0
2026-04-16 03:19 UTC
Requires
- php: ^8.4
- firebase/php-jwt: ^7.0
- monkeyscloud/monkeyslegion-session: *
- psr/event-dispatcher: ^1.0
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- psr/simple-cache: ^3.0
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
Suggests
- ext-openssl: Required for RS256/ES256 asymmetric JWT signing
- ext-redis: Required for Redis-based rate limiting and token storage
- monkeyscloud/monkeyslegion-cli: CLI commands for auth management
- monkeyscloud/monkeyslegion-database: Database-backed user providers and RBAC storage
- monkeyscloud/monkeyslegion-webauthn: WebAuthn/FIDO2 passkey authentication via WebAuthnGuard
- nyholm/psr7: PSR-7 implementation for middleware responses
This package is auto-updated.
Last update: 2026-04-16 03:24:37 UTC
README
Multi-guard, attribute-first authentication and authorization for the MonkeysLegion framework. Ground-up rebuild for PHP 8.4 with property hooks, typed constants, and zero hard dependencies.
Features
| Feature | Status |
|---|---|
| Multi-Guard System | JWT, Session, API Key, WebAuthn/Passkey, Composite (try multiple in order) |
| Attribute-First Auth | #[Guard], #[Authenticated], #[Authorize], #[RequiresRole], #[RequiresPermission], #[RateLimit], #[Passkey] |
| JWT Service | HS256/RS256, token families, refresh rotation attack detection |
| Session Guard | Session fixation prevention, token version validation, remember-me |
| Policy Gate | allows(), denies(), authorize(), inspect() with deny reasons |
| RBAC | Hierarchical roles, wildcard permissions, super-admin, decoupled via RoleRepositoryInterface |
| Password Hasher | NIST SP 800-63B policy engine, Argon2ID/bcrypt, auto-rehash |
| Rate Limiting | Per-route, per-user, configurable via attributes |
| Two-Factor Auth | TOTP (RFC 6238), backup/recovery codes |
| PSR-15 Middleware | Authentication, Authorization, Rate Limiting — all attribute-aware |
| PHP 8.4 Native | Property hooks, typed constants, readonly DTOs |
Requirements
- PHP 8.4 or higher
firebase/php-jwt^7.0psr/http-message^2.0
Installation
composer require monkeyscloud/monkeyslegion-auth:dev-2.0.0
Architecture
src/
├── Attribute/ # #[Guard], #[Authenticated], #[Authorize], #[RequiresRole], #[RequiresPermission], #[RateLimit]
├── Contract/ # GuardInterface, StatefulGuardInterface, AuthenticatableInterface, SessionInterface, UserProviderInterface, ...
├── DTO/ # AuthResult, TokenPair, OAuthUser, PasswordPolicy
├── Event/ # AuthEvent, LoginSucceeded, LoginFailed, Logout, TokenRefreshed, ...
├── Exception/ # AuthException hierarchy with HTTP status codes and logging context
├── Guard/ # JwtGuard, SessionGuard, ApiKeyGuard, CompositeGuard, AuthManager
├── Middleware/ # AuthenticationMiddleware, AuthorizationMiddleware, RateLimitMiddleware
├── Policy/ # Gate (ability-based access control)
├── RBAC/ # RbacService, RoleRepositoryInterface, InMemoryRoleRepository
├── RateLimit/ # InMemoryRateLimiter
├── Service/ # AuthService, JwtService, PasswordHasher
├── Storage/ # InMemoryTokenStorage, InMemoryUserProvider, InMemorySession
├── Trait/ # AuthenticatableTrait, HasRolesTrait, HasPermissionsTrait
└── TwoFactor/ # TotpProvider
Quick Start
JWT Guard (Stateless)
use MonkeysLegion\Auth\Guard\JwtGuard; use MonkeysLegion\Auth\Guard\AuthManager; use MonkeysLegion\Auth\Service\JwtService; $jwt = new JwtService('your-secret-key-at-least-32-chars'); $guard = new JwtGuard($jwt, $userProvider); $manager = new AuthManager(defaultGuard: 'jwt'); $manager->register('jwt', $guard); // Authenticate a request $user = $manager->guard()->authenticate($request);
Session Guard (Stateful)
use MonkeysLegion\Auth\Guard\SessionGuard; $guard = new SessionGuard($session, $userProvider); // Login (regenerates session ID to prevent fixation) $guard->login($user); // Authenticate from session $user = $guard->authenticate($request); // Logout $guard->logout();
WebAuthn / Passkey Guard
Integrates with MonkeysLegion-WebAuthn for passwordless authentication:
use MonkeysLegion\Auth\Guard\WebAuthnGuard; use MonkeysLegion\Auth\Event\PasskeyAuthenticated; use MonkeysLegion\Auth\Attribute\Passkey; // 1. Register the guard $manager->register('webauthn', new WebAuthnGuard($userProvider)); // 2. In your controller: verify the assertion, then set the request attribute $credential = $webAuthnService->verifyAuthentication($assertionResponse); $request = $request->withAttribute('webauthn.user_handle', $credential->userHandle); // 3. The guard resolves the user from the verified attribute $user = $manager->guard('webauthn')->authenticate($request); // 4. Dispatch audit event $dispatcher->dispatch(new PasskeyAuthenticated( userId: $user->getAuthIdentifier(), credentialId: base64_encode($credential->credentialId), ipAddress: $serverParams['REMOTE_ADDR'] ?? null, ));
Mark routes/controllers as requiring passkey authentication:
#[Passkey] // userVerification: 'preferred' #[Passkey(userVerification: 'required')] // high-assurance actions public function transferFunds(): Response { ... }
Attribute-Based Security
use MonkeysLegion\Auth\Attribute\Authenticated; use MonkeysLegion\Auth\Attribute\RequiresRole; use MonkeysLegion\Auth\Attribute\RequiresPermission; use MonkeysLegion\Auth\Attribute\RateLimit; #[Authenticated(guard: 'jwt')] #[RequiresRole(['admin', 'editor'], mode: 'any')] #[RateLimit(maxAttempts: 60, decaySeconds: 60)] class ArticleController { #[RequiresPermission('articles.publish')] public function publish(int $id): Response { // Only authenticated users with admin/editor role // and articles.publish permission can reach here } }
Policy Gate
use MonkeysLegion\Auth\Policy\Gate; $gate = new Gate(); $gate->define('update-post', fn($user, $post) => $user->id === $post->authorId); // Check $gate->allows($user, 'update-post', $post); // true/false $gate->authorize($user, 'update-post', $post); // throws UnauthorizedException // Detailed deny reason $result = $gate->inspect($user, 'update-post', $post); $result->allowed; // false $result->reason; // "Not authorized for: update-post"
Password Hashing with Policy
use MonkeysLegion\Auth\Service\PasswordHasher; use MonkeysLegion\Auth\DTO\PasswordPolicy; $hasher = new PasswordHasher( policy: new PasswordPolicy( minLength: 12, requireUppercase: true, requireNumbers: true, requireSymbols: true, rejectCommon: true, ), ); $hash = $hasher->hash('MyStr0ng!Pass'); $hasher->verify('MyStr0ng!Pass', $hash); // true $hasher->needsRehash($hash); // false
Security Features
- Token family tracking — detects refresh token reuse attacks
- CSPRNG token IDs —
random_bytes(16)for all token identifiers - Session fixation prevention — session regenerated on every login
- Token versioning — increment version to invalidate all sessions/tokens globally
- Timing-safe comparisons —
hash_equalsfor all credential/token checks - Account lockout — configurable failed attempt limits
- Audit trail — all auth events include correlation IDs
Testing
composer test # 122 tests, 277 assertions
License
MIT © MonkeysCloud