M BUZZ CRAZE NEWS
// news

Juju deployed apache+gunicorn+django app over SSL, openid fails with No Mode

By Emma Johnson

Blog post

Just FYI I wrote up a blog post explaining everything I did to get up and going:

I have these services deployed and everything is accessible over https. However, when I attempt to authenticate via launchpad.net openid 2 things happen.

First the callback address is when it should be and second the application fails with a OpenID authentication failed: Invalid openid.mode ''" when it finally does make it back to the https host.

zef-sample-apache2-0:~$ cat /etc/apache2/sites-enabled/10.0.3.206_https

# Managed by juju
<VirtualHost *:80> ServerName 10.0.3.206 Redirect permanent /
</VirtualHost>
<VirtualHost *:443> ServerName 10.0.3.206 ServerAdmin CustomLog /var/log/cts-custom.log combined ErrorLog /var/log/cts-error.log SSLEngine on SSLCertificateFile /etc/ssl/certs/ssl-cert-cts.pem SSLCertificateKeyFile /etc/ssl/private/ssl-cert-cts.key RequestHeader set X-FORWARDED-SSL "on" RequestHeader set X-FORWARDED_PROTO "https" ProxyRequests off ProxyPreserveHost on <Proxy *> Order Allow,Deny Allow from All </Proxy> ProxyPass / ProxyPassReverse / #RewriteEngine on #RewriteRule ^/(.*)$ [P,L]
# Alias /favicon.ico /srv/seg-dashboard/segdash/static/favicon.ico
# Alias /robots.txt /srv/seg-dashboard/segdash/static/robots.txt
# Alias /static/admin /var/www/static/admin
# Alias /static/ /srv/seg-dashboard/segdash/static/
</VirtualHost>

I force everything over ssl so at this point im not sure if its an application issue with my django app since running a local https server and authenticating over SSL works fine.

Any ideas?

Here is my juju status output

machines: 0: agent-state: running dns-name: localhost instance-id: local instance-state: running
services: apache2: charm: cs:precise/apache2-11 exposed: true relations: reverseproxy: - seg-dashboard units: apache2/0: agent-state: started machine: 0 open-ports: - 80/tcp - 443/tcp public-address: 10.0.3.206 gunicorn: charm: cs:precise/gunicorn-7 relations: wsgi-file: - seg-dashboard subordinate: true subordinate-to: - seg-dashboard postgresql: charm: cs:precise/postgresql-30 exposed: false relations: db: - seg-dashboard replication: - postgresql units: postgresql/0: agent-state: started machine: 0 public-address: 10.0.3.37 rabbitmq-server: charm: cs:precise/rabbitmq-server-12 exposed: false relations: amqp: - seg-dashboard cluster: - rabbitmq-server units: rabbitmq-server/0: agent-state: started machine: 0 public-address: 10.0.3.144 seg-dashboard: charm: local:precise/seg-dashboard-1 relations: amqp: - rabbitmq-server db: - postgresql website: - apache2 wsgi: - gunicorn units: seg-dashboard/0: agent-state: started machine: 0 public-address: 10.0.3.113 subordinates: gunicorn/0: agent-state: started

And here is the relevant portion to the Launchpad Openid setup (django settings.py)

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
ALLOWED_EXTERNAL_OPENID_REDIRECT_DOMAINS = ['lvh.me', 'localhost', 'canonical.com']
# Add support for django-openid-auth
AUTHENTICATION_BACKENDS = ( 'django_openid_auth.auth.OpenIDBackend', 'django.contrib.auth.backends.ModelBackend',
)
OPENID_CREATE_USERS = True
OPENID_UPDATE_DETAILS_FROM_SREG = True
OPENID_SSO_SERVER_URL = '
OPENID_USE_AS_ADMIN_LOGIN = True
OPENID_LAUNCHPAD_TEAMS_REQUIRED = [ 'canonical',
]
OPENID_LAUNCHPAD_STAFF_TEAMS = ( 'cool-guys',
)
OPENID_STRICT_USERNAMES = True
OPENID_USE_EMAIL_FOR_USERNAME = True
LOGIN_URL = '/openid/login/'
LOGIN_REDIRECT_URL = '/'
# Login is required for all these patterns
LOGIN_REQUIRED_URLS = ( r'/(.*)$',
)
# We much except the openid URLs otherwise we go in loops.
LOGIN_REQUIRED_URLS_EXCEPTIONS = ( r'/openid/(.*)$',
)

Additional:

I believe the problem stems from the handoff from Apache(SSL) to gunicorn(nonSSL) and then when it hits launchpad.net the callback url is the Apache server (nonSSL). I attempted to use something like django-sslify to force SSL on the application side but it seems like the ProxyPreserveHost does not care/check if the host is coming from https or http and just defaults to http.

More:

Here is the request headers sent to launchpad.net

User-Agent:Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0
Referer:
Host:login.launchpad.net
DNT:1
Connection:keep-alive

And here is what the form data looks like:

openid_referer:""
openid.return_to:
openid.realm:

This is utilizing the django-openid-auth library and I am currently digging through the code to see why the consumer is directly setting the return_to http when the referer shows https?

1 Answer

Ive updated the post to show the proper configuration in both an Apache vhost and the django settings.py file.

You'll want to see a header to something like

RequestHeader set X-FORWARDED_PROTO "https"

And set the following in django settings

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWADED_PROTO', 'https')

You can read more about it here:

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy