DEV Community

Shubham Raturi
Shubham Raturi

Posted on

Google Grant Type in Laravel with Socialite, log in with Google API

Hi Everyone
To authenticate your app from the front end, follow these steps to build an API for Google login. The API will produce a bearer token, which you can check in the Laravel backend. and verify a user accordingly.
Step 1. Install Laravel Socialite package. and Laravel Passport
Step 2. Add this code to service.php

  'google' => [
    'api_key' => env('GOOGLE_API_KEY'),
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => env('GOOGLE_REDIRECT')
    ]
Enter fullscreen mode Exit fullscreen mode

setup the key form your google in your.env file
Step 3. Create a file in app/Grant/GoogleGrant.php or anywhere in your app.
Step 4. Copy paste or modify this code according to you.

<?php

namespace App\Grants;

use App\User;
use DateInterval;
use Google\Exception;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Laravel\Socialite\Facades\Socialite;
use League\OAuth2\Server\Grant\AbstractGrant;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;

class GoogleGrant extends AbstractGrant
{
    public function __construct(
        RefreshTokenRepositoryInterface $refreshTokenRepository
    ) {
        $this->refreshTokenRepository = $refreshTokenRepository;
    }

    /**
     * @inheritDoc
     * @return string
     */
    public function getIdentifier(): string
    {
        return 'google';
    }

    /**
     * @inheritDoc
     *
     * @param ServerRequestInterface $request
     * @param ResponseTypeInterface $responseType
     * @param DateInterval $accessTokenTTL
     * @return ResponseTypeInterface
     * @throws
     */
    public function respondToAccessTokenRequest(
        ServerRequestInterface $request,
        ResponseTypeInterface  $responseType,
        DateInterval $accessTokenTTL
    ): ResponseTypeInterface {
        $client = $this->validateClient($request);
        $scopes = $this->validateScopes($this->getRequestParameter('scope', $request));

        $user = $this->validateUser($request);

        // Finalize the requested scopes
        $scopes = $this->scopeRepository
            ->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getAuthIdentifier());

        // Issue and persist new tokens
        $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getAuthIdentifier(), $scopes);
        $refreshToken = $this->issueRefreshToken($accessToken);

        // Inject tokens into response
        $responseType->setAccessToken($accessToken);
        $responseType->setRefreshToken($refreshToken);

        return $responseType;
    }

    /**
     * Validate the request content and generate mapped user
     *
     * @param ServerRequestInterface $request
     * @return User
     * @throws GoogleLoginFailure
     * @throws ValidationException
     * @throws Exception
     */
    public function validateUser(ServerRequestInterface $request): User
    {
        $validator = Validator::make($request->getParsedBody(), [
            'access_token' => 'required'
        ]);

        $validator->validate();

        try {
            $user = Socialite::driver('google')->userFromToken($request->getParsedBody()['access_token']);
        } catch (ClientException $clientException) {
            throw new ClientException($clientException);
        }

        /**
         * @var $authUser User
         */
        try {
            return User::where('email', $user->email)->firstOrFail();
        } catch (ModelNotFoundException $ex) {
             abort(401, 'Custom message');
            throw new ModelNotFoundException('custom message');
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

step 5. Register this grant you AuthServiceProvide.php file. inside boot() method

  try {
            $this->app->make(AuthorizationServer::class)
                ->enableGrantType(
                    $this->googleGrant(),
                    Passport::tokensExpireIn()
                );
        } catch (LogicException $exception) {
            return;
        }
Enter fullscreen mode Exit fullscreen mode

Step 6. Make a method AuthServiceProvide.php

   /**
     * Returns GoogleGrant instance
     *
     * @return GoogleGrant
     * @throw
     * @throws Exception
     * @throws ContainerExceptionInterface
     */
    protected function googleGrant(): GoogleGrant
    {
        $this->app->singleton(GoogleGrant::class, function () {
            $googleGrant = new GoogleGrant($this->app->make(RefreshTokenRepository::class));
            $googleGrant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());
            return $googleGrant;
        });

        try {
            return $this->app->get(GoogleGrant::class);
        } catch (NotFoundExceptionInterface $e) {
            throw new Exception($e);
        }
    }
Enter fullscreen mode Exit fullscreen mode

Top comments (0)