Skip to main content

Using mod_auth_openid with Ubuntu SSO

I have some internal web sites running on my home server. Earlier I configured WebAuth with WebKDC to create SSO-like experience. This was working well, but I wanted to use some 3rd party solution to be able to use auth on remote services even if local WebAuth host is not accessible.

The requirements were:

  • Specify the list of users which are allowed to login.

  • Don’t require server-side scripting

Since Ubuntu SSO is already used for Launchpad, Ubuntu One and various other services I decided that it is good enough for my small network.

Ubuntu hosts are using python-apache-openid python module and it has a very nice feature of being able to restrict access to some launchpad teams. It is not yet critical for me so I decided to look around in the archive and found libapache2-mod-auth-openid.

This is a packaged version of mod_auth_openid from findingscience.com/mod_auth_openid – that web site contains the documentation for the module as well as examples.

The version in Oneiric is 0.5 which did not contain the feature I was after, the ability to restrict the access to some set of OpenID users without resorting to external script. So I went forward and updated the package to 0.6 and for the first time I was so pleased with the resulting package that I decided to send the updates to Debian maintainer. The updated package was successfully built in my ppa:rye/ppa and can be installed on Oneiric with

sudo apt-add-repository ppa:rye/ppa
sudo apt-get update
sudo apt-get install libapache2-mod-auth-openid

apt-add-repository is available from python-software-properties package.

Please verify that you have installed version 0.6:

$ apt-cache policy libapache2-mod-auth-openid
libapache2-mod-auth-openid:
Installed: 0.6-0ubuntu1
Candidate: 0.6-0ubuntu1

Configuration

I started with the following in my /etc/apache2/sites-available/default and added the items needed for OpenID support.

<VirtualHost *:80>
ServerAdmin webmaster@localhost

DocumentRoot /var/www
<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
<Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
</Directory>

# OpenID support:
<Location />
    AuthType OpenID
    Require valid-user
    AuthOpenIDTrusted ^https://login.ubuntu.com/\+openid
    AuthOpenIDLoginPage /openid/
    AuthOpenIDCookiePath /
</Location>

<Location /openid>
    Order allow,deny
    Allow from all
    Satisfy any
</Location>
# /OpenID support

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog ${APACHE_LOG_DIR}/access.log combined

Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
    Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>

</VirtualHost>

I am using a custom login page since I don’t need to enter my identifier every time. I am using a single provider so I am submitting an OpenID request automatically to Ubuntu SSO.

The /var/www/openid/index.html page is simple:

The query string parsing is actually needed to display the error that has been passed to the page in case the request is canceled on the provider or something else has happened.

By default the module creates the database in /tmp/mod_auth_openid.db, you can change it with AuthOpenIDDBLocation directive. If you migrate to some other host and forget to create the necessary paths for the database, you will get no_idp_found errors as if fetching the OpenID page failed.

Now the module needs to be enabled (this was not working in 0.5 out of the box) and apache needs to be restarted:

sudo a2enmod authopenid
sudo service apache2 restart

Now you have OpenID enabled for your virtual host root directory. The thing is it is enabled for everybody with Ubuntu SSO account so we need to restrict the access.

To find your OpenID identifier, log into your system using OpenID and browse the logs:

192.168.1.114 - https://login.ubuntu.com/+id/hPQWPsH ↩
[12/Nov/2011:12:24:54 +0200] ↩
"GET / HTTP/1.1" 304 210 "-" "Mozilla/5.0 ↩
(Ubuntu; X11; Linux x86_64; rv:8.0)

Accounts that exist in launchpad can find out their +id/... value from the https://launchpad.net/~yournick, the openid.delegate will have this info. Launchpad login service and Ubuntu SSO service are currently using the same database, but we are targeting SSO.

<link rel="openid.delegate"
    href="https://login.launchpad.net/+id/hPQWPsHxx" />

The OpenID value needs to go to the apache config as regular “Require user” directive:

<Location />
  AuthType OpenID
  Require user https://login.ubuntu.com/+id/hPQWPsH
  AuthOpenIDTrusted ^https://login.ubuntu.com/\+openid
  AuthOpenIDLoginPage /openid/
  AuthOpenIDCookiePath /
</Location>

Restart apache, and only the user specified in the Require user directive will be able to access the resource.

Limitations

This module can be used only for ID authentication. While it is technically possible to request the OpenID provider to reply with user email or any other attributes, the module does not provide any protection from changing the values as they are traveling as a GET request back to the original form target page.