Mc 100's
Mc 100's

Reputation: 480

How to catch authentication errors in Silex?

I am developping a Rest API with Silex framework and I use SecurityServiceProvider. However, if a user sends bad credentials throw HTTP, I don't know how I can catch the error to display something like this :

{"status_code":401, "error_message":"Bad credentials"}

Below is a part of my code:

$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'default' => array(
            'pattern' => '^.*$',
            'stateless' => true,
            'http' => true,
            'users' => $app->share(function() use ($app) {
                return new App\Providers\UserProvider($app['db']);
            }),
        ),
    ),
));

// ...

$app->error(function (\Exception $e, $code) use ($app) {
    // This code is never executed in case of Bad credentials

    // ...

    return new JsonResponse($contentResponse, $statusCode);
});

Thank you in advance

EDIT

I've seen I can use $app['security.authentication.failure_handler.'.$name] but it is never handled in my case.

$app['security.authentication.failure_handler.default'] = $app->share(function ($app) {
     // This code is never executed
     return new MySuccessHandler();
});

Is it because of 'http' => true?

Upvotes: 1

Views: 542

Answers (3)

Mc 100's
Mc 100's

Reputation: 480

Because of the structure of my code, I decided to check the error in the after middleware, throw an exception and catch it with $app->error(...).

$app->after(function (Request $request, Response $response) {
    // If Unauthorized
    if ($response->getStatusCode() == 401)
        throw new Exception('Unauthorized'); // This exception will be handled by "$app->error(...)"
});


$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'default' => array(
            'pattern' => '^.*$',
            'stateless' => true,
            'http' => true,
            'users' => $app->share(function() use ($app) {
                return new App\Providers\UserProvider($app['db']);
            }),
        ),
    ),
));

// ...

$app->error(function (\Exception $e, $code) use ($app) {
    // ...
    return new JsonResponse($contentResponse, $statusCode);
});

Upvotes: 0

mTorres
mTorres

Reputation: 3590

Instead of using the generic error function you can listen to the security events emitted by the security component, specifically to the security.authentication.failure one.

To do so, you just need to call the on method:

<?php

use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent

//...
$app->on('security.authentication.failure', function(AuthenticationFailureEvent $event) {
  // you can do some checks if you want, but there's no need...

  return new JsonResponse($contentResponse, $statusCode);
});

Keep in mind that this is untested code.

Upvotes: 1

fucethebads
fucethebads

Reputation: 469

try it with

$app->error(function (\Exception $e, $code) use ($app) {
   // This code is never executed in case of Bad credentials

   if($e instanceof AuthenticationException){

       return new JsonResponse(["status_code"=>401, "error_message"=>"Bad credentials"], 401);
   }
   // ...

  return new JsonResponse($contentResponse, $statusCode);
});

Upvotes: 0

Related Questions