47

I'm trying to implement a custom authentication provider in Symfony 2. I'm sending a test request using Fiddler and printing all headers server side; well, Authorization header is missing.

Am i doing something wrong?

GET /RESTfulBackend/web/index.php HTTP/1.1
Authorization: FID 44CF9590006BF252F707:jZNOcbfWmD/
Host: localhost
User-Agent: Fiddler
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3

Listener just prints the headers and quits:

class HMACListener implements ListenerInterface
{
    private $securityContext;

    private $authenticationManager;

    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        print_r($request->headers->all()); 
        die();
     }
}

Response is missing Authorization header:

Array
(
    [host] => Array
        (
            [0] => localhost
        )
    [user-agent] => Array
        (
            [0] => Fiddler
        )
    [accept] => Array
        (
            [0] => text/html,application/xhtml+xml,application/xml
        )
    [accept-language] => Array
        (
            [0] => it-it,it;q=0.8,en-us;q=0.5,en;q=0.3
        )
)
  • possible duplicate of [Authorization header missing in django rest\_framework, is apache to blame?](http://stackoverflow.com/questions/13387516/authorization-header-missing-in-django-rest-framework-is-apache-to-blame) – Wilt Apr 20 '15 at 12:34
  • Check also the answers [here in this similar question](http://stackoverflow.com/q/13387516/1697459) – Wilt Jan 13 '16 at 08:33

9 Answers9

64

You must add this code to a virtualhost tag

It will not work if you put it in a Directory tag.

    RewriteEngine On
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
DazBaldwin
  • 4,125
  • 3
  • 39
  • 43
33

Akambi's answer didn't work for me, but found this answer in the php website:

"Workaround for missing Authorization header under CGI/FastCGI Apache:

SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0

Now PHP should automatically declare $_SERVER[PHP_AUTH_*] variables if the client sends the Authorization header."

Thanks derkontrollfreak+9hy5l!

matt
  • 430
  • 4
  • 4
  • Thank you. Do you know why the header is not sent? – anna Sep 21 '16 at 10:26
  • Applied this fix but it's still not responding to 401 header in my script. – Twisty Jan 18 '17 at 23:46
  • This is the only solution works, `RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]`'s one is not working – tom10271 Feb 15 '17 at 09:01
  • This worked for me by adding it in the VirtualHost config file. It should work fine in .htaccess too, just make sure there is no proxies, container etc in between before the request reaches your app. – Omar Tariq Oct 22 '19 at 12:03
20

The verified solution worked for me at the time to get the Authorization header through. However, it generated an empty Authorization header when there was none in the incoming request. This is how I solved it:

RewriteEngine On
RewriteCond %{HTTP:Authorization} .+
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
mezod
  • 2,313
  • 3
  • 21
  • 31
11

I had the same problem when writing a public API with custom Authorization header. To fix the HeaderBag I used a listener:

namespace My\Project\Frontend\EventListener;

use Symfony\Component\HttpFoundation\HeaderBag;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;

/**
 * Listener for the REQUEST event. Patches the HeaderBag because the
 * "Authorization" header is not included in $_SERVER
 */
class AuthenticationHeaderListener
{
    /**
     * Handles REQUEST event
     *
     * @param GetResponseEvent $event the event
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        $this->fixAuthHeader($event->getRequest()->headers);
    }
    /**
     * PHP does not include HTTP_AUTHORIZATION in the $_SERVER array, so this header is missing.
     * We retrieve it from apache_request_headers()
     *
     * @param HeaderBag $headers
     */
    protected function fixAuthHeader(HeaderBag $headers)
    {
        if (!$headers->has('Authorization') && function_exists('apache_request_headers')) {
            $all = apache_request_headers();
            if (isset($all['Authorization'])) {
                $headers->set('Authorization', $all['Authorization']);
            }
        }
    }
}

and bound it to kernel.request in the service definition:

services:
  fix_authentication_header_listener:
    class: My\Project\Frontend\EventListener\AuthenticationHeaderListener
    tags:
      - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 255 }
Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
7

Authorization header is used for http basic authentication which is discarded by apache if not in valid format. Try using another name.

Mun Mun Das
  • 14,992
  • 2
  • 44
  • 43
  • Thanks. How for example Amazon S3 can use it? http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html –  Aug 16 '12 at 18:03
  • Well if you see Apache implementation it expects the request token to be base_64 encoded string and on server side it base64_decodes the string and set `PHP_AUTH_USER` and `PHP_AUTH_PW` server variable. As you see the implementation is server specific. So Amazon S3 web servers have implemented the scheme differently. – Mun Mun Das Aug 16 '12 at 18:23
  • What you would suggest then? using apache_request_headers() (apache specific) or using a custom header? –  Aug 17 '12 at 06:54
  • You can make an apache module to make your authentication scheme compliance with http basic authentication. For example check [this](http://httpd.apache.org/docs/trunk/mod/mod_authnz_ldap.html) module. Or you can use custom header e.g `X-FID-Authorization`. – Mun Mun Das Aug 17 '12 at 07:16
  • 2
    AFAIK Apache will accept any format Authorization header. It is PHP which discards anything else than valid Basic or Digest header. – Mika Tuupola Oct 23 '14 at 20:12
  • It seems that we can use the header name ''Php-Auth-Digest" as an alternative to "Authorization". see Symfony\Component\HttpFoundation\ServerBag::getHeaders() – Artur Cichosz Oct 25 '16 at 06:22
7

Another option that worked for Apache 2.4 when other options did not was to set the CGIPassAuth option in the relevant <Directory> context, like this:

CGIPassAuth On

According to the documentation, it is available since Apache 2.4.13.

likeitlikeit
  • 5,563
  • 5
  • 42
  • 56
  • 1
    This is what worked for me. Otherwise the Authorization header was simply missing from both getallheaders and $_SERVER – G_Gus Aug 02 '17 at 13:53
0

Another solution is to change your PHP handler to run PHP as Apache Module instead of as CGI application.

Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Not a good solution though because it will be slower as module than as CGI. Also there are problems with the rights in cache and logs folder during the development. – Jorj Dec 10 '15 at 10:39
  • @Jorj "problems" can you be more specific? I bet it is just a matter of configuration. It is a working solution. Never said it was the "best". That is a matter of opinion.. – Wilt Dec 10 '15 at 11:07
  • Sure, here is what happens: as a developer on a unix box you would create files under your user, right ? Then you would launch some commands from your console which would create files in cache and logs folder. If PHP is configured as module in Apache it will run with Apache's user, that is "www" or "nobody" or something similar. As a result it will try to overwrite the files created by you in cache and logs folders and it will throw errors because they belongs to another owner. Of course, there are workarounds to this too, but still is an additional headache. – Jorj Dec 11 '15 at 12:59
0

We should authorise this header "Authorization" on the server side,

it's also simply done with nelmioCorsBundle nelmio_cors: defaults: allow_credentials: false allow_origin: [] allow_headers: [] allow_methods: [] expose_headers: [] max_age: 0 hosts: [] origin_regex: false forced_allow_origin_value: ~ paths: '^/api/': allow_origin: ['*'] allow_headers: ['Authorization']

ghaliano
  • 396
  • 6
  • 10
0

If you're using apache and you already have a header override set in your .htaccess file but you're still getting 401 errors

RewriteCond %{HTTP:Authorization} .+
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]

Then make sure you enable config overrides in your VirtualHost. Set the value to All for the AllowOverride parameter in the Directory tag

<VirtualHost *:80>
    ...
    <Directory /var/www/***>
        AllowOverride All
        ...
    </Directory> 

</VirtualHost> 

Don't forget to restart apache after making changes

emrdev
  • 2,155
  • 3
  • 9
  • 15