NotionCommotion Posted October 3, 2016 Share Posted October 3, 2016 I am using a header for authentication of an api. If the header is not included, I send back a 401 code. $key = $request->getHeaderLine('X-GreenBean-Key'); if (empty($key)) { $error=\MyApp\ErrorResponse::missingKey(); return $response->withJson($error[0], $error[1]); } Problem is my server is being hit twice, the first time without the header, and thus the client never attempts the second request. The request is cross-domain, and thus I added the header name to Access-Control-Allow-Headers. Below is my test scripts documenting what appears to be happening. What am I doing wrong??? ajax.html <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Testing</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.js" type="text/javascript"></script> <script type="text/javascript"> $(function(){ $.ajax({ type:'GET', url:'http://example.com/ajax', headers: {"X-Greenbean-Key": "main_key"} }) }); </script> </head> <body></body> </html> ajax.php <?php require __DIR__.'/../vendor/autoload.php'; $logger = new \Monolog\Logger('my_logger'); $file_handler = new \Monolog\Handler\StreamHandler("../logs/testing.log"); $logger->pushHandler($file_handler); $logger->addInfo('Server Hit. Header: '.$_SERVER['HTTP_X_GREENBEAN_KEY']); testing.log (for Monolog) [2016-10-03 05:25:14] my_logger.INFO: Server Hit. Header: [] [] [2016-10-03 05:25:14] my_logger.INFO: Server Hit. Header: main_key [] [] log (apache) 192.168.1.1 - - [03/Oct/2016:05:25:14 -0700] "OPTIONS /ajax.php HTTP/1.1" 200 134 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 FirePHP/0.7.4" 192.168.1.1 - - [03/Oct/2016:05:25:14 -0700] "GET /ajax.php HTTP/1.1" 200 - "http://dd.badobe.com/ajax.html" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 FirePHP/0.7.4" httpd.conf <VirtualHost *:80> ServerName example.com DocumentRoot /var/www/src/public <Directory "/var/www/src/public"> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all RewriteEngine On Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" Header set Access-Control-Allow-Headers "X-Greenbean-Key, Origin, X-Requested-With, Content-Type, Accept" </Directory> </VirtualHost> Quote Link to comment https://forums.phpfreaks.com/topic/302273-troubles-with-header-for-authentication-cors-and-options/ Share on other sites More sharing options...
Solution Jacques1 Posted October 3, 2016 Solution Share Posted October 3, 2016 (edited) When you set custom HTTP headers, the client has to preflight to determine whether the actual request will be valid. This is the OPTIONS request you're seeing in the log. When you respond with a 401 code, the client assumes that the test has failed and will not send the actual request. To fix the problem, exclude OPTIONS requests from the header check so that the client will get a 200 response. Edited October 3, 2016 by Jacques1 1 Quote Link to comment https://forums.phpfreaks.com/topic/302273-troubles-with-header-for-authentication-cors-and-options/#findComment-1537987 Share on other sites More sharing options...
NotionCommotion Posted October 3, 2016 Author Share Posted October 3, 2016 (edited) Thank you! Should an OPTIONS request always positively? For instance, should every PHP script which responds to HTTP requests have the following few lines? <?php if ($_SERVER['REQUEST_METHOD']==='OPTIONS') { http_response_code(200); exit; } // remaining code goes here.... EDIT. Or should apache/etc or php.ini be set up so it never gets to PHP? Edited October 3, 2016 by NotionCommotion Quote Link to comment https://forums.phpfreaks.com/topic/302273-troubles-with-header-for-authentication-cors-and-options/#findComment-1537989 Share on other sites More sharing options...
Jacques1 Posted October 3, 2016 Share Posted October 3, 2016 (edited) If the script uses CORS, yes. But you still need the CORS headers in the response. Edited October 3, 2016 by Jacques1 Quote Link to comment https://forums.phpfreaks.com/topic/302273-troubles-with-header-for-authentication-cors-and-options/#findComment-1537990 Share on other sites More sharing options...
NotionCommotion Posted October 3, 2016 Author Share Posted October 3, 2016 If the script uses CORS, yes. But you still need the CORS headers in the response. CORS headers? What are they? Quote Link to comment https://forums.phpfreaks.com/topic/302273-troubles-with-header-for-authentication-cors-and-options/#findComment-1537992 Share on other sites More sharing options...
Jacques1 Posted October 3, 2016 Share Posted October 3, 2016 When the client makes a preflight OPTIONS request, you need to respond with Access-Control-Allow-Origin, Access-Control-Request-Method (only if you're using more than GET and POST) and Access-Control-Allow-Headers. When the client makes the actual request, you need to respond with Access-Control-Allow-Origin. Right now, it seems you allow CORS for absolute everything. That's a very bad idea, because the same-origin policy exists for a reason. You need to allow CORS for individual resources (hence the name). So if a particular PHP script should be accessible from other domains, that's when you enable CORS for this script. Probably the most natural approach is to set the headers within the script. If you insist on doing it with the webserver, you need to apply the headers on a per-resource basis. In any case, skipping script execution in case of an OPTIONS request is extremely confusing, so, no, I wouldn't do that. Quote Link to comment https://forums.phpfreaks.com/topic/302273-troubles-with-header-for-authentication-cors-and-options/#findComment-1537999 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.