📦 Marketplace⭐ GitHub
API Referencev2.0

Auth, Session & Validation


Table of Contents


AuthService

MonkeysLegion\Auth\Service\AuthService

Core authentication service — guard-agnostic credential-based auth with rate limiting, token versioning, 2FA, and refresh token family tracking.

Constructor

new AuthService(
    users: UserProviderInterface,
    hasher: PasswordHasher,
    jwt: JwtService,
    tokenStorage: ?TokenStorageInterface = null,
    rateLimiter: ?RateLimiterInterface = null,
    twoFactor: ?TwoFactorProviderInterface = null,
    events: ?EventDispatcherInterface = null,
);

Methods

register(string $email, string $password, array $attributes = [], ?string $ip = null): AuthenticatableInterface

Register a new user. Hashes password, dispatches UserRegistered event.

Throws: UserAlreadyExistsException, RateLimitExceededException


login(string $email, string $password, ?string $ip = null, ?string $userAgent = null): AuthResult

Authenticate with email/password. Returns tokens or 2FA challenge.

Throws: InvalidCredentialsException, AccountLockedException, RateLimitExceededException

$result = $auth->login('user@example.com', 'password');
if ($result->requires2FA) {
    // Send $result->challengeToken to client for 2FA verification
} else {
    $tokens = $result->tokens; // TokenPair
}

verify2FA(string $challengeToken, string $code, ?string $ip, ?string $ua): AuthResult

Complete login after 2FA verification (TOTP or recovery code).

Throws: TwoFactorInvalidException, TokenInvalidException


refresh(string $refreshToken, ?string $ip = null): TokenPair

Refresh an access token. Implements token family rotation for reuse attack detection.

Throws: TokenExpiredException, TokenRevokedException, TokenInvalidException


validateAccessToken(string $token): array<string, mixed>

Validate an access token, check blacklist and version.

Throws: TokenExpiredException, TokenRevokedException, TokenInvalidException


getUserFromToken(string $token): ?AuthenticatableInterface

Extract user from access token. Returns null on any failure.


logout(string $accessToken, bool $allDevices = false, ?string $ip = null): void

Revoke tokens. If $allDevices = true, increments token version to invalidate all sessions.


changePassword(AuthenticatableInterface $user, string $current, string $new, ?string $ip = null): void

Change password. Automatically invalidates all tokens.

Throws: InvalidCredentialsException


issueTokenPair(AuthenticatableInterface $user, ?string $familyId = null): TokenPair

Issue a new access + refresh token pair for a user.


JwtService

MonkeysLegion\Auth\Service\JwtService

JWT token issuance and verification using HS256/RS256.

Properties (PHP 8.4 Hooks)

PropertyTypeDescription
$accessTtlintAccess token TTL in seconds
$refreshTtlintRefresh token TTL in seconds

Constructor

ParamTypeDefaultDescription
$secretstringSigning key
$accessTtlint1800Access token TTL (30 min)
$refreshTtlint604800Refresh token TTL (7 days)
$leewayint0Clock skew tolerance
$nbfSkewint0NBF backward offset
$issuer?stringnullJWT iss claim
$audience?stringnullJWT aud claim
$algorithmstring'HS256'Signing algorithm

Methods

MethodSignatureReturnsDescription
issueAccessToken()(array $claims)stringIssue access token
issueRefreshToken()(array $claims, ?string $familyId)stringIssue refresh token with family tracking
issue()(array $claims, int $ttl)stringIssue custom-TTL token
decode()(string $token)arrayDecode & verify token
decodeWithLeeway()(string $token, int $leeway)arrayDecode with extra leeway
getExpiration()(string $token)?intGet exp claim (no sig verify)
isExpired()(string $token)boolCheck if expired (no sig verify)
getTokenId()(string $token)?stringExtract jti claim
generateTokenId()()stringCSPRNG token ID

Auth Attributes

AttributeTargetDescription
#[Authenticated]Method/ClassRequire authenticated user
#[Authorize(policy, method)]MethodCheck authorization policy
#[RequiresRole('admin')]Method/ClassRequire specific role
#[RequiresPermission('posts.edit')]Method/ClassRequire specific permission
#[RateLimit(max: 60, per: 60)]MethodPer-route rate limiting
#[Guard('jwt')]Method/ClassSpecify auth guard
#[Passkey]MethodWebAuthn passkey auth

Auth DTOs

TokenPair

final readonly class TokenPair {
    public string $accessToken;
    public string $refreshToken;
    public int $accessExpiresAt;
    public int $refreshExpiresAt;
    public ?string $familyId;
}

AuthResult

final class AuthResult {
    public readonly bool $success;
    public readonly bool $requires2FA;
    public readonly ?AuthenticatableInterface $user;
    public readonly ?TokenPair $tokens;
    public readonly ?string $challengeToken;
    public readonly ?string $guardUsed;

    public static function success(user, tokens, guard): self;
    public static function requires2FA(challengeToken): self;
}

Auth Exceptions

