HTML5 Zone is brought to you in partnership with:

Gonzalo Ayuso is a Web Architect with more than 10 year of experience in the web development, specialized in Open Source technologies. Experienced delivering scalable, secure and high performing web solutions to large scale enterprise clients. Blogs at gonzalo123.com. Gonzalo is a DZone MVB and is not an employee of DZone and has posted 54 posts at DZone. You can read more from them at their website. View Full User Profile

Google App Engine, PHP and Silex. Setting up a Login Provider

06.06.2013
| 4238 views |
  • submit to reddit

Last week Google announced the PHP support for Google App Engine (GAE). PHPStorm, the great IDE for PHP development, also announced support for Google App Engine PHP. Because of that now is time to hack a little bit with this new toy.

I’ve worked in a couple of projects with Google App Engine in the past (with Python). With PHP the process is almost the same. First we need to define our application in the app.yaml file. In our example we are going to redirect all requests to main.php, where our Silex application is defined.

application: silexgae
version: 1
runtime: php
api_version: 1
threadsafe: true
 
handlers:
- url: .*
  script: main.php

To build a simple Silex application over Google App Engine is pretty straightforward (more info here). Because of that we’re going to go a little further. We are going to use the log-in framework provided by GAE to log-in with our Goggle account within our Silex application. In fact we can use the standard OAuth authentication process but Google provides a simple way to use our gmail account.

Now we’re going to build a LoginProvider to make this process simpler. Our base Silex application will be the following one:

<?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();

Our LoginProvider is a simple Class that implements 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)
    {
    }
}

As you can see our Provider class proviedes us an instance of Gae\Auth class

<?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;
    }
}

And that’s all. Full code is available in my github account and you can also use composer to include this provider within your projects.


Published at DZone with permission of Gonzalo Ayuso, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)