Monday 13 January 2020

OPTIONS request gets a "401 Unauthorized" response

I crafted an API with Symfony 4 that uses a custom token verification. I tested the API on Postman and everything works perfectly, now I want to use the API using jQuery and fetch all the data , but in the browser, I'm facing CORS issues like below:

Access to XMLHttpRequest at 'http://localhost:8000/api/reports' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

Here is my server-side API:

I've implemented a CORSEventSubscriber to allow the CORS like below :

class CORSSubscriber implements EventSubscriberInterface
{

/**
 * @var TokenStorageInterface
 */
private $tokenStorage;

public function __construct(TokenStorageInterface $tokenStorage)
{
    $this->tokenStorage = $tokenStorage;
}
public function onKernelResponse(FilterResponseEvent $event)
{
    $responseHeaders = $event->getResponse()->headers;
    $responseHeaders->set('Access-Control-Allow-Origin', '*');
    $responseHeaders->set('Access-Control-Allow-Headers', 'x-auth-token, content-type');
    $responseHeaders->set('Access-Control-Allow-Methods', 'POST, GET');
}

/**
 * @inheritDoc
 */
public static function getSubscribedEvents()
{
    return [
        KernelEvents::RESPONSE => 'onKernelResponse',
    ];
}

This is the action that I'm calling in the controller:

/**
 * @Route("/api/reports",name="reports",methods={"GET","OPTIONS"})
 * @param Request $request
 * @return Response
 * @throws  Exception
 */
function getReports(Request $request){

return new JsonResponse('test', Response::HTTP_UNAUTHORIZED);

}

I tried consuming the API like this

    <script>
    $(document).ready(function(){

        authenticate().then(function (data) {
           // the promise resolve the token and data.token output the correct value
           $.ajax({
               url:'http://localhost:8000/api/reports',
               type: 'GET',
                headers: {'X-Auth-Token' : data.token },
               success: function (data) {
                   //append data to your app
                   console.log(data);
               }
           })
        })
    });
    function authenticate() {
        let data={
            "username": "test",
            "password": "test"
        };
        return new Promise(function(resolve, reject) {
            $.ajax({
                url:'http://localhost:8000/api/auth/check',
                type:'POST',
                data:JSON.stringify(data),
                dataType:'Json',
                success: function (data) {
                    console.log(data);
                resolve(data);
                },
                error:function () {
                }
            })
        });
    }


</script>

I added this to debug closely the issue and i found out that this function only executes for POST when there's a token method like OPTIONS it doesn't execute

public function onKernelRequest(GetResponseEvent $event)
{
    $this->logger->info($event->getRequest()->getRealMethod());
}


from OPTIONS request gets a "401 Unauthorized" response

No comments:

Post a Comment