ExceptionHTTPDescription
InvalidCredentialsException401Wrong email/password
TokenExpiredException401JWT has expired
TokenInvalidException401JWT signature/format invalid
TokenRevokedException401Token blacklisted or version mismatch
UnauthorizedException401Generic unauthorized
ForbiddenException403Insufficient permissions
AccountLockedException423Too many failed attempts
RateLimitExceededException429Rate limit hit
UserAlreadyExistsException409Duplicate registration
TwoFactorRequiredException4032FA challenge needed
TwoFactorInvalidException401Invalid 2FA code
InvalidApiKeyException401Bad API key

Auth Events

All events are dispatched via PSR-14.

EventPropertiesDescription
LoginSucceeded$user, $ipAddress, $userAgentSuccessful login
LoginFailed$email, $reason, $ipAddress, $userAgentFailed login attempt
Logout$userId, $allDevices, $ipAddressUser logged out
UserRegistered$user, $ipAddressNew registration
PasswordChanged$userId, $ipAddressPassword updated
TokenRefreshed$userId, $ipAddressToken pair refreshed
PasskeyAuthenticated$user, $credentialIdWebAuthn login

SessionManager

MonkeysLegion\Session\SessionManager implements SessionInterface

Session management with file, database, and Redis drivers.

Properties (PHP 8.4 Hooks)

PropertyTypeDescription
$idstringSession ID (get/set)
$isStartedboolWhether session is active
$attributesAttributeBagKey-value attribute bag
$flashesFlashBagFlash message bag
$metadataMetadataBagSession metadata (IP, UA, timestamps)

Lifecycle Methods

MethodSignatureReturnsDescription
start()()boolStart session (locks, reads, initializes)
save()()boolSerialize and persist session data
regenerate()(bool $destroy = false)boolRegenerate session ID
invalidate()()boolClear all data and regenerate
destroy()()boolAlias for invalidate()

Data Methods

MethodSignatureReturnsDescription
get()(string $key, mixed $default = null)mixedGet attribute
set()(string $key, mixed $value)voidSet attribute
has()(string $key)boolCheck attribute exists
remove()(string $key)voidRemove attribute
pull()(string $key, mixed $default = null)mixedGet and remove
all()()arrayAll attributes

Flash Data

MethodSignatureDescription
flash()(string $key, mixed $value): voidFlash data (available next request)
reflash()(): voidKeep all flash data for another request
keep()(string ...$keys): voidKeep specific flash keys
now()(string $key, mixed $value): voidFlash for current request only

CSRF

MethodSignatureReturnsDescription
token()()stringGet CSRF token
regenerateToken()()voidGenerate new CSRF token

Session Drivers

DriverConfig KeyDescription
FileDriverSESSION_DRIVER=fileFile-based (default)
DatabaseDriverSESSION_DRIVER=databaseDatabase table
RedisDriverSESSION_DRIVER=redisRedis store

Validation Attributes

All in MonkeysLegion\Validation\Attributes\. Used on DTO constructor parameters.

AttributeParametersDescription
#[NotBlank]Must not be empty
#[Length(min, max)]int $min, int $maxString length range
#[Email]Valid email format
#[Range(min, max)]float $min, float $maxNumeric range
#[Regex(pattern)]string $patternPCRE pattern match
#[Url]Valid URL format
#[Uuid]Valid UUID format
#[Choice(choices)]array $choicesValue must be in list
#[Unique(table, column)]string $table, string $columnDatabase uniqueness
#[Confirmed]Must match {field}_confirmation
#[Date]Valid date string
#[Numeric]Numeric value
#[Integer]Integer value
#[Boolean]Boolean value
#[ArrayOf(type)]string $typeArray of specific type
#[MinCount(n)]int $nMinimum array elements
#[MaxCount(n)]int $nMaximum array elements

Usage in DTOs

final readonly class CreateUserRequest
{
    public function __construct(
        #[NotBlank]
        #[Email]
        public string $email,

        #[NotBlank]
        #[Length(min: 8, max: 128)]
        public string $password,

        #[Length(max: 255)]
        public string $name = '',
    ) {}
}

DTOs are auto-validated when type-hinted in controller methods. Returns 422 Unprocessable Content on failure.


Gate (Authorization)

MonkeysLegion\Auth\Policy\Gate

Policy-based authorization.

Usage

// In controller
#[Authorize(PostPolicy::class, 'update')]
public function update(ServerRequestInterface $request, string $id): Response { ... }

// Policy class
final class PostPolicy
{
    public function update(AuthenticatableInterface $user, Post $post): bool
    {
        return $user->getAuthIdentifier() === $post->author_id;
    }
}

RBAC

MonkeysLegion\Auth\RBAC\RbacService

Role-Based Access Control.

Methods

MethodSignatureReturnsDescription
hasRole()(user, string $role)boolCheck user has role
hasPermission()(user, string $permission)boolCheck user has permission
assignRole()(user, string $role)voidAssign role to user
revokeRole()(user, string $role)voidRemove role from user

Configuration (config/auth.mlc)

rbac {
    roles {
        admin    { permissions = ["*"] }
        editor   { permissions = ["posts.*", "media.*"], inherits = ["viewer"] }
        viewer   { permissions = ["posts.view", "media.view"] }
    }
}