定制 betterauth/multimodal-php 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

betterauth/multimodal-php

Composer 安装命令:

composer require betterauth/multimodal-php

包简介

Framework-agnostic authentication library for PHP — works with Symfony, Laravel, or standalone

README 文档

README

Framework-agnostic authentication library for PHP. Session-based, token-based (Paseto V4), or both — works with Symfony, Laravel, or standalone via PDO.

Features

  • Three authentication modes — Monolith (session/cookie), API (stateless Paseto V4 tokens), Hybrid (both)
  • OAuth social login — Google, GitHub, Facebook, Microsoft, Discord, Twitter, Apple
  • OpenID Connect server — act as an SSO provider with authorization code + PKCE
  • Magic links — passwordless email authentication
  • TOTP 2FA — RFC 6238 with backup codes, SHA-256 default, SHA-1 migration path
  • Session security — adaptive risk scoring (IP, device, country, impossible travel)
  • Multi-tenancy — organizations, teams, members, invitations
  • Plugin system — lifecycle hooks (user.created, token.created, session.created, …)
  • PDO storage — 20 ready-to-use repositories, replaceable via interfaces
  • Password security — Argon2id hashing, zxcvbn-inspired strength validation, auto-rehash on login

Requirements

  • PHP 8.2+
  • Extensions: json, openssl, pdo

Installation

composer require betterauth/multimodal-php

Quick start

Session-based (monolith)

use BetterAuth\Core\AuthManager;
use BetterAuth\Core\SessionAuthManager;
use BetterAuth\Core\SessionService;
use BetterAuth\Core\PasswordHasher;
use BetterAuth\Core\Config\AuthConfig;
use BetterAuth\Storage\Pdo\PdoUserRepository;
use BetterAuth\Storage\Pdo\PdoSessionRepository;

$pdo = new PDO('sqlite:auth.db');

$config   = AuthConfig::forMonolith('your-secret-key-min-32-chars');
$users    = new PdoUserRepository($pdo);
$sessions = new PdoSessionRepository($pdo);
$hasher   = new PasswordHasher();
$service  = new SessionService($sessions, $config);

$sessionAuth = new SessionAuthManager($users, $service, $hasher);
$auth        = new AuthManager($config, sessionAuth: $sessionAuth);

// Sign up
$result = $auth->signUp('user@example.com', 'SecureP@ss2024!', 'Alice');

// Sign in
$result = $auth->signIn('user@example.com', 'SecureP@ss2024!');
// $result = ['user' => UserDto, 'session' => Session]

// Validate session
$user = $auth->validateSession($result['session']->getToken());

Token-based (API)

use BetterAuth\Core\AuthManager;
use BetterAuth\Core\TokenAuthManager;
use BetterAuth\Core\TokenService;
use BetterAuth\Core\PasswordHasher;
use BetterAuth\Core\Config\AuthConfig;
use BetterAuth\Storage\Pdo\PdoUserRepository;
use BetterAuth\Storage\Pdo\PdoRefreshTokenRepository;

$pdo = new PDO('sqlite:auth.db');

$config   = AuthConfig::forApi('your-secret-key-min-32-chars');
$users    = new PdoUserRepository($pdo);
$refresh  = new PdoRefreshTokenRepository($pdo);
$hasher   = new PasswordHasher();
$signer   = new TokenService($config);

$tokenAuth = new TokenAuthManager($users, $refresh, $signer, $hasher, $config);
$auth      = new AuthManager($config, tokenAuth: $tokenAuth);

// Sign in
$result = $auth->signIn('user@example.com', 'SecureP@ss2024!');
// $result = ['user' => UserDto, 'access_token' => '...', 'refresh_token' => '...', 'expires_in' => 3600]

// Refresh tokens (atomic rotation)
$newTokens = $auth->refresh($result['refresh_token']);

Authentication modes

Mode Method Use case
MONOLITH Session + cookie Server-rendered apps (Symfony, Laravel)
API Paseto V4 + refresh token REST APIs, SPAs, mobile apps
HYBRID Both active Web frontend + mobile clients sharing the same backend
$config = AuthConfig::forMonolith($secret);  // Session mode
$config = AuthConfig::forApi($secret);       // Token mode
$config = AuthConfig::forHybrid($secret);    // Both

OAuth

use BetterAuth\Providers\OAuthProvider\OAuthManager;
use BetterAuth\Providers\OAuthProvider\GoogleProvider;
use BetterAuth\Providers\OAuthProvider\GitHubProvider;

$oauth = new OAuthManager($auth, $users, $accountLinks);

$oauth->addProvider(new GoogleProvider($clientId, $clientSecret, $redirectUri));
$oauth->addProvider(new GitHubProvider($clientId, $clientSecret, $redirectUri));

// Step 1 — redirect
$authUrl = $oauth->getAuthorizationUrl('google', ['scope' => 'email profile']);
// redirect user to $authUrl['url'], store $authUrl['state'] in session

// Step 2 — callback
$result = $oauth->handleCallback('google', $code, $redirectUri, $ip, $userAgent, $state, $expectedState);

Supported providers: Google, GitHub, Facebook, Microsoft, Discord, Twitter, Apple.

