PHP code example of glueful / entrada

1. Go to this page and download the library: Download glueful/entrada library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

glueful / entrada example snippets


return [
    'enabled_providers' => ['google', 'facebook', 'github', 'apple'],
    'auto_register' => true, // auto-create user accounts for new social logins
    'sync_profile' => true,  // sync profile data from social providers

    // Account linking is governed by the verified-email gate (see "Account Linking" below),
    // not a config flag — a social identity is auto-linked to an existing local account only
    // when the provider asserts the email is verified.

    // Provider configurations
    'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
        'redirect_uri' => env('GOOGLE_REDIRECT_URI'),
    ],
    'facebook' => [
        'app_id' => env('FACEBOOK_APP_ID'),
        'app_secret' => env('FACEBOOK_APP_SECRET'),
        'redirect_uri' => env('FACEBOOK_REDIRECT_URI'),
        'api_version' => env('FACEBOOK_API_VERSION', 'v21.0'), // Graph API version
    ],
    'github' => [
        'client_id' => env('GITHUB_CLIENT_ID'),
        'client_secret' => env('GITHUB_CLIENT_SECRET'),
        'redirect_uri' => env('GITHUB_REDIRECT_URI'),
    ],
    'apple' => [
        'client_id' => env('APPLE_CLIENT_ID'),
        'client_secret' => env('APPLE_CLIENT_SECRET'),
        'team_id' => env('APPLE_TEAM_ID'),
        'key_id' => env('APPLE_KEY_ID'),
        'redirect_uri' => env('APPLE_REDIRECT_URI'),
    ],
];

return [
    'field_mapping' => [
        'social' => [
            'uuid' => ['id'],
            'email' => ['email'],
            'username' => ['username', 'login'],
            'first_name' => ['first_name', 'given_name'],
            'last_name' => ['last_name', 'family_name'],
            'photo_url' => ['photo_url', 'picture', 'avatar_url'],
            'email_verified' => ['verified_email', 'email_verified'],
        ],
    ],
    'storage' => [
        'users' => [
            'table' => 'users',
            'columns' => [
                'uuid' => 'uuid',
                'username' => 'username',
                'email' => 'email',
                'password' => 'password',
                'status' => 'status',
                'created_at' => 'created_at',
                'email_verified_at' => 'email_verified_at',
            ],
        ],
        'profiles' => [
            'table' => 'profiles',
            'columns' => [
                'uuid' => 'uuid',
                'user_uuid' => 'user_uuid',
                'first_name' => 'first_name',
                'last_name' => 'last_name',
                'photo_url' => 'photo_url',
            ],
        ],
    ],
];

return [
    'post_registration' => [
        'enabled' => false, // opt-in
        // Invokable class-string (recommended) or callable
        // Signature: (string $userUuid, array $socialData, ApplicationContext $context): void
        'handler' => App\Auth\SocialRegistrationHandler::class,
    ],
];



namespace App\Controllers;

use Symfony\Component\HttpFoundation\Request;
use Glueful\Http\Response;
use Glueful\Extensions\Entrada\Services\SocialAuthService;
use Glueful\Extensions\Entrada\Providers\GoogleAuthProvider;

class AuthController
{
    private SocialAuthService $socialAuth;

    public function __construct()
    {
        $this->socialAuth = container()->get(SocialAuthService::class);
    }

    /**
     * Handle social login initiation
     */
    public function socialLogin(Request $request, string $provider)
    {
        try {
            // Get the provider instance
            $authProvider = $this->socialAuth->getProvider($provider);

            if (!$authProvider) {
                return Response::error("Provider {$provider} not supported", 400);
            }

            // Initiate OAuth flow
            return $authProvider->initiateOAuthFlow($request);

        } catch (\Exception $e) {
            return Response::error("Failed to initiate login: " . $e->getMessage(), 500);
        }
    }

    /**
     * Handle OAuth callback
     */
    public function socialCallback(Request $request, string $provider)
    {
        try {
            $authProvider = $this->socialAuth->getProvider($provider);

            if (!$authProvider) {
                return Response::error("Provider {$provider} not supported", 400);
            }

            // Handle the OAuth callback
            $userData = $authProvider->handleCallback($request);

            if (!$userData) {
                return Response::error($authProvider->getError() ?? "Authentication failed", 401);
            }

            // Generate application tokens
            $tokens = $authProvider->generateTokens($userData);

            return Response::success([
                'access_token' => $tokens['access_token'],
                'refresh_token' => $tokens['refresh_token'],
                'user' => $userData
            ], 'Login successful');

        } catch (\Exception $e) {
            return Response::error("Authentication failed: " . $e->getMessage(), 401);
        }
    }
}



use Glueful\Extensions\Entrada\Providers\GoogleAuthProvider;
use Glueful\Extensions\Entrada\Providers\FacebookAuthProvider;
use Glueful\Extensions\Entrada\Providers\GithubAuthProvider;
use Glueful\Extensions\Entrada\Providers\AppleAuthProvider;

