Back-End

6 dez, 2013

Google App Engine, PHP e Silex – Configurando um provedor de login

Publicidade

Em maio deste ano, o Google anunciou suporte PHP para o Google App Engine (GAE). PHPStorm, uma ótima IDE para desenvolvimento PHP, também anunciou suporte para o Google App Engine PHP. Por conta disso, é hora de hackear alguns bits com os “novos brinquedinhos”.

Eu já trabalhei em alguns projetos com o Google App Engine no passado (com Python). Com PHP, o processo é quase o mesmo. Primeiro precisamos definir nosso aplicativo no arquivo app.yaml. Em nosso exemplo, iremos redirecionar todas as requisições para o main.php, onde o nosso aplicativo Silex está definido

application: silexgae
version: 1
runtime: php
api_version: 1
threadsafe: true

handlers:
- url: .*
  script: main.php

Criar um simples aplicativo Silex no Google App Engine é bastante objetivo (mais informações aqui). Por causa disso, iremos um pouco adiante. Usaremos framework de login fornecido pelo GAE para logarmos com a nossa conta do Google em nosso aplicativo Silex. Na verdade, podemos usar o processo de autenticação Oauth padrão, mas o Google forneceu uma forma simples de utilizar nossa conta do Gmail.

Agora faremos um LoginProvider para tornar o processo mais simples. Nosso aplicativo Silex de base será o seguinte:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Silex\Application;
use Gae\LoginProvider;
use Gae\Auth;

$app = new Application();
$app->register(new LoginProvider(), array(
    'auth.onlogin.callback.url' => '/private',
    'auth.onlogout.callback.url' => '/loggedOut',
));

/** @var Auth $auth */
$auth = $app['gae.auth']();

$app->get('/', function () use ($app, $auth) {
    return $auth->isLogged() ?
        $app->redirect("/private") :
        "<a href='" . $auth->getLoginUrl() . "'>login</a>";
});

$app->get('/private', function () use ($app, $auth) {
    return $auth->isLogged() ?
        "Hello " . $auth->getUser()->getNickname() .
          " <a href='" . $auth->getLogoutUrl() . "'>logout</a>" :
        $auth->getRedirectToLogin();
});

$app->get('/loggedOut', function () use ($app) {
    return "Thank you!";
});

$app->run();

Nosso LoginProvider é uma Class simples que implementa Silex\ServiceProviderInterface

<?php
namespace Gae;

require_once 'google/appengine/api/users/UserService.php';

use google\appengine\api\users\UserService;
use Gae\Auth;
use Silex\Application;
use Silex\ServiceProviderInterface;

class LoginProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['gae.auth'] = $app->protect(function () use ($app) {
            return new Auth($app, UserService::getCurrentUser());
        });
    }

    public function boot(Application $app)
    {
    }
}

Como podemos ver, nossa classe Provider nos fornece uma instância da classe Gae\Auth

<?php
namespace Gae;

require_once 'google/appengine/api/users/UserService.php';

use google\appengine\api\users\User;
use google\appengine\api\users\UserService;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Silex\Application;

class Auth
{
    private $user = null;
    private $loginUrl;
    private $logoutUrl;
    private $logged;

    public function __construct(Application $app, User $user=null)
    {
        $this->user = $user;

        if (is_null($user)) {
            $this->loginUrl = UserService::createLoginUrl($app['auth.onlogin.callback.url']);
            $this->logged = false;
        } else {
            $this->logged = true;
            $this->logoutUrl = UserService::createLogoutUrl($app['auth.onlogout.callback.url']);
        }
    }

    /**
     * @return RedirectResponse
     */
    public function getRedirectToLogin()
    {
        return new RedirectResponse($this->getLoginUrl());
    }
    /**
     * @return boolean
     */
    public function isLogged()
    {
        return $this->logged;
    }

    /**
     * @return string
     */
    public function getLoginUrl()
    {
        return $this->loginUrl;
    }

    /**
     * @return string
     */
    public function getLogoutUrl()
    {
        return $this->logoutUrl;
    }

    /**
     * @return \google\appengine\api\users\User|null
     */
    public function getUser()
    {
        return $this->user;
    }
}

E é só isso. O código completo está disponível na minha conta do github, e você também pode utilizar o composer para incluir este serviço dentro dos seus projetos.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://gonzalo123.com/2013/05/20/google-app-engine-php-and-silex-setting-up-a-login-provider/