Looking for a modern replacement for HybridAuth in your PHP projects? Whether you’ve outgrown it or found it too cumbersome, several excellent alternatives have emerged in recent years. Here’s a breakdown of your best options for handling social authentication in PHP applications.
League OAuth2 Client: The Community Favorite
The League’s OAuth 2.0 Client has become one of the most widely adopted solutions in the PHP ecosystem. It strikes an excellent balance between functionality and simplicity, handling the complex OAuth 2.0 flow without overwhelming your codebase.
What makes it stand out is its modular approach – the core package provides the foundation, while separate provider packages handle the specifics of each service. This means you only include what you need, keeping your dependencies lean.
1 2 3 |
composer require league/oauth2-client |
Quick Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Using the Google provider as an example $provider = new \League\OAuth2\Client\Provider\Google([ 'clientId' => 'your-client-id', 'clientSecret' => 'your-client-secret', 'redirectUri' => 'https://example.com/callback', 'scopes' => ['email', 'profile'], ]); // If we don't have an authorization code, get one if (!isset($_GET['code'])) { $authUrl = $provider->getAuthorizationUrl(); $_SESSION['oauth2state'] = $provider->getState(); header('Location: ' . $authUrl); exit; // Check state to prevent CSRF attacks } elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) { unset($_SESSION['oauth2state']); exit('Invalid state'); } else { // Get an access token using the authorization code $token = $provider->getAccessToken('authorization_code', [ 'code' => $_GET['code'] ]); // Get the user's details $user = $provider->getResourceOwner($token); echo 'Hello, ' . $user->getFirstName() . '!'; } |
The library is fully compliant with modern PHP standards (PSR-1, PSR-2, PSR-4, and PSR-7), and includes a GenericProvider class that works with any standard OAuth 2.0 provider right out of the box.
SocialConnect/auth: The Comprehensive Solution
If you need support for multiple authentication protocols beyond just OAuth2, SocialConnect/auth might be your best bet. This library handles OAuth1, OAuth2, OpenID, and OpenIDConnect standards with a unified API.
1 2 3 |
composer require socialconnect/auth |
Quick Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// Create a HTTP client $httpClient = new \SocialConnect\HttpClient\Curl(); // Create HTTP stack $httpStack = new \SocialConnect\Provider\HttpStack( $httpClient, new \SocialConnect\HttpClient\RequestFactory(), new \SocialConnect\HttpClient\StreamFactory() ); // Configure providers $configureProviders = [ 'redirectUri' => 'https://example.com/callback.php', 'provider' => [ 'facebook' => [ 'client_id' => 'your-app-id', 'client_secret' => 'your-app-secret' ], 'google' => [ 'client_id' => 'your-client-id', 'client_secret' => 'your-client-secret' ] ] ]; // Create service $service = new \SocialConnect\Auth\Service( $httpStack, new \SocialConnect\Provider\Session\Session(), $configureProviders ); // Get provider instance $provider = $service->getProvider('facebook'); // Get authorization URL $redirectUrl = $provider->makeAuthUrl(); // Redirect to authorization URL header('Location: ' . $redirectUrl); |
And in your callback script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// Get provider instance again $provider = $service->getProvider('facebook'); // Get access token $accessToken = $provider->getAccessTokenByRequestParameters($_GET); // Get user profile $user = $provider->getIdentity($accessToken); // Print user information echo 'ID: ' . $user->id . PHP_EOL; echo 'Name: ' . $user->name . PHP_EOL; echo 'Email: ' . $user->email . PHP_EOL; |
SocialConnect boasts support for over 30 providers including all the major players like Facebook, Google, Twitter, and GitHub. Its modular architecture follows the PSR-7, PSR-17, and PSR-18 standards, making it a great fit for modern PHP applications.
Firebase PHP-JWT: For JWT Specialists
Sometimes you don’t need a full social authentication suite – you just need to handle JWT (JSON Web Tokens). Firebase PHP-JWT is a specialized library that does exactly that, making it perfect for custom authentication systems or when working with JWTs from various providers.
1 2 3 |
composer require firebase/php-jwt |
Quick Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
use Firebase\JWT\JWT; use Firebase\JWT\Key; // Your secret key (keep this private!) $key = 'your-secret-key'; // Create token payload $payload = [ 'iss' => 'https://your-domain.com', // Issuer 'aud' => 'https://your-app.com', // Audience 'iat' => time(), // Issued at time 'exp' => time() + (60 * 60), // Expires in 1 hour 'user_id' => 123, // Custom user data 'email' => 'user@example.com' ]; // Generate JWT $jwt = JWT::encode($payload, $key, 'HS256'); echo "Generated token: " . $jwt . PHP_EOL; // Later, when you need to verify and decode the token: try { $decoded = JWT::decode($jwt, new Key($key, 'HS256')); // Access the claims echo "User ID: " . $decoded->user_id . PHP_EOL; echo "Email: " . $decoded->email . PHP_EOL; } catch (Exception $e) { echo "Token verification failed: " . $e->getMessage(); } |
It’s a lightweight package with minimal dependencies that complies with RFC 7519 (the JWT specification). If you’re building a custom authentication flow or need to integrate with a JWT-based system, this library provides just what you need without the overhead of a complete OAuth implementation.
OAuth2 Server PHP: When You Need to Be the Provider
For projects where you need to implement your own OAuth2 server rather than just connecting to external providers, Brent Shaffer’s OAuth2 Server PHP library is the go-to solution.
1 2 3 |
composer require bshaffer/oauth2-server-php |
Quick Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
// Database configuration $dsn = 'mysql:dbname=oauth2_server;host=localhost'; $username = 'root'; $password = ''; // Initialize OAuth storage and server $storage = new OAuth2\Storage\Pdo(['dsn' => $dsn, 'username' => $username, 'password' => $password]); $server = new OAuth2\Server($storage); // Add the "Client Credentials" grant type $server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage)); // Add the "Authorization Code" grant type $server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage)); // Handle a token request if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_SERVER['REQUEST_URI'] == '/token') { $server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send(); exit; } // Handle an authorization request if ($_SERVER['REQUEST_URI'] == '/authorize') { $request = OAuth2\Request::createFromGlobals(); $response = new OAuth2\Response(); // Validate the authorize request if (!$server->validateAuthorizeRequest($request, $response)) { $response->send(); exit; } // Display an authorization form if (!isset($_POST['authorized'])) { exit(' <form method="post"> Do you authorize the app to access your data? <input type="submit" name="authorized" value="yes"> <input type="submit" name="authorized" value="no"> </form> '); } // Process the authorization form $is_authorized = ($_POST['authorized'] === 'yes'); $server->handleAuthorizeRequest($request, $response, $is_authorized); $response->send(); } |
This library provides a complete OAuth2 server implementation that supports multiple grant types. It’s well-documented with practical examples and can be integrated with various PHP frameworks.
Why Move Away From HybridAuth?
HybridAuth served the PHP community well for many years since its inception in 2009. However, as PHP has evolved, developers have increasingly found HybridAuth challenging to work with for several reasons:
- Its architecture doesn’t always align with modern PHP practices
- Some find its API overly complex for simple use cases
- The codebase has accumulated technical debt over the years
- Integration with newer frameworks can be challenging
The alternatives discussed here generally offer more modern codebases with better PHP version support, clearer documentation, and more active development communities.
Making Your Choice
When selecting a replacement for HybridAuth, consider your specific requirements:
- If you need a well-supported, general-purpose OAuth2 client, League OAuth2 Client is hard to beat
- For multi-protocol support beyond just OAuth2, SocialConnect/auth offers the most comprehensive solution
- When working specifically with JWTs, Firebase PHP-JWT provides a focused tool
- If you need to implement your own OAuth2 server, OAuth2 Server PHP is purpose-built for the task
Each of these libraries represents the evolving approach to authentication in the PHP ecosystem, emphasizing modularity, standards compliance, and focused functionality.
FAQ
What are PHP Authentication Libraries?
What features should a modern PHP authentication library include?
What is the difference between OAuth and JWT?
What are some popular framework-agnostic PHP authentication libraries?
- Delight-im/PHP-Auth: A simple, lightweight, and secure authentication library
- Firebase/php-jwt: A straightforward library for working with JSON Web Tokens
- RobThree/TwoFactorAuth: A library specifically for two-factor authentication
- league/oauth2-client: A PHP package for OAuth 2.0 client integration
- multiOTP: An open-source strong authentication library with support for various token types
- adhocore/jwt: A minimalist yet powerful JWT library
How do I implement two-factor authentication (2FA) in PHP?
- Choose a 2FA library like RobThree/TwoFactorAuth or Sonata/GoogleAuthenticator
- Generate a secret key for each user
- Create a QR code containing the secret for users to scan with authenticator apps
- Store the secret securely in your database
- During login, after password verification, prompt for the time-based code
- Verify the entered code against the user’s stored secret
- Provide backup codes for recovery in case users lose access to their devices
Should I build my own authentication system or use an existing library?
What is the role of password hashing in PHP authentication?
How do JWT tokens work in PHP authentication?
- Creates a payload containing user information and permissions
- Adds standard claims like expiration time and issuer
- Signs the token with a secret key (using HMAC) or private key (using RSA/ECDSA)
- Returns the encoded token to the client
How can I implement social login with PHP?
- Choose an OAuth client library like league/oauth2-client or HybridAuth
- Register your application with each provider to obtain client IDs and secrets
- Configure the library with these credentials
- Create login buttons that redirect to the authentication URL
- Handle the callback from the provider
- Retrieve user information from the provider’s API
- Create or update a local user record linked to the social identity
What security considerations should I keep in mind when using authentication libraries?
- Always use HTTPS to prevent credential interception
- Keep libraries updated to address security vulnerabilities
- Implement proper session management with secure cookies
- Add rate limiting to prevent brute force attacks
- For JWT implementations, set appropriate short expiration times
- Never store sensitive data in JWT tokens
- Implement CSRF protection for authentication forms
- Consider adding multi-factor authentication
- Validate and sanitize all input, even from authenticated users
- Follow the principle of least privilege for authorization
How do I implement role-based access control (RBAC) with PHP authentication?
- Define roles and permissions in your database structure
- Associate users with roles (many-to-many relationship)
- Create middleware or helper functions to check permissions
- Secure routes and controller actions with permission checks
- Implement UI elements that adapt to user permissions
How do I handle token revocation in JWT-based authentication?
- Short expiration times: Limit the window of token validity
- Token blacklisting: Store revoked tokens in a database or cache
- Token versioning: Include a version number in tokens that can be invalidated
- Refresh token rotation: Issue new refresh tokens with each use
- Redis/Memcached for efficient blacklist storage
What PHP versions do modern authentication libraries support?
How can I test the security of my PHP authentication implementation?
- Run automated security scanning tools like OWASP ZAP or Burp Suite
- Perform penetration testing against your authentication endpoints
- Test for common vulnerabilities (SQL injection, XSS, CSRF)
- Verify password policies and hashing implementation
- Check session management for security issues
- Test rate limiting and account lockout mechanisms
- Conduct code reviews focused on security aspects
- Consider professional security audits for critical applications
Can I use multiple authentication libraries together?
How do I implement secure session management in PHP?
- Use HTTPS for all authenticated pages
- Set secure and HttpOnly flags on session cookies
- Configure proper session.cookie_samesite settings (Lax or Strict)
- Regenerate session IDs after login and privilege changes
- Set reasonable session timeouts
- Store sessions securely (Redis or database instead of files)
- Implement CSRF protection for all forms
- Consider IP binding for sensitive applications
- Add user agent validation for extra security
How do I implement OAuth 2.0 in my PHP application?
- Choose a library like league/oauth2-server (for servers) or league/oauth2-client (for clients)
- Configure OAuth entities (clients, scopes, grants)
- Implement authorization and token endpoints
- Set up resource server validation
- Secure all OAuth endpoints with HTTPS
- Implement proper token storage and validation
- Add refresh token capabilities
How do I choose between stateful and stateless authentication?
- Choose stateful when: security is paramount, you need immediate revocation capabilities, your application is monolithic, or you have heavy server-side rendering.
- Choose stateless when: you’re building microservices, need horizontal scaling without shared storage, developing mobile APIs, or implementing single-page applications.
What code sample can I use to implement basic PHP authentication?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// Initialize database connection $db = new \PDO('mysql:dbname=auth;host=localhost;charset=utf8mb4', 'username', 'password'); // Initialize auth component $auth = new \Delight\Auth\Auth($db); // Register a new user try { $userId = $auth->register('user@example.com', 'strong_password', 'John Doe'); echo 'User registered with ID: ' . $userId; } catch (\Delight\Auth\InvalidEmailException $e) { echo 'Invalid email address'; } catch (\Delight\Auth\InvalidPasswordException $e) { echo 'Invalid password'; } catch (\Delight\Auth\UserAlreadyExistsException $e) { echo 'User already exists'; } // Log in a user try { $auth->login('user@example.com', 'strong_password'); echo 'User is logged in'; } catch (\Delight\Auth\InvalidEmailException $e) { echo 'Invalid email address'; } catch (\Delight\Auth\InvalidPasswordException $e) { echo 'Invalid password'; } catch (\Delight\Auth\EmailNotVerifiedException $e) { echo 'Email not verified'; } catch (\Delight\Auth\TooManyRequestsException $e) { echo 'Too many requests'; } // Check if user is logged in if ($auth->isLoggedIn()) { echo 'User is logged in with ID: ' . $auth->getUserId(); } else { echo 'User is not logged in'; } // Log out $auth->logOut(); |
How can I implement JWT authentication in PHP?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
<?php // Include the JWT library require_once 'vendor/autoload.php'; use Firebase\JWT\JWT; use Firebase\JWT\Key; // Your secret key (keep this secure and not in your code in production) $key = 'your-secret-key'; // Creating a token after successful authentication function generateToken($userId, $email) { global $key; $payload = [ 'iss' => 'your-app-name', // Issuer 'aud' => 'your-app-clients', // Audience 'iat' => time(), // Issued at time 'nbf' => time(), // Not before time 'exp' => time() + 3600, // Expiration (1 hour) 'data' => [ // Custom data 'userId' => $userId, 'email' => $email ] ]; // Generate JWT return JWT::encode($payload, $key, 'HS256'); } // Verify and decode a token function validateToken($jwt) { global $key; try { // Decode JWT $decoded = JWT::decode($jwt, new Key($key, 'HS256')); return $decoded; } catch (Exception $e) { // Token is invalid return false; } } // Example usage for login endpoint if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['email'], $_POST['password'])) { $email = $_POST['email']; $password = $_POST['password']; // Verify credentials (replace with your authentication logic) if (verifyCredentials($email, $password)) { $userId = getUserId($email); // Get user ID // Generate token $token = generateToken($userId, $email); // Return token to client header('Content-Type: application/json'); echo json_encode(['token' => $token]); } else { http_response_code(401); echo json_encode(['error' => 'Invalid credentials']); } } // Example usage for protected endpoint if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_SERVER['HTTP_AUTHORIZATION'])) { // Get token from Authorization header $authHeader = $_SERVER['HTTP_AUTHORIZATION']; $token = str_replace('Bearer ', '', $authHeader); // Validate token $decoded = validateToken($token); if ($decoded) { // Token is valid, return protected data $userId = $decoded->data->userId; // Fetch user data $userData = getUserData($userId); header('Content-Type: application/json'); echo json_encode($userData); } else { // Invalid token http_response_code(401); echo json_encode(['error' => 'Invalid or expired token']); } } ?> |
How do I implement 2FA with TOTP in PHP?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php // Include the library require_once 'vendor/autoload.php'; use RobThree\Auth\TwoFactorAuth; // Create a new instance of the TwoFactorAuth class $tfa = new TwoFactorAuth('MyApp'); // Generate a new secret key for a user function generateSecretKey() { global $tfa; return $tfa->createSecret(); // Default 160 bits } // Get the QR code URL to display to the user function getQRCodeUrl($username, $secret) { global $tfa; return $tfa->getQRCodeImageAsDataUri($username, $secret); } // Verify the TOTP code provided by the user function verifyCode($secret, $code) { global $tfa; return $tfa->verifyCode($secret, $code); } // Example: Setting up 2FA for a user if ($_GET['action'] === 'setup') { // Generate a new secret key $secret = generateSecretKey(); // Store the secret in the database for the user // storeSecretForUser($userId, $secret); // Generate QR code URL $qrCodeUrl = getQRCodeUrl('user@example.com', $secret); // Display QR code to the user echo "<h1>Scan this QR code with your authenticator app:</h1>"; echo "<img src='{$qrCodeUrl}'>"; echo "<p>Or manually enter this code: {$secret}</p>"; } // Example: Verifying a code during login if ($_POST['action'] === 'verify') { $userId = $_POST['user_id']; $code = $_POST['code']; // Get the user's secret from the database $secret = getUserSecret($userId); // Replace with your function // Verify the code if (verifyCode($secret, $code)) { echo "Code is valid. Login successful!"; // Continue with login process } else { echo "Invalid code. Please try again."; } } ?> |