// Get a specific provider
$googleProvider = container()->get(GoogleAuthProvider::class);
$facebookProvider = container()->get(FacebookAuthProvider::class);
$githubProvider = container()->get(GithubAuthProvider::class);
$appleProvider = container()->get(AppleAuthProvider::class);

// Verify a native mobile token. Google/Apple take the ID token; Facebook/GitHub take the
// access token. Each provider's verifyNativeToken() takes a single string argument.
$userData = $googleProvider->verifyNativeToken($idToken);

if ($userData) {
    // User authenticated successfully
    $tokens = $googleProvider->generateTokens($userData);
    // Use tokens for your application
}



use Glueful\Extensions\Entrada\Services\SocialAccountService;

class UserSocialAccountController
{
    private SocialAccountService $socialAccountService;

    public function __construct()
    {
        $this->socialAccountService = container()->get(SocialAccountService::class);
    }

    /**
     * Link a social account to existing user
     */
    public function linkSocialAccount(string $userUuid, array $socialData): bool
    {
        return $this->socialAccountService->linkAccountToUser(
            $userUuid,
            $socialData['provider'],
            $socialData['social_id'],
            $socialData['profile_data']
        );
    }

    /**
     * Get all social accounts for a user
     */
    public function getUserSocialAccounts(string $userUuid): array
    {
        return $this->socialAccountService->getUserSocialAccounts($userUuid);
    }

    /**
     * Unlink a social account
     */
    public function unlinkSocialAccount(string $userUuid, string $provider): bool
    {
        return $this->socialAccountService->unlinkAccount($userUuid, $provider);
    }

    /**
     * Check if user has a specific social account
     */
    public function hasSocialAccount(string $userUuid, string $provider): bool
    {
        $accounts = $this->socialAccountService->getUserSocialAccounts($userUuid);
        return collect($accounts)->where('provider', $provider)->isNotEmpty();
    }
}



namespace App\Services;

use Glueful\Extensions\Entrada\Services\SocialAuthService;
use Glueful\Auth\TokenManager;

class CustomAuthService
{
    private SocialAuthService $socialAuth;

    public function __construct()
    {
        $this->socialAuth = container()->get(SocialAuthService::class);
    }

    /**
     * Authenticate user with social provider tokens
     */
    public function authenticateWithSocial(string $provider, array $tokens): ?array
    {
        $authProvider = $this->socialAuth->getProvider($provider);

        if (!$authProvider) {
            throw new \InvalidArgumentException("Unknown provider: {$provider}");
        }

        // Verify tokens based on provider. verifyNativeToken() takes one argument: the ID token
        // for Google/Apple, the access token for Facebook/GitHub.
        switch ($provider) {
            case 'google':
            case 'apple':
                $userData = $authProvider->verifyNativeToken($tokens['id_token'] ?? '');
                break;

            case 'facebook':
            case 'github':
                $userData = $authProvider->verifyNativeToken($tokens['access_token'] ?? '');
                break;

            default:
                $userData = null;
        }

        if (!$userData) {
            return null;
        }

        // Generate application JWT tokens
        return TokenManager::generateTokenPair($userData);
    }

    /**
     * Get or create user from social data
     */
    public function findOrCreateSocialUser(array $socialData): array
    {
        return $this->socialAuth->findOrCreateUser($socialData);
    }
}



namespace App\Middleware;

use Symfony\Component\HttpFoundation\Request;
use Glueful\Http\Response;
use Glueful\Extensions\Entrada\Services\SocialAuthService;

class SocialAuthMiddleware
{
    private SocialAuthService $socialAuth;

    public function __construct()
    {
        $this->socialAuth = container()->get(SocialAuthService::class);
    }

    public function handle(Request $request, \Closure $next)
    {
        // Check for social auth token in header
        $authHeader = $request->headers->get('Authorization');

        if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) {
            return $next($request);
        }

        $token = substr($authHeader, 7);

        // Validate token with social providers
        foreach ($this->socialAuth->getEnabledProviders() as $provider) {
            $authProvider = $this->socialAuth->getProvider($provider);

            if ($authProvider->canHandleToken($token)) {
                if ($authProvider->validateToken($token)) {
                    // Token is valid, continue
                    return $next($request);
                }

                // Token is invalid
                return Response::error('Invalid social auth token', 401);
            }
        }

        // Not a social auth token, continue
        return $next($request);
    }
}



namespace App\Listeners;

use Glueful\Extensions\Entrada\Events\SocialLoginEvent;
use Glueful\Extensions\Entrada\Events\SocialAccountLinkedEvent;

class SocialAuthEventListener
{
    /**
     * Handle social login event
     */
    public function onSocialLogin(SocialLoginEvent $event): void
    {
        $user = $event->getUser();
        $provider = $event->getProvider();
        $socialData = $event->getSocialData();

        // Log the social login
        logger()->info("User {$user['uuid']} logged in via {$provider}", [
            'provider' => $provider,
            'social_id' => $socialData['id'] ?? null,
            'email' => $user['email'] ?? null
        ]);

        // Update last login timestamp
        db()->table('users')
            ->where('uuid', $user['uuid'])
            ->update(['last_login_at' => now()]);

        // Sync profile data if needed
        if (config('sauth.sync_profile')) {
            $this->syncUserProfile($user['uuid'], $socialData);
        }
    }

