"WSGIPassAuthorization On", but HTTP_AUTHORIZATION is not sent through...

3,540 views
Skip to first unread message

Jumpfroggy

unread,
Dec 22, 2009, 4:31:20 PM12/22/09
to modwsgi
I've got Apache serving multiple django web apps via virtual hosts.
For one of those hosts, I have "WSGIPassAuthorization On". However,
the django app does not have HTTP_AUTHORIZATION or
HTTP_HTTP_AUTHORIZATION in the request.META headers. If I run the app
with the django "manage.py runserver", then I see the header just
fine.

I'm using Apache 2.2 with mod_wsgi 3.1. I use hostname-based virtual
hosts. I used to have this working on another server by simply using
"WSGIPassAuthorization On" in the httpd.conf file, but I've changed
setup and now I can't figure out why it's not working.

Here is my httpd.conf:
ServerRoot "/path/to/apache2"
Listen 12345

LoadModule log_config_module modules/mod_log_config.so
LoadModule authz_host_module modules/mod_authz_host.so


LoadModule authn_default_module modules/mod_authn_default.so
#LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_default_module modules/mod_authz_default.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule auth_digest_module modules/mod_auth_digest.so

#LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule mime_module modules/mod_mime.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so

LoadModule wsgi_module modules/mod_wsgi.so

ServerAdmin admin@(removed).com

#DocumentRoot "/path/to/apache2/htdocs"

<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
</Directory>

# Logging
ErrorLog "logs/error_log"
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i
\"" combined
CustomLog "logs/access_log" combined

# Virtual Hosting Setup

ServerLimit 1
MinSpareThreads 1
MaxSpareThreads 5
ThreadsPerChild 10

<Directory /path/to/wsgi>
Order allow,deny
Allow from all
</Directory>

NameVirtualHost *:12345

# Virtual Hosts

<VirtualHost *:12345>
ServerName (domain1).com
KeepAlive Off
WSGIDaemonProcess (domain1).com processes=1 threads=20 inactivity-
timeout=60 display-name=[wsgi-scriptshare]httpd
WSGIProcessGroup (domain1).com
WSGIScriptAlias / /path/to/wsgi/scriptshare.wsgi
</VirtualHost>

<VirtualHost *:12345>
ServerName (domain2).com
ServerAlias www.(domain2).com
KeepAlive Off
WSGIDaemonProcess (domain2).com processes=1 threads=10 inactivity-
timeout=60 display-name=[wsgi-everythingri]httpd
WSGIProcessGroup (domain2).com
WSGIScriptAlias / /path/to/wsgi/everythingri.wsgi
</VirtualHost>

<VirtualHost *:12345>
ServerName (domain3).com
KeepAlive Off

# THIS SHOULD PASS HTTP_AUTHORIZATION TO DJANGO...
WSGIPassAuthorization On

WSGIDaemonProcess (domain3).com processes=1 threads=10 inactivity-
timeout=60 display-name=[wsgi-dev-seemonkey]httpd
WSGIProcessGroup (domain3).com
WSGIScriptAlias / /path/to/wsgi/seemonkey.wsgi
</VirtualHost>

I run this test program:


import urllib
import urllib2

url = '(removed)'

print 'URL: %s' % url

headers = {
'HTTP_AUTHORIZATION': '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
HTTP_AUTHORIZATION',
'FAKE': '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FAKE',
}
print 'headers: %s' % headers

print 'Results:'

#print 'sending headers: %s' % headers

req = urllib2.Request(url, headers=headers)

try:
url1 = urllib2.urlopen(req)
except Exception, e:
print 'Exception:'
print e
else:
response = url1.read()
print 'response:'
print '----------------------------------------'
print response
print '----------------------------------------'
print ''

For "manage.py runserver", I get this result:
URL: (django runserver url)
headers: {'HTTP_AUTHORIZATION':
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! HTTP_AUTHORIZATION', 'FAKE':
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FAKE'}
Results:
response:
----------------------------------------
request.META[wsgi.version]: (1, 0)
request.META[wsgi.multiprocess]: False
request.META[RUN_MAIN]: 'true'
request.META[SERVER_PROTOCOL]: 'HTTP/1.1'
request.META[SERVER_SOFTWARE]: 'WSGIServer/0.1 Python/2.5.4'
request.META[SCRIPT_NAME]: u''
request.META[REQUEST_METHOD]: 'GET'
request.META[PROCESSOR_REVISION]: '0f0b'
request.META[QUERY_STRING]: ''
request.META[HTTP_HTTP_AUTHORIZATION]:
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! HTTP_AUTHORIZATION'
request.META[wsgi.errors]: <open file '<stderr>', mode 'w' at
0x00A400B0>
request.META[CONTENT_LENGTH]: ''
request.META[HTTP_CONNECTION]: 'close'
request.META[REMOTE_HOST]: ''
request.META[REMOTE_ADDR]: '127.0.0.1'
request.META[SERVER_PORT]: '10002'
request.META[SESSIONNAME]: 'Console'
request.META[PROCESSOR_LEVEL]: '6'
request.META[HTTP_FAKE]: '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
FAKE'
request.META[USERNAME]: '(username)'
request.META[wsgi.input]: <socket._fileobject object at 0x018B76B0>
request.META[HTTP_USER_AGENT]: 'Python-urllib/2.5'
request.META[HTTP_HOST]: 'localhost:10002'
request.META[wsgi.multithread]: True
request.META[PATHEXT]:
'.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH'
request.META[PATH_INFO]: u'/(page_url)'
request.META[SERVER_NAME]: '(server name)'
request.META[GATEWAY_INTERFACE]: 'CGI/1.1'
request.META[wsgi.run_once]: False
request.META[DJANGO_SETTINGS_MODULE]: '(django app name).settings'
request.META[CONTENT_TYPE]: 'text/plain'
request.META[wsgi.file_wrapper]: <class
'django.core.servers.basehttp.FileWrapper'>
request.META[OS]: 'Windows_NT'
request.META[HTTP_ACCEPT_ENCODING]: 'identity'
request.META[wsgi.url_scheme]: 'http'
request.META.get('HTTP_AUTHORIZATION', None): None
request.META.get('HTTP_HTTP_AUTHORIZATION', None):
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! HTTP_AUTHORIZATION'
----------------------------------------

The HTTP_HTTP_AUTHORIZATION shows up just fine.

But with the apache server, I get these results:
URL: (apache url)
headers: {'HTTP_AUTHORIZATION':
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! HTTP_AUTHORIZATION', 'FAKE':
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FAKE'}
Results:
response:
----------------------------------------
request.META[mod_wsgi.reload_mechanism]: '1'
request.META[mod_wsgi.listener_port]: '29019'
request.META[SERVER_SOFTWARE]: 'Apache/2.2.14 (Unix) mod_wsgi/2.5
Python/2.5.4'
request.META[SCRIPT_NAME]: u''
request.META[SERVER_SIGNATURE]: ''
request.META[REQUEST_METHOD]: 'GET'
request.META[PATH_INFO]: u'/(page url)'
request.META[SERVER_PROTOCOL]: 'HTTP/1.0'
request.META[QUERY_STRING]: ''
request.META[HTTP_USER_AGENT]: 'Python-urllib/2.5'
request.META[HTTP_CONNECTION]: 'close'
request.META[SERVER_NAME]: '(server name)'
request.META[REMOTE_ADDR]: '127.0.0.1'
request.META[wsgi.url_scheme]: 'http'
request.META[SERVER_PORT]: '80'
request.META[wsgi.multiprocess]: True
request.META[HTTP_FAKE]: '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
FAKE'
request.META[SERVER_ADDR]: '127.0.0.1'
request.META[mod_wsgi.process_group]: '(removed)'
request.META[SCRIPT_FILENAME]: '(removed).wsgi'
request.META[SERVER_ADMIN]: '(removed)'
request.META[wsgi.input]: <mod_wsgi.Input object at 0xb03b8f48>
request.META[HTTP_HOST]: '(removed)'
request.META[wsgi.multithread]: True
request.META[mod_wsgi.callable_object]: 'application'
request.META[REQUEST_URI]: '/(removed)'
request.META[wsgi.version]: (1, 0)
request.META[GATEWAY_INTERFACE]: 'CGI/1.1'
request.META[HTTP_X_FORWARDED_FOR]: '(removed)'
request.META[wsgi.errors]: <mod_wsgi.Log object at 0xa348338>
request.META[REMOTE_PORT]: '51174'
request.META[mod_wsgi.listener_host]: ''
request.META[mod_wsgi.version]: (2, 5)
request.META[wsgi.run_once]: False
request.META[mod_wsgi.application_group]: '(removed)|'
request.META[mod_wsgi.script_reloading]: '1'
request.META[wsgi.file_wrapper]: <built-in method file_wrapper of
mod_wsgi.Adapter object at 0xa268c80>
request.META[HTTP_ACCEPT_ENCODING]: 'identity'
request.META.get('HTTP_AUTHORIZATION', None): None
request.META.get('HTTP_HTTP_AUTHORIZATION', None): None
----------------------------------------

The "FAKE" http header shows up as "HTTP_FAKE", but the
"HTTP_AUTHORIZATION" header doesn't show up at all. It's being
filtered out, which is what you'd expect if the WSGIPassAuthorization
was Off. I've restarted the server a ton, played with the http.conf,
and I'm stuck.

What other steps can I try to troubleshoot this? My host is
webfaction, which runs Apache behind an nginx proxy frontend. I'm not
sure if that makes a difference. I've been using this fine on another
machine, but recently switched machines, then recompiled apache, and
now it doesn't work. Something's wrong, but I'm out of ideas of where
to look.

Thanks so much for any help!

Graham Dumpleton

unread,
Dec 22, 2009, 4:46:15 PM12/22/09
to mod...@googlegroups.com
I'll have a look at the information you sent, but suggest that rather
than use a simplified Django test program, use a raw WSGI application
to dump out environment passed. See:

http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Displaying_Request_Environment

That will take Django out of the picture.

Graham

2009/12/23 Jumpfroggy <rocket...@gmail.com>:

> --
>
> You received this message because you are subscribed to the Google Groups "modwsgi" group.
> To post to this group, send email to mod...@googlegroups.com.
> To unsubscribe from this group, send email to modwsgi+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/modwsgi?hl=en.
>
>
>

Jumpfroggy

unread,
Dec 22, 2009, 10:34:19 PM12/22/09
to modwsgi
On Dec 22, 4:46 pm, Graham Dumpleton <graham.dumple...@gmail.com>
wrote:

> I'll have a look at the information you sent, but suggest that rather
> than use a simplified Django test program, use a raw WSGI application
> to dump out environment passed. See:
>  http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Displaying_...

> That will take Django out of the picture.
> Graham

Graham,
Thanks so much for your help. It's a shame I'm not great at reading
the mod_wsgi docs, because there's a ton of helpful stuff in there
that I just seem to gloss over.

I've added that test application in and below are the results. Same
thing: the "FAKE" header shows up as "HTTP_FAKE", but the
HTTP_AUTHORIZATION header is missing. I'm going to contact my hosting
co. to make sure it's not a problem on their side, but I have a hunch
it's something I've done wrong in the config.

-James

BTW, Thanks Graham for being so involved with mod_wsgi. It's very
useful, and it's nice to find a project that's so 'alive'.

-- Pasted from the debugging application: --
URL: http://test.(domain).com


headers: {'HTTP_AUTHORIZATION':
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! HTTP_AUTHORIZATION', 'FAKE':
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FAKE'}
Results:

----------------------------------------
PID: 13460
UID: 654
GID: 654

DOCUMENT_ROOT: '/path/to/htdocs'
GATEWAY_INTERFACE: 'CGI/1.1'
HTTP_ACCEPT_ENCODING: 'identity'
HTTP_CONNECTION: 'close'
HTTP_FAKE: '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FAKE'
HTTP_HOST: 'test.(domain).com'
HTTP_USER_AGENT: 'Python-urllib/2.5'
HTTP_X_FORWARDED_FOR: '(removed)'
PATH: '(removed)'
PATH_INFO: '/'
PATH_TRANSLATED: '/path/to/test.wsgi/'
QUERY_STRING: ''
REMOTE_ADDR: '127.0.0.1'
REMOTE_PORT: '57509'
REQUEST_METHOD: 'GET'
REQUEST_URI: '/'
SCRIPT_FILENAME: '/path/to/test.wsgi'
SCRIPT_NAME: ''
SERVER_ADDR: '127.0.0.1'
SERVER_ADMIN: 'admin@(domain).com'
SERVER_NAME: 'test.(domain).com'
SERVER_PORT: '80'
SERVER_PROTOCOL: 'HTTP/1.0'
SERVER_SIGNATURE: ''


SERVER_SOFTWARE: 'Apache/2.2.14 (Unix) mod_wsgi/2.5 Python/2.5.4'

mod_wsgi.application_group: 'test.(domain).com|'
mod_wsgi.callable_object: 'application'
mod_wsgi.listener_host: ''
mod_wsgi.listener_port: '12345'
mod_wsgi.process_group: 'test.(domain).com'
mod_wsgi.reload_mechanism: '1'
mod_wsgi.script_reloading: '1'
mod_wsgi.version: (2, 5)
wsgi.errors: <mod_wsgi.Log object at 0xb7f3f608>


wsgi.file_wrapper: <built-in method file_wrapper of mod_wsgi.Adapter

object at 0xb7f10650>
wsgi.input: <mod_wsgi.Input object at 0xb7f2b4a8>
wsgi.multiprocess: True
wsgi.multithread: True
wsgi.run_once: False
wsgi.url_scheme: 'http'
wsgi.version: (1, 0)
----------------------------------------

Graham Dumpleton

unread,
Dec 22, 2009, 10:48:49 PM12/22/09
to mod...@googlegroups.com
All I can suggest right now is move the:

WSGIPassAuthorization On

outside of all virtual hosts rather than restricting it to just one.

If this works though, suggests that virtual host mapping by Apache
isn't working as you expect.

You could also add:

SetEnv XXX YYY

in Apache configuration, inside of virtual host, but also then outside
of virtual host, to verify that that setting even carrying through
into WSGI environment when that is used in different contexts.

Overall, as far as I know all that needs to be done on WebFaction is
set WSGIPassAuthorization. Ie., nothing need in nginx front end.

Graham

2009/12/23 Jumpfroggy <rocket...@gmail.com>:

Jumpfroggy

unread,
Dec 23, 2009, 4:59:36 AM12/23/09
to modwsgi
Summary: I should be sending "AUTHORIZATION" instead of
"HTTP_AUTHORIZATION" as the http header?

Ok, so after playing around, I think the problem is with my test
program, and also with my incorrect/incomplete understanding of HTTP
header names.

These http headers show up fine:
A -> HTTP_A
FAKE -> HTTP_FAKE
PAGE-TYPE -> HTTP_PAGE_TYPE

However, these do not show up at all:
A_
HTTP_FAKE
PAGE_TYPE

So apache filters out all names with underscores. It also prepends
HTTP_, and converts _ to -, which I knew. I think the problem is that
I'm sending "HTTP_AUTHORIZATION", which gets filtered out. However,
if I send an "AUTHORIZATION" header, it gets turned into
"HTTP_AUTHORIZATION" due to apache name mangling and then shows up
fine with "WSGIPassAuthorization On".

I've been focusing too much on "HTTP_AUTHORIZATION" to realize that
that's just the mangled version of the AUTHORIZATION header. Does
that make sense, or am I short-circuiting here?

So if this is truly the case, then I'm being stupid;
WSGIPassAuthorization worked just fine, it was my test program that
was incorrect. I'll try this with Google Checkout, and see if that
works as well.

Graham Dumpleton

unread,
Dec 23, 2009, 5:02:44 AM12/23/09
to mod...@googlegroups.com
2009/12/23 Jumpfroggy <rocket...@gmail.com>:

> Summary: I should be sending "AUTHORIZATION" instead of
> "HTTP_AUTHORIZATION" as the http header?

Yep. I sort of assumed you were using standard client which sent it as
'Authorization' HTTP header.

Interesting that Apache filters out anything with underscore, I didn't
know that. Will have to remember for future.

Graham

Jumpfroggy

unread,
Dec 23, 2009, 5:27:49 AM12/23/09
to modwsgi
Yeah, just a big miss on my part. Everything's working now, thanks
for the tips. Definitely got me going in the right direction.

Joao Paulo Fernandes Ventura

unread,
Jul 28, 2014, 3:40:39 PM7/28/14
to mod...@googlegroups.com
Hello,

I am having a similar problem with a Django application running at Amazon EC2 (I also posted a question at Stack Overflow).

First I would like to know which of the following files should contain the rewrite rule option:
  • site-full.conf
  • site-simple.conf
  • vhosts.conf
  • httpd.conf
And second, if this is the correct manner of declare the rewrite rule on site-full.conf and site-simple.conf:

    WSGIScriptAlias / /home/sfw/%(namespace)s/appengine/wsgi.py
    WSGIPassAuthorization On

    <Directory "/home/sfw/%(namespace)s/">
        AllowOverride All
        Require all granted

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

        <Files wsgi.py>
            SetEnvIfNoCase Host %(full_host_regex)s|%(naked_host_regex)s VALID_HOST
            Order Deny,Allow
            Deny from All
            Allow from env=VALID_HOST
        </Files>
    </Directory>

Thank you a lot for your help :-)

Graham Dumpleton

unread,
Jul 28, 2014, 8:55:36 PM7/28/14
to mod...@googlegroups.com
What exactly are you trying to do?

Especially, why do you have the following?

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

And where does the password checking even occur and with which authentication scheme?

Right now you have nothing in the Apache configuration such that it is doing authentication management.

Are you doing authentication in your Django application?

Usually people use form based login with Django and not HTTP authentication, and WSGIPassAuthorization has got nothing to do with Django form based authentication.

Graham

--
You received this message because you are subscribed to the Google Groups "modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to modwsgi+u...@googlegroups.com.

To post to this group, send email to mod...@googlegroups.com.
Visit this group at http://groups.google.com/group/modwsgi.
For more options, visit https://groups.google.com/d/optout.

João Paulo

unread,
Jul 28, 2014, 9:23:28 PM7/28/14
to mod...@googlegroups.com
I am using this django as an android mobile backend. The application running on AMZ is the responsible for authentication management, including social login.
--
Joao Paulo Fernandes Ventura
Computer Engineer - University of Campinas
http://br.linkedin.com/in/talktojp

Computer games don't affect kids.
I mean if Pac-Man affected us as kids, we'd all
be running around darkened rooms, munching magic
pills and listening to repetitive electronic music.

Kristian Wilson, Nintendo, Inc. 1989.
=============================================

Graham Dumpleton

unread,
Jul 28, 2014, 9:29:27 PM7/28/14
to mod...@googlegroups.com
Sorry, don't understand what you mean by that.

When you say 'The application running on AMZ is the responsible for authentication management' are you talking about your Django application, or some separate application independent of Apache, or one somehow integrated with Apache authentication mechanism.

Graham

João Paulo

unread,
Jul 28, 2014, 9:41:19 PM7/28/14
to mod...@googlegroups.com
I have a virtual machine running on Amazon EC2. Inside this machine, I also have a django application project working as a RESTful back-end to my mobile app.

Through a RESTful GET like curl -u j...@hotmail.com:potatoes https://sfw.com/accounts/login/, I get a status code 401 (wrong username or password).

I have understood until know, from all my trials, is that the HTTP_AUTHORIZATION is not arriving to the running Django.

Graham Dumpleton

unread,
Jul 28, 2014, 9:47:12 PM7/28/14
to mod...@googlegroups.com
So what is:

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

meant to be trying to achieve.

You should not need to be trying to set HTTP_AUTHORIZATION yourself.

Graham

João Paulo

unread,
Jul 28, 2014, 9:57:42 PM7/28/14
to mod...@googlegroups.com
In theory, this is the solution I copied from another post in order to fix the missing HTTP_AUTHORIZATION. But I was not successful on it.

I got no problems running the same django project on home PC. 

Graham Dumpleton

unread,
Jul 28, 2014, 10:10:26 PM7/28/14
to mod...@googlegroups.com
Have you used something like:


or:


to capture and display the WSGI environ dictionary before it hits the Django application to see if the header is passed through from mod_wsgi.

All that should be required is WSGIPassAuthorization.

Is WSGIPassAuthorization definitely only mentioned once in all the Apache configuration files.

What version of mod_wsgi are you using?

Is that section of Apache configuration you gave in a VirtualHost?

Do you have multiple VirtualHost's for the site, one for HTTP and one for HTTPS. Is the WSGIPassAuthorization directive set in both VirtualHost's?

Graham
Reply all
Reply to author
Forward
0 new messages