Installation:
composer require betterauth/symfony-bundle
php bin/console better-auth:install
config/packages/betterauth.yaml and creates a default User entity (extendable).Quick Configuration:
Edit betterauth.yaml to define:
better_auth:
providers:
google: true # Enable OAuth providers
features:
two_factor: true # Enable 2FA
session:
enabled: true # Session-based auth
First Use Case:
full for all features):
php bin/console better-auth:setup-features --preset=full --with-controllers --migrate
php bin/console debug:router | grep auth
/auth/login route (generated by --with-controllers).Authentication Modes:
better_auth.session for traditional web apps. Configure in betterauth.yaml:
session:
enabled: true
cookie_secure: true # HTTPS-only
better_auth.api for stateless APIs. Example:
api:
enabled: true
token_ttl: 3600 # 1-hour tokens
hybrid:
enabled: true
session_ttl: 86400
api_ttl: 3600
OAuth Integration:
betterauth.yaml:
providers:
google:
enabled: true
client_id: "%env(GOOGLE_CLIENT_ID)%"
client_secret: "%env(GOOGLE_CLIENT_SECRET)%"
github: true
/auth/oauth/{provider}) or call the service directly:
$auth = $this->get('better_auth.auth');
$user = $auth->authenticateWithOAuth('google', $request);
Two-Factor Authentication (2FA):
features:
two_factor:
enabled: true
method: totp # or 'backup_codes'
$auth->requireTwoFactor($user); // Redirects to 2FA flow
Token Rotation (API):
api:
token_rotation:
enabled: true
max_tokens: 3
$newToken = $auth->refreshToken($currentToken);
Multi-Tenant Support (Optional):
multi_tenant:
enabled: true
tenant_field: tenant_id # Field in User entity
$auth->setTenantContext($tenantId);
Custom User Entity:
Extend the default User entity (auto-generated at src/Entity/User.php):
// src/Entity/CustomUser.php
use BetterAuth\Symfony\Entity\User as BaseUser;
class CustomUser extends BaseUser {
#[ORM\Column]
private string $customField;
// Add getters/setters
}
Update betterauth.yaml:
user_entity: App\Entity\CustomUser
Event Listeners:
Subscribe to auth events (e.g., AuthSuccessEvent):
# config/services.yaml
services:
App\EventListener\AuthListener:
tags:
- { name: kernel.event_listener, event: better_auth.auth_success, method: onAuthSuccess }
API Platform Integration:
Secure API resources with the better_auth.api guard:
# config/packages/api_platform.yaml
api_platform:
formats:
jsonld:
mime_types: ['application/ld+json']
security:
resource_class: ~
guard: better_auth.api
Custom Routes:
Override default routes by defining your own controller and updating betterauth.yaml:
routes:
login: app_auth_login # Custom route name
Database Migrations:
--migrate with setup-features to avoid schema mismatches:
php bin/console better-auth:setup-features --preset=full --migrate
php bin/console doctrine:migrations:execute latest --em=better_auth
Token Storage:
better_auth_token table by default. Ensure this table exists or configure a custom storage:
api:
token_storage:
table: custom_token_table
Session vs. API Conflicts:
hybrid enabled. Configure explicitly:
session:
enabled: false # Disable if using API-only
OAuth Redirect URIs:
https://yourapp.com/auth/oauth/google/callback). Configure in betterauth.yaml:
providers:
google:
redirect_uri: "%env(AUTH_REDIRECT_URI)%"
2FA Backup Codes:
better_auth_2fa_backup_code table. Regenerate codes via:
$auth->regenerateBackupCodes($user);
Enable Verbose Logging:
Add to config/packages/monolog.yaml:
handlers:
better_auth:
type: stream
path: "%kernel.logs_dir%/better_auth.log"
level: debug
Common Errors:
user_entity in betterauth.yaml points to a valid Doctrine entity.client_id/client_secret and redirect URIs in provider configs.api.token_ttl is not set too low (default: 3600s).Testing:
Use the better-auth:test:auth command to simulate auth flows:
php bin/console better-auth:test:auth --provider=google --email=user@example.com
Custom Authenticators:
Implement BetterAuth\Symfony\Authenticator\AuthenticatorInterface:
class CustomAuthenticator implements AuthenticatorInterface {
public function authenticate(Request $request): ?User {
// Custom logic
}
}
Register in betterauth.yaml:
authenticators:
custom:
class: App\Auth\CustomAuthenticator
priority: 100
Custom Providers:
Extend BetterAuth\Symfony\Provider\OAuthProvider for new OAuth services:
class CustomOAuthProvider extends OAuthProvider {
protected function getAuthorizationUrl(): string {
// Custom OAuth flow
}
}
Configure in betterauth.yaml:
providers:
custom_provider:
class: App\Auth\CustomOAuthProvider
enabled: true
Token Handlers:
Override token logic by implementing BetterAuth\Symfony\Token\TokenHandlerInterface:
class CustomTokenHandler implements TokenHandlerInterface {
public function createToken(User $user): string {
// Custom token generation
}
}
Set in betterauth.yaml:
api:
token_handler: App\Auth\CustomTokenHandler
Multi-Tenant Logic:
Extend BetterAuth\Symfony\Tenant\TenantResolverInterface:
class CustomTenantResolver implements TenantResolverInterface {
public function resolve(Request $request): ?Tenant {
// Custom tenant resolution (e.g., from subdomain)
}
}
Configure:
multi_tenant:
resolver: App\Auth\CustomTenantResolver
How can I help you explore Laravel packages today?