Just FYI I wrote up a blog post explaining everything I did to get up and going: http://www.astokes.org/post/2013-07-14-juju-gunicorn-apache-django
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 http://10.x.x.x when it should be https://10.x.x.x 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 / https://10.0.3.206/ </VirtualHost> <VirtualHost *:443> ServerName 10.0.3.206 ServerAdmin firstname.lastname@example.org 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 / http://10.0.3.113:8080/ ProxyPassReverse / http://10.0.3.113:8080/ #RewriteEngine on #RewriteRule ^/(.*)$ http://10.0.3.113:8080/$1 [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.
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 = 'https://login.launchpad.net/' 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/(.*)$', )
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.
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:https://10.0.3.218/openid/login/?next=/ Host:login.launchpad.net DNT:1 Connection:keep-alive
And here is what the form data looks like:
openid_referer:"https://10.0.3.218/openid/login/?next=/" openid.return_to:http://10.0.3.218/openid/complete/?next=%2F&janrain_nonce=2013-07-13T03%3A35%3A28ZSrfuV5 openid.realm:http://10.0.3.218/
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?