TOTP two-factor authentication

use BetterAuth\Providers\TotpProvider\TotpProvider;

$totp = new TotpProvider($totpStorage, $users);

// Enable 2FA
$setup = $totp->generateSecret($userId, 'MyApp');
// $setup = ['secret' => '...', 'uri' => 'otpauth://totp/...', 'backup_codes' => [...]]

// Verify setup
$totp->enableTotp($userId, $setup['secret'], $codeFromApp);

// Validate on login
$totp->verifyTotp($userId, $codeFromApp);
  • SHA-256 by default, SHA-1 fallback for legacy migration
  • 10 one-time backup codes (bcrypt-hashed)
  • 24h re-verification window

Magic links

use BetterAuth\Providers\MagicLinkProvider\MagicLinkProvider;

$magicLink = new MagicLinkProvider($storage, $auth, $users, $config);

// Send link
$magicLink->sendMagicLink('user@example.com', $emailSender, 'https://app.com/auth/verify');

// Verify (from callback)
$result = $magicLink->verifyMagicLink($token, $ip, $userAgent);
  • 10-minute token expiry
  • Rate-limited (3 requests / 5 minutes)
  • Auto-creates users (optional)
  • No user enumeration (always returns success)

OpenID Connect server

Act as an SSO provider for your own clients:

use BetterAuth\Providers\OidcProvider\OidcProvider;

$oidc = new OidcProvider($clients, $codes, $tokenManager, $users, $config);

// Authorization endpoint
$result = $oidc->authorize($clientId, $redirectUri, 'openid profile email', $state, $userId, $codeChallenge, 'S256');

// Token endpoint
$tokens = $oidc->token($grantType, $code, $redirectUri, $clientId, $clientSecret, $codeVerifier);

// Discovery
$config = $oidc->getDiscoveryConfig('https://auth.example.com');

Supports PKCE (S256 + plain), scopes (openid, profile, email, offline_access), and ID token claims.

Session security

Adaptive risk scoring on every request:

Signal Weight
Device type change (Desktop → Mobile) 30
OS family change 25
Country change 40
Impossible travel (< 1h + different country) 50
IP subnet change 15
Browser family change 15

Thresholds: 0–24 → allow, 25–49 → log, 50–74 → require reauth, 75+ → terminate session.

Multi-tenancy

// Organizations, teams, members, invitations
$org = $orgRepo->create('Acme Corp', 'acme-corp', $creatorId);
$teamRepo->create($org->getId(), 'Engineering', 'engineering');
$invitationRepo->create($org->getId(), 'new@example.com', 'member', $inviterId);

Plugin system

use BetterAuth\Core\Plugin\PluginManager;
use BetterAuth\Core\Plugin\PluginInterface;
use BetterAuth\Core\Plugin\PluginContext;

class AuditPlugin implements PluginInterface
{
    public function getName(): string { return 'audit'; }
    public function getVersion(): string { return '1.0.0'; }
    public function getDependencies(): array { return []; }
    public function isEnabled(): bool { return true; }
    public function getConfig(): array { return []; }

    public function install(PluginContext $context): void
    {
        $context->registerHook('user.logged_in', function (array $data) {
            // log login event
        });
    }
}

$plugins = new PluginManager();
$plugins->register(new AuditPlugin());
$plugins->loadAll();

Built-in hooks: user.created, user.logged_in, user.logged_out, token.created, session.created, oauth.linked.

Storage

All repositories are interface-based. The library ships with 20 PDO implementations that work with any SQL database (SQLite, MySQL, PostgreSQL, MariaDB).

Replace any repository by implementing the corresponding interface:

Interface Purpose
UserRepositoryInterface User CRUD + lookup by email/provider
SessionRepositoryInterface Session lifecycle
RefreshTokenRepositoryInterface Token rotation with atomic consume()
MagicLinkStorageInterface Passwordless tokens
TotpStorageInterface TOTP secrets + backup codes
OAuthClientRepositoryInterface OIDC client credentials
OrganizationRepositoryInterface Multi-tenant organizations

See src/Interfaces/ for the full list (28 interfaces).

Configuration

AuthConfig exposes all settings as constructor parameters with sensible defaults:

Setting Default
Session lifetime 7 days
Session absolute lifetime 30 days
Access token lifetime 1 hour
Refresh token lifetime 30 days
Rate limit max attempts 5
Rate limit decay 300 seconds
Cookie HttpOnly true
Cookie Secure true
Cookie SameSite Lax

Security

  • Tokens: Paseto V4 local encryption (XChaCha20-Poly1305), keys derived via HKDF
  • Passwords: Argon2id only, automatic rehash on login when cost parameters change
  • Rate limiting: per-key sliding window via PSR-6 cache (Redis, Memcached, APCu) with in-memory fallback
  • Anti-enumeration: timing-safe dummy password_verify() on user-not-found, silent success on unknown emails
  • CSRF: hash_equals state validation on OAuth callbacks
  • Refresh tokens: atomic rotation via consume() — prevents token reuse

Framework integration

This library provides the authentication core. Framework-specific bundles wire it into DI, routing, and middleware:

Framework Package
Symfony betterauth/symfony-bundle

License

MIT

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 3
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-16