Symfony security return 401 response instead of redirect

olanod picture olanod · Sep 6, 2013 · Viewed 10k times · Source

I'm writing an ajax application with ajax authentication and now I started using the symfony security component in silex to handle authentication/authorization.
Doing a simple test with a simple configuration, I go to a protected area by the firewall and the response I get is a redirection to the /login page but what I need in my app is a 401 response with possible additional information(in headers or json body) on how to login.

$app['security.firewalls'] = [
    'api' => [
        'pattern' => '^/api',
        'logout' => ['logout_path'=>'/auth/logout'],
        'users' => $app->share(function(Application $app) {
            return new MyUserProvider();
        })
    ]
];

EDIT: I got a hint but I'm not sure how to use it. Implementing an entry point with AuthenticationEntryPointInterface I can tell the api how to answer unauthenticated requests and give the user the instructions needed to authenticate. That could be my 401 response with login instructions.

Answer

panK picture panK · Jan 8, 2014

What you need is a AuthenticationEntryPoint handler. Simple example:

class AuthenticationEntryPoint implements AuthenticationEntryPointInterface {

/**
 * Starts the authentication scheme.
 *
 * @param Request $request The request that resulted in an AuthenticationException
 * @param AuthenticationException $authException The exception that started the authentication process
 *
 * @return Response
 */
public function start(Request $request, AuthenticationException $authException = null)
{
    $array = array('success' => false);
    $response = new Response(json_encode($array), 401);
    $response->headers->set('Content-Type', 'application/json');

    return $response;
}
}

Register class as a service in services.xml file:

<parameters>
    <parameter key="authentication_entry_point.class">YourNameSpace\AuthenticationEntryPoint</parameter>
</parameters>

<services>
    <service id="authentication_entry_point" class="%authentication_entry_point.class%"/>
</services>

and make a small change in security.yml file:

security:
  firewalls:
    somename:
      entry_point: authentication_entry_point