addMinutes(self::minutesForPortal($portal)); } public static function loginMeta(string $portal): array { $expiresAt = self::expiresAtForPortal($portal); return [ 'token_expires_at' => $expiresAt->toIso8601String(), 'token_lifetime_minutes' => self::minutesForPortal($portal), ]; } public static function isExpired(Authenticatable $user, string $portal): bool { if (! method_exists($user, 'token')) { return false; } $token = $user->token(); if (! $token || ! $token->created_at) { return false; } return Carbon::now()->greaterThanOrEqualTo( Carbon::parse($token->created_at)->addMinutes(self::minutesForPortal($portal)) ); } public static function revokeActiveTokens(Authenticatable $user): void { if (! method_exists($user, 'tokens')) { return; } try { $user->tokens()->where('revoked', false)->update(['revoked' => true]); } catch (\Throwable $e) { // Login should not fail if revocation fails. } } }