    /**
     * Handle social account linked event
     */
    public function onSocialAccountLinked(SocialAccountLinkedEvent $event): void
    {
        $userUuid = $event->getUserUuid();
        $provider = $event->getProvider();

        // Send notification to user
        notification()->send($userUuid, [
            'type' => 'social_account_linked',
            'message' => "Your {$provider} account has been linked successfully",
            'provider' => $provider
        ]);
    }

    private function syncUserProfile(string $userUuid, array $socialData): void
    {
        $updates = [];

        if (!empty($socialData['name'])) {
            $updates['name'] = $socialData['name'];
        }

        if (!empty($socialData['picture'])) {
            $updates['avatar_url'] = $socialData['picture'];
        }

        if (!empty($updates)) {
            db()->table('users')
                ->where('uuid', $userUuid)
                ->update($updates);
        }
    }
}

// For native mobile apps, POST tokens directly
POST /auth/social/google
Content-Type: application/json

{
    "id_token": "google-id-token-here",
    "access_token": "google-access-token-here"
}

// Response
{
    "success": true,
    "message": "Authentication successful",
    "data": {
        "access_token": "your-app-jwt-token",
        "refresh_token": "your-app-refresh-token",
        "user": {
            "uuid": "user-uuid",
            "email": "[email protected]",
            "name": "User Name"
        },
        "social_account": {
            "uuid": "social-account-uuid",
            "provider": "google",
            "social_id": "google-user-id"
        }
    }
}

// Web OAuth Flow
GET  /auth/social/{provider}              // Initiate OAuth flow
GET  /auth/social/{provider}/callback     // OAuth callback handler

// Native App Flow
POST /auth/social/{provider}              // Direct token verification

// Apple-specific (supports both GET and POST)
GET  /auth/social/apple                   // Apple OAuth initiation
POST /auth/social/apple/callback          // Apple callback (POST only)

// Social account management
GET    /user/social-accounts              // List connected social accounts
DELETE /user/social-accounts/{uuid}       // Unlink social account

// User profile operations
GET    /user/profile                      // Get user profile
PUT    /user/profile                      // Update user profile

// User creation process
1. Verify social provider token/ID token
2. Extract user profile information
3. Check if user exists by email
4. Create new user if not exists
5. Create social account association
6. Generate application JWT tokens
7. Return authentication response

// Account linking process
1. User authenticates with social provider
2. System finds existing user by email
3. If the provider reports the email as VERIFIED → link the social account
   (if UNVERIFIED → reject with 409; the user must link manually after signing in)
4. Updates profile if sync_profile is enabled
5. Returns authentication tokens

// Synced profile fields
- Name (first_name, last_name, display_name)
- Email address
- Profile photo URL
- Social provider ID
- Additional provider-specific data

// Uses Glueful's TokenManager for secure JWT tokens
$tokens = $this->tokenManager->generateTokenPair($userUuid, [
    'social_provider' => $provider,
    'social_id' => $socialId
]);

// Supports both OAuth flow and ID token verification
- OAuth 2.0 with OpenID Connect
- ID token validation with Google's public keys
- Access token verification via Google API
- Profile data from Google People API

// Facebook Graph API integration
- OAuth 2.0 flow
- Access token validation via Facebook Graph API
- Profile data extraction
- Long-lived token generation

// GitHub OAuth implementation
- OAuth 2.0 with tHub API
- Verified email resolved authoritatively from /user/emails (primary + verified)

// Advanced Apple Sign In implementation
- OAuth 2.0 with Sign In with Apple
- ID-token signature verification via Apple's JWKS (RS256 / openssl)
- ES256 private-key JWT generation for client secrets (DER via ASN1Parser)
- First-time user data handling

// Resolve a provider and check basic availability
$google = container()->get(Glueful\Extensions\Entrada\Providers\GoogleAuthProvider::class);
// e.g., dump config/redirect URI or perform a light request

// Link existing users to social accounts
$existingUser = $userRepository->findByEmail($socialEmail);
if ($existingUser) {
    $socialAccountService->linkAccountToUser(
        $existingUser->getUuid(),
        $provider,
        $socialId,
        $profileData
    );
}

use Glueful\Extensions\Entrada\Providers\AbstractSocialProvider;

class CustomProvider extends AbstractSocialProvider
{
    public function getAuthorizationUrl(array $scopes = []): string
    {
        // Implement OAuth authorization URL generation
    }
    
    public function validateToken(string $token): array
    {
        // Implement token validation logic
    }
    
    public function getUserProfile(string $accessToken): array
    {
        // Implement user profile retrieval
    }
}
bash
php glueful extensions:list
php glueful extensions:info entrada
bash
composer extensions:enable entrada
bash
php glueful migrate run
bash
php glueful generate:json doc
bash
php glueful extensions:list
php glueful extensions:info entrada
php glueful extensions:diagnose