62

I've managed to extend TokenAuthentication and I have a working model when using the request session to store my tokens, however when I attempt to pass Authorization as a header parameter as described here, I noticed that my Responses come back without the META variable HTTP_AUTHORIZATION. I also noticed that if I pass "Authorization2" as a header parameter that it is visible in the request:

{
    '_content_type': '', 
    'accepted_media_type': 'application/json', 
    '_request': <WSGIRequest
        path:/api/test_auth/,
        GET:<QueryDict: {}>,
        POST:<QueryDict: {}>,
        COOKIES:{
            'MOD_AUTH_CAS_S': 'ba90237b5b6a15017f8ca1d5ef0b95c1',
            'csrftoken': 'VswgfoOGHQmbWpCXksGUycj94XlwBwMh',
            'sessionid': 'de1f3a8eee48730dd34f6b4d41caa210'
        },
        META:{
           'DOCUMENT_ROOT': '/etc/apache2/htdocs',
           'GATEWAY_INTERFACE': 'CGI/1.1',
           'HTTPS': '1',
           'HTTP_ACCEPT': '*/*',
           'HTTP_ACCEPT_CHARSET': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
           'HTTP_ACCEPT_ENCODING': 'gzip,deflate,sdch',
           'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.8',
           'HTTP_AUTHORIZATION2': 'Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4c',
           ...

My first guess is that the authorization header is being removed by apache, and I have read a few S/O questions that state that apache will throw out the value if it does not match basic authorization and authenticate, but I have no idea how to allow the Authorization header to 'pass through' to Django and the WSGIRequest. Does anyone know how to solve this problem?

I also use mod_auth_cas and mod_proxy, if that changes anything..

Wilt
  • 33,082
  • 11
  • 129
  • 176
steve-gregory
  • 7,036
  • 7
  • 34
  • 47

4 Answers4

77

If you are using Apache and mod_wsgi, then I found the easy solution to this in the official Django REST framework website

Apache mod_wsgi specific configuration

Note that if deploying to Apache using mod_wsgi, the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.

If you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the WSGIPassAuthorization directive in the appropriate context and setting it to 'On'.

# this can go in either server config, virtual host, directory or .htaccess 
WSGIPassAuthorization On
Community
  • 1
  • 1
Steven
  • 2,118
  • 1
  • 20
  • 22
  • 2
    Thank you for the update. This applies to Tastypie non-session based authentication as well. – garromark Nov 03 '13 at 03:46
  • This is NOT always the solution. If did deploy Django in Apache with fcgid (see: https://docs.djangoproject.com/en/1.8/howto/deployment/fastcgi/#apache-shared-hosting), you must tell mod_fcgid to pass "Authentication" header by adding (usually in vhost.cof): FcgidPassHeader Authorization – serfer2 May 18 '15 at 18:06
  • I have tried this, but it doesn't seem to work. I added it to my sites-enabled .conf file and restarted apache, but to no avail. i keep getting the redirect for authentication. any ideas? – lemonpro Oct 23 '15 at 00:00
  • Thanks - this solution is also not Django-specific, it worked for me with Apache2 + uwsgi + web.py – Sergey Kudriavtsev Jun 04 '16 at 21:22
  • 1
    I have a case where a mobile app sending Authorization Header gets striped only on some certain request, I wonder why! – Karan Kumar Oct 07 '16 at 20:06
  • I was start to blaming bitnami because some bad configuration until I found your answer, thank you very much – fnaquira Jul 23 '19 at 21:18
  • Delete the cookies or use private mode to check if the solution did fix your problems. – user2672299 Nov 13 '19 at 18:43
37

Sorry to answer my own question minutes after asking it. But it turns out it was apache2 after all! After crawling the webs and looking through a few search results I found this in a comment:

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

Adding the above lines to my conf file seemed to solve all of my problems! Hopefully this helps users down the road!

steve-gregory
  • 7,036
  • 7
  • 34
  • 47
  • There is an open ticket to document this apache behavior: https://github.com/tomchristie/django-rest-framework/issues/488 If anyone can shed some light on eg. Nginx behaviour in this regard that'd also be helpful. – Tom Christie Jan 03 '13 at 22:33
  • @Tom Christie, this is how you do it with nginx: proxy_no_cache $http_pragma $http_authorization; proxy_cache_bypass $http_pragma $http_authorization; proxy_set_header HTTP_AUTHORIZATION $http_authorization; – Salvatore Iovene Jan 06 '13 at 19:55
  • @SalvatoreIovene I saw a few notes around that when I was digging. Presumably that only applies when using Nginx as a proxy. (?) – Tom Christie Jan 07 '13 at 21:42
  • This worked for me. Note that I had to put the rewrite rule inside the statement I needed it enabled for. – Laserallan Aug 07 '14 at 20:17
  • This works, but apparently, when no Authorization header is sent, this will create an empty one. Is there a way to not get an Authorization header when none is sent? – mezod Jan 05 '15 at 18:41
  • But if I'm not using Apache? – LeonanCarvalho Sep 28 '16 at 20:08
14

It depends on which kind of Django/Apache deployment you did. You need to tell the correct Apache module to allow to pass "Authentication" HTTP header:

  • Apache/mod_wsgi:

    WSGIPassAuthorization On

  • Apache/mod_fcgid:

    FcgidPassHeader Authorization

In other words: many Apache modules filters "Authentication" HTTP header, so Django will not receive it. You have to be sure your Django App is receiving it in request.

See: django_rest doc and Apache fcgid doc.

NOTE: After modifying Apache configuration you'll need to restart apache daemon or tell to reload your .cgi file (i.e: touch my_site_fcgifile.fcgi).

serfer2
  • 2,175
  • 1
  • 19
  • 16
0

The issue is the underscore in the HTTP header HTTP_AUTHORIZATION. Most webservers just ignores the headers with underscores.

Django dev server also exhibits the same, omitting headers with underscores.

This is the reason why Authorization2 works.

A Quick work around is to replace _ underscores in headers with - dashes,

Ex. changing the HTTP_AUTHORIZATION to HTTP-AUTHORIZATION

All Іѕ Vаиітy
  • 18,901
  • 11
  • 65
  • 90