Graph-IT

Login 2

This example extends the Login-example, by:

This example is not meant to show a security feature, but is meant to show soem basic handling of cookies using giwt.

LoginResponseHandler

The new LoginResponseHandler sets cookies once the user was authenticated.

<?php

namespace Graphit\Examples;

class LoginResponseHandler implements \Graphit\Core\ResponseHandlerInterface
{
  public function __construct(\Graphit\Core\Kernel $kernel)
  {
    $this->kernel = $kernel;
  }

  public function handleResponse(\Graphit\Core\Response $response, \Graphit\Core\Request $request)
  {
    $authenticated = $this->kernel['authenticated'];
    if (!$authenticated) {
      return $response;
    }
    $secret = $this->kernel['cookie'][$authenticated];
    $cookies = [
      'login' => ['value' => $authenticated, 'expire' => time() + (24 * 60 * 60 * 20)], // 30 days
      'secret' => ['value' => $secret, 'expire' => time() + (24 * 60 * 60 * 20)] // 30 days
    ];
    return $response->setCookies($cookies);
  }
}

In case the user wasn't authenticated, no cookies will be set. On the other hand if the user was successfully authenticated a 'login'- and a 'secret'-cookie are set.

So since future request might contain our cookies we need to adjust our LoginRequestHandler-class.

LoginRequestHandler

Inside the LoginRequestHandler we adjust the handleRequest-method to not ask for credentials when the incoming request contains valid cookies. (Username and secret match the expected values.)

public function handleRequest(\Graphit\Core\Request $request)
{
  $cookie = $request->cookie();
  if($cookie && isset($cookie['login']) && isset($cookie['secret'])) {
    $username = $cookie['login'];
    if ($this->kernel['cookie'][$username] == $cookie['secret']) {
      $request->vars()->set('authenticated', $username);
      return;
    }
  }

  $username = $request->getUser();
  $password = $request->getPassword();
  $validator = new LoginValidator($this->kernel);
  if ($validator->validate($username, $password)) {
    $request->vars()->set('authenticated', $username);
  } else {
    return $this->requestCredentials($request);
  }
}

Next, we adjust the HelloRequestHandler to use the new LoginResponseHandler.

HelloRequestHandler

Inside the HelloRequestHandler we add the LoginResponseHandler to the ChainRequestHandler.

public function __construct(\Graphit\Core\Kernel $kernel)
{
  $this->kernel = $kernel;

  $this->handler = new \Graphit\Core\ChainRequestHandler();

  $default = $kernel['defaultLocale'] ?: 'de';
  $possible = $kernel['possibleLocales'] ?: ['de'];
  $handler = new \Graphit\Core\LocaleRequestHandler($default, $possible);
  $this->handler->addRequestHandler($handler);

  $router = $kernel['router'];
  $handler = new \Graphit\Core\RouterRequestHandler($router);
  $this->handler->addRequestHandler($handler);

  $handler = new \Graphit\Core\PossibleLocaleRequestHandler();
  $this->handler->addRequestHandler($handler);

  $handler = new LoginRequestHandler($kernel);
  $this->handler->addRequestHandler($handler);

  $handler = new \Graphit\Core\ControllerRequestHandler($kernel);
  $this->handler->addRequestHandler($handler);

  $handler = new LoginResponseHandler($kernel);
  $this->handler->addResponseHandler($handler);
}

Since we write cookies which contain a secret and also check for this secret inside the LoginRequestHandler, we now adjust the service.json to hold those secrets. Normally one would read these from a Database or another trusted source, but for this example we keep it minimal.

services.json

We just add a "cookie"-array at the top of the to the services.json which holds the 'secret' we expect as cookie for a specific user.

"cookie": {
  "username": "a secret",
  "test": "secret"
},