Skip to content

Instantly share code, notes, and snippets.

@tarlepp
Last active February 7, 2017 21:37
Show Gist options
  • Save tarlepp/0e2c779695b2aa96271c to your computer and use it in GitHub Desktop.
Save tarlepp/0e2c779695b2aa96271c to your computer and use it in GitHub Desktop.
<?php
namespace App\Listeners;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class AjaxAuthenticationListener
{
/**
* Handles security related exceptions.
*
* @param GetResponseForExceptionEvent $event An GetResponseForExceptionEvent instance
*/
public function onCoreException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
$request = $event->getRequest();
// It never hits here
if ($request->isXmlHttpRequest()) {
if ($exception instanceof AuthenticationException || $exception instanceof AccessDeniedException || $exception instanceof AuthenticationCredentialsNotFoundException) {
$responseData = array('status' => 401, 'msg' => 'User Not Authenticated');
$response = new JsonResponse();
$response->setData($responseData);
$response->setStatusCode($responseData['status']);
$event->setResponse($response);
}
}
}
}
[2016-02-11 21:45:44] myapp.INFO: Populated the TokenStorage with an anonymous Token. [] []
[2016-02-11 21:45:44] myapp.INFO: > POST /backend/auth/login [] []
[2016-02-11 21:45:44] myapp.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\UsernameNotFoundException(code: 0): User 'admdin' not found. at /home/wunder/projects/backend-silex/src/App/Providers/UserProvider.php:66)"} []
[2016-02-11 21:45:44] myapp.DEBUG: Calling Authentication entry point. [] []
[2016-02-11 21:45:44] myapp.INFO: < 302 http://wunder.sytes.net:6969/backend/login [] []
[2016-02-11 21:45:44] myapp.ERROR: Symfony\Component\HttpKernel\Exception\NotFoundHttpException: No route found for "GET /login" (uncaught exception) at /home/wunder/projects/backend-silex/vendor/symfony/http-kernel/EventListener/RouterListener.php line 176 {"exception":"[object] (Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException(code: 0): No route found for \"GET /login\" at /home/wunder/projects/backend-silex/vendor/symfony/http-kernel/EventListener/RouterListener.php:176, Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException(code: 0): No routes found for \"/login\". at /home/wunder/projects/backend-silex/vendor/symfony/routing/Matcher/UrlMatcher.php:98)"} []
<?php
/**
* /src/App/Application.php
*
* @author TLe, Tarmo Leppänen <[email protected]>
*/
namespace App;
// Silex application
use App\Components\Swagger\SwaggerServiceProvider;
use App\Listeners\AjaxAuthenticationListener;
use App\Providers\SecurityServiceProvider as ApplicationSecurityServiceProvider;
use Silex\Application as SilexApplication;
// Silex specified providers
use Silex\Provider\DoctrineServiceProvider;
use Silex\Provider\MonologServiceProvider;
use Silex\Provider\SecurityJWTServiceProvider;
use Silex\Provider\SecurityServiceProvider;
use Silex\Provider\ValidatorServiceProvider;
// 3rd party providers
use Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider;
use JDesrosiers\Silex\Provider\CorsServiceProvider;
use Sorien\Provider\PimpleDumpProvider;
use M1\Vars\Provider\Silex\VarsServiceProvider;
// Application specified providers
use App\Providers\UserProvider;
use App\Services\Loader;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
/**
* Class Application
*
* Main application class that is used to run application. Class bootstraps application all providers, mount routes,
* etc.
*
* @category Core
* @package App
* @author TLe, Tarmo Leppänen <[email protected]>
*/
class Application extends SilexApplication
{
/**
* Project root directory, determined via this file
*
* @var string
*/
private $rootDir;
/**
* Current environment which is used to run application.
*
* @var string
*/
private $env;
/**
* Application constructor.
*
* @param string $env
*/
public function __construct($env)
{
// Set private vars
$this->rootDir = __DIR__ . '/../../';
$this->env = $env;
// Construct Silex application
parent::__construct();
// Create application configuration
$this->applicationConfig();
// Register all necessary providers
$this->applicationRegister();
// Configure application firewall
$this->applicationFirewall();
// Load services
$this->loadServices();
// Attach application mount points
$this->applicationMount();
// Attach CORS to application
$this->after($this['cors']);
}
/**
* Getter method for 'rootDir' property.
*
* @return string
*/
public function getRootDir()
{
return $this->rootDir;
}
/**
* Getter method for 'env' property.
*
* @return string
*/
public function getEnv()
{
return $this->env;
}
/**
* Application configuration.
*
* @return void
*/
private function applicationConfig()
{
// Register configuration provider
$this->register(
new VarsServiceProvider($this->rootDir . 'resources/config/' . $this->env . '/config.yml'),
[
'vars.options' => [
'cache' => true,
'cache_path' => $this->rootDir . 'var',
'cache_expire' => $this->env === 'dev' ? 0 : 0,
'replacements' => [
'rootDir' => $this->rootDir,
'env' => $this->env,
],
],
]
);
// Set application level values
$this['debug'] = $this['vars']->get('debug');
$this['security.jwt'] = $this['vars']->get('security.jwt');
$this['pimpledump.output_dir'] = $this['vars']->get('pimpledump.output_dir');
$this['services'] = $this['vars']->get('services');
return;
}
/**
* Method to register all specified providers for application.
*
* @return void
*/
private function applicationRegister()
{
$this['dispatcher']->addListener("kernel.exception", function(GetResponseForExceptionEvent $event) {
if (
($event->getException()->getCode() == '403') ||
($event->getException()->getCode() == '404')
) {
$request = $event->getRequest();
if ($request->isXmlHttpRequest()) {
$event->setResponse(new Response("Access Denied", 403));
}
}
});
// Register all providers for application
$this->register(new ValidatorServiceProvider());
$this->register(new SecurityServiceProvider());
$this->register(new ApplicationSecurityServiceProvider());
$this->register(new SecurityJWTServiceProvider());
$this->register(new PimpleDumpProvider());
$this->register(new MonologServiceProvider(), $this['vars']->get('monolog'));
$this->register(new DoctrineServiceProvider(), $this['vars']->get('database'));
$this->register(new DoctrineOrmServiceProvider(), $this['vars']->get('orm'));
$this->register(new CorsServiceProvider(), $this['vars']->get('cors'));
$this->register(new SwaggerServiceProvider(), $this['vars']->get('swagger'));
}
/**
* Method to setup application firewall.
*
* @see http://silex.sensiolabs.org/doc/providers/security.html
*
* @return array
*/
private function applicationFirewall()
{
$entityManager = $this['orm.em'];
$app = $this;
// Set provider for application users
$this['users'] = function() use ($app, $entityManager) {
return new UserProvider($entityManager);
};
// Security Firewalls configuration
$this['security.firewalls'] = [
// Root route
'root' => [
'pattern' => '^/$',
'anonymous' => true,
],
// Login route
'login' => [
'pattern' => '^/auth/login$',
'anonymous' => true,
],
// Pimple dump
'pimpleDump' => [
'pattern' => '^/_dump$',
'anonymous' => true,
],
// CORS preflight requests
'cors-preflight' => array(
'pattern' => $this['cors_preflight_request_matcher'],
),
// API docs are also anonymous
'docs' => [
'pattern' => '^/api',
'anonymous' => true,
],
// And all other routes
'secured' => [
'pattern' => '^.*$',
'users' => $this['users'],
'jwt' => [
'use_forward' => true,
'require_previous_session' => false,
'stateless' => true,
],
],
];
}
/**
* Method to attach main mount point to be handled via ControllerProvider.
*
* @return void
*/
private function applicationMount()
{
// Register all application routes
$this->mount('', new ControllerProvider());
}
/**
* Load shared services.
*
* @return void
*/
private function loadServices()
{
$loader = new Loader($this);
$loader->bindServicesIntoContainer();
}
}
var_dump($this['services']);
array(1) {
["ajax.listener"]=>
array(2) {
["class"]=>
string(39) "App\Listeners\AjaxAuthenticationListener"
["tags"]=>
array(1) {
[0]=>
array(4) {
["name"]=>
string(21) "kernel.event_listener"
["event"]=>
string(16) "kernel.exception"
["method"]=>
string(15) "onCoreException"
["priority"]=>
int(1000)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment