82

I'm currently trying to read the authorization header in a PHP script that I'm calling with a POST request. The Authorization header is populated with a token. It seems the Authorization header is somehow removed before it arrives at my PHP script. I'm executing the post request with Postman (Chrome addon) and I enabled CORS in my PHP script. I don't have access to the apache server directly.

HTTP Request:

Accept:*/*
Accept-Encoding:gzip,deflate
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,ja;q=0.2
Authorization:Bearer mytoken
Cache-Control:no-cache
Connection:keep-alive
Content-Length:32
Content-Type:text/plain;charset=UTF-8
Host:www.myhost.com
Origin:chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
 User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)       
 Chrome/38.0.2125.104 Safari/537.36

PHP script:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type,      Accept");
header("Content-Type: application/json");

$headers = getallheaders();
echo $headers['Authorization'];

The above script outputs '' (= nothing).

igorsantos07
  • 4,149
  • 4
  • 40
  • 59
jimmy
  • 3,951
  • 3
  • 19
  • 27

11 Answers11

231

After quite some time a found a solution to this problem. Somehow the Authorization header was stripped away. By adding the following lines in my .htaccess, I was able to get it to work.

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
akinuri
  • 9,179
  • 10
  • 57
  • 92
jimmy
  • 3,951
  • 3
  • 19
  • 27
  • 2
    I had the same problem when trying to use HTTP Basic Authorization with my REST api on Php 5.4 and Apache. I had modified the .htaccess file to support RewriteEngine On for the rest api and similarly all my request headers seemed to be there except authorization when I query them in PHP. Your fix is correct, thanks! – Deemoe Dec 16 '14 at 20:04
  • 1
    This fixes the same problem occurring when using CodeIgniter 3 using the codeigniter-restserver library when custom routes are being used. Interestingly enough it also creates two headers, `HTTP_AUTHORIZATION` and `REDIRECT_HTTP_AUTHORIZATION`, both with an identical value. – TJ L Mar 15 '17 at 19:12
  • Awesome answer, works perfectly. If you have other conditions in your .htaccess file, I've placed this at the top (first). – Calin Jul 10 '17 at 12:52
  • 13
    4 years later on PHP 7.2 and this is still relevant! Awesome fix! – spice Dec 28 '18 at 21:48
  • 1
    glad I found it at the first hit in google, saved me headache... works perfectly – Joey Feb 19 '19 at 07:39
  • 9
    I was going to upvote this... then I realized I already had, the last time I had this problem. – Jerry Mar 22 '19 at 23:06
  • 5
    Excellent solution... Now can someone explain what is going on? This only happens on some servers. Why does it get stripped out? – Jahmic May 02 '20 at 09:30
  • 9
    I was curious about this too; apparently Apache does not pass the `Authorization` header by default for security reasons. Instead, you must manually enable it (circa 2.4.13) with the `CGIPassAuth` directive, valid in `.htaccess` or in directory configs. This functionality has applied to previous versions as well, but I'm not able to find documentation explaining this for those older versions. – patricknelson Aug 12 '20 at 00:59
  • 1
    This is still relevant in the year 2021 for the version PHP 7.4. – Pradip Shenolkar Mar 24 '21 at 11:46
  • in IIS , how i can make that ? could you please help me ? – Quentin Merlin Jun 11 '21 at 15:03
69

I had first to add this to my machines Apache config file:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

On Linux in /etc/apache2/apache2.conf

On Mac using Homebrew in /usr/local/etc/httpd/httpd.conf

On Mac with "native" Apache: /private/etc/apache2/httpd.conf or: /etc/apache2/httpd.conf

Adding this to .htaccess didn't work for any reason:

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
FullStack Alex
  • 1,371
  • 12
  • 21
  • 2
    Thank you, your response help me – viniciussvl Aug 01 '19 at 08:19
  • 10
    You can add `SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1` in .htaccess. That worked for me. – Mohit Sep 14 '19 at 08:08
  • 2
    It worked for me. I'm using aws lightsail so.. I added the code in /opt/bitnami/apache2/conf/httpd.conf. In addition I think restarting server is necessary. sudo /opt/bitnami/ctlscript.sh restart apache. – mazend Feb 08 '20 at 02:43
  • @Mohit For me this had to be in the Apache config file (or virtualhost config) – i.e. it did *not* work when added to the .htaccess file. I don't know why this is because I have `AllowOverride ALL` set – Ade Mar 15 '20 at 20:43
  • I was having errors with Laravel Passport, the server returned Unauthenticated. With this response I was able to fix it. Lifesaver! – David Copano Jiménez May 09 '20 at 16:48
  • This solved the issue on a Bitnami wordpress server too. The Apache2 config is put in the file opt/bitnami/apache2/conf/httpd.conf I added `SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1` and it got rid of the error. Thank you – Hevski Mar 11 '21 at 22:16
  • Thank you! Updating .htaccess alone did not do the trick, but adding that to my httpd.conf file did the trick after a restart. – prafferty Apr 24 '21 at 18:01
  • How to do that in iIS ? – Quentin Merlin Jun 13 '21 at 20:19
  • For brevity, this works within `` elements in the httpd-vhosts.conf file as well. FYI, local apache server on windows – soulshined Dec 13 '21 at 02:18
  • Thank you sooooo much. This answer definitely saved my day. – Nelson Katale May 10 '22 at 15:32
10

if you use WHM + CPanel + PHP and if your show result like this here missing Authorization

Array
(
    [Host] => domain.com
    [Connection] => keep-alive
    [Cache-Control] => max-age=0
    [Upgrade-Insecure-Requests] => 1
    [User-Agent] => Mozilla/5.0
    [Accept] => text/html,application/xhtml+xml
    [Sec-Fetch-Site] => none
    [Sec-Fetch-Mode] => navigate
    [Sec-Fetch-User] => ?1
    [Sec-Fetch-Dest] => document
    [Accept-Encoding] => gzip, deflate, br
    [Accept-Language] => en
)

Now just flow these steps.

Step 1: .htaccess file add

RewriteEngine On

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Step 2: add in your PHP file like index.php

1. getallheaders();

2. apache_request_headers();
 
3. $SERVER['REDIRECT_HTTP_AUTHENTICATION'];

You can use anyone.

Step 3: go to WHM Panel and flow this navigation

Home » Service Configuration » Apache Configuration » Include Editor » Pre VirtualHost Include » All Version 

Add this line

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

and Restart Apache Server (if not restart the server then not working properly)

Step 4: My Result Show

Array
(
    [Authorization] => hhRbRZtypswriasabjn3xHT+9Fe9sWHjejhID/YTmookDdrN7WyTUULWwCvmMRiW0RaDRtozLVnvjnl
    [User-Agent] => PostmanRuntime/7.26.8
    [Accept] => */*
    [Cache-Control] => no-cache
    [Host] => domain.com
    [Accept-Encoding] => gzip, deflate, br
    [Connection] => keep-alive
    [Content-Type] => application/x-www-form-urlencoded
    [Content-Length] => 3
    [X-Https] => 1
)

this work has done. after you flow these steps and again show the same error please comment here

Purvesh Tejani
  • 101
  • 1
  • 2
8

Below array holds request headers, that may be missing in $_SERVER variable

$headers = apache_request_headers();

(Especially true for 'HTTP_X_REQUESTED_WITH' ajax header, which will be found this way as: $headers['X_REQUESTED_WITH']

Grigoreas P.
  • 2,312
  • 23
  • 19
  • Although this is correct, I can see the correct header in there (and this is much better than using the .htaccess solution!) the key in the array are CASE SENSITIVE. So you can't easily access them without tweaking the array first... – Alexis Wilke Nov 03 '18 at 23:52
  • 1
    See this answer about transforming the keys of an array to lower or upper case: https://stackoverflow.com/questions/4240001/php-array-keys-case-insensitive-lookup#answer-4240019 – Alexis Wilke Nov 04 '18 at 00:09
8

The most elegant solution to this problem is enabling this directive in .htaccess.

CGIPassAuth On

This directive is part of the apache core and doesn't require any special module to be enabled. See the documentation here.

The problem happens when using php-fpm with apache (as oposed to using the php module directly in apache).

This is a security measure that prevents sensitive data to be transfered from apache to php through fcgi.

This solution fixes not only $_SERVER["HTTP_AUTHORIZATION"] but also $_SERVER["PHP_AUTH_USER"], used in "Basic" authentication as described in php's official documentation.

In my opinion, all other solutions that involve setting the HTTP_AUTHORIZATION environment variable through SetEnvIf or with RewriteRules are workarounds and don't solve the root problem.

I tested this solution in 2021 with php7.4.

santiago arizti
  • 3,555
  • 1
  • 32
  • 43
3

I want to extend the previous answers with a specific case.

I'm using LAMP (bitnami) on AWS (Lightsail). My code is written using CodeIgniter 3. So I already have a .htacess file and this is what's in it:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>

I wanted to implement jimmy's solution:

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

But how? Everyone seems to "suggest" something, but not be specific about it. Having multiple rewrite conditions/rules seemed problematic. I'm not an Apache guru, so I had to experiment. I managed to get it working in the following way:

<IfModule mod_rewrite.c>
    RewriteEngine On
    
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>

Now, there's an "HTTP_AUTHORIZATION" key in the $_SERVER array.

Edit: There seems to be also another key "REDIRECT_HTTP_AUTHORIZATION" with the same value.

akinuri
  • 9,179
  • 10
  • 57
  • 92
1

This solution (mentioned above) worked for me after tricking httpd.conf file:

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

To make this work, httpd.conf had to include these directives in my Alias section:

AllowOverride All
Options FollowSymLinks

The first one is too open (yes, I know), but .htaccess is totally avoided if you put AllowOverride None.

Also, RewriteRule is avoided too is you don't use FollowSymLinks or so (based in Apache docs)

hgc2002
  • 168
  • 1
  • 9
1

In my case if found it in $_SERVER["REDIRECT_HTTP_AUTHORIZATION"]

Pavel Popov
  • 91
  • 1
  • 3
0

I don't know why my php 5.4.45 running on NGINX was refusing any custom header containing underscores:

ACCEPTED: CURLOPT_HTTPHEADER => array('Authorization: 123456')

REFUSED: CURLOPT_HTTPHEADER => array('my_Authorization: 123456')

I hope it can help someone. Cheers

luciomonter
  • 318
  • 5
  • 7
0

We were able to address this same issue by switching to use the php-fpm (FastCGI) instead of using mod_php for apache. The header is passed unmolested to FastCGI but seems to be stripped by mod_php.

nullability
  • 10,189
  • 3
  • 45
  • 60
0

For me, enabling PHP-FPM on PHP 8.1 fixed the issue, without any amendment in htaccess.