XWiki Google Apps authentication with Nginx and Lua

XWiki is a really terrific open-source wiki package that, in my opinion, is the only freely-available package coming even close to the functionality of Atlassian’s Confluence. I recently wanted to integrate XWiki with single sign-on provided by Google Apps, but there are no XWiki plugins that work directly with Google Apps OAuth. Instead, we’ll be using a custom Lua authenticator with Nginx to handle authentication redirects, then provide authentication headers to XWiki.

In this post, I’ll be going into how I configured this scheme on an Ubuntu 12.04 LTS system. 14.04 should work without significant modifications.

Caveats

If you need to switch between multiple Google Apps accounts, logout does not work using the link in XWiki. There’s probably a trivial workaround that I haven’t bothered to find yet.

Prerequisites

Before beginning, you’ll need these in order to follow along:

  1. A public-facing Ubuntu/Debian server with a functioning XWiki installation. This article will assume this server is running on the default HTTP port 8080.
  2. An XWiki administrator account with a username that matches your Google Apps username (the portion before the @ symbol). If you do not create this, you will be locked out of administration once you enable Google Apps login.
  3. A verified Google Apps domain with at least one user account. I’ll be using mydomain.com in this article’s examples.
  4. A permanent hostname for the XWiki server, to be used for OAuth2 callbacks. I’ll be using xwiki.mydomain.com in examples.
  5. An SSL certificate for the site, issued by a trusted Certification Authority, and installed on the XWiki server. I’ll be using /etc/ssl/certs/xwiki.mydomain.com.pem in examples. I’ll also be assuming that your certificate is a PEM file containing the key, the server certificate, and the certificate chain concatenated into a single file. If this is not how you store your certificates, you’ll need to update your Nginx configuration accordingly.

You should not have Nginx preinstalled on your server. We are going to build our own Nginx with the Lua module installed. (If you have a custom-built Nginx package with a recent Lua module version compiled in already, feel free to use it, of course.)

Create the OAuth credentials

OAuth differs from traditional username/password authentication in that an application using OAuth never sees the username or password that are provided. Instead, the application redirects to a third-party login server that verifies a user’s credentials. Once you are verified, Google’s OAuth systems will issue a callback to your application confirming that the user is correctly authenticated. To make this function, you need to tell Google’s servers a little bit about your XWiki installation.

Create a Google Developer project

Log into the Google Developers Console using your Google Apps account. Once you are logged in, click the Create Project button in the middle of the screen. Name your project whatever you like, then click Create to finish account creation. The Google Developers Console should now take you inside your newly-created project.

Configure a consent screen

Before you can create an OAuth client ID, you need to configure a consent screen. This is the screen that’s shown to users after they log into Google, asking them to grant certain account privileges to your application.

From the menu on the left side of the screen, click APIs & auth to expand the sub-menu, then click Consent screen. Under Email address, select your email address. Under Product name, enter a product name that will be shown on the consent screen for your applications. All other fields are optional. Once you’ve finished filling in all the fields, click Save to create your consent screen.

Create an OAuth Client ID

From the menu on the left side of the screen, click APIs & auth to expand the sub-menu, then click Credentials. Locate the OAuth heading, then click the Create new Client ID button. The Create Client ID dialog will appear. Enter the following parameters:

  • Application type: Web application
  • Authorized Javascript origins: https://xwiki.mydomain.com
  • Authorized redirect URIs: https://xwiki.mydomain.com/_oauth

The client ID should now appear on the right side of the screen. Note the Client ID and Client secret fields. You’ll need both of these values later to configure authentication in Nginx.

Install Lua and CJSON

Begin by installing the Lua libraries. We’ll be using LuaJIT with Nginx for performance. We also need some security libraries in order to have HTTPS support in Lua.

Next, download and build the Lua CJSON library. The current version is 2.1.0 as of this writing.

 

Build a custom Nginx with Lua scripting

Download lua-nginx-module and extract the sources, so the module can be found by the Nginx configure script:

Install some Nginx build dependencies:

Then download, extract, and configure Nginx:

Download the authentication module and configure Nginx

Agora Games has kindly published an Nginx Lua script that can be used to support OAuth2 authentication. However, at the time of this publication, it doesn’t support a crucial feature that we need — the ability to set HTTP headers based on OAuth login status. We’re going to pull that from eschwim’s fork.

With the script in place, we’re going to configure Nginx. Create an virtual host in /etc/nginx/nginx.conf with the following configuration:

With the configuration in place, start Nginx with sudo /opt/nginx-1.7.10/sbin/nginx -c /etc/nginx.conf.

(You should, of course, configure Nginx to start with your init system of choice, like Upstart or runit, so Nginx will start automatically when your server reboots. That configuration is beyond the scope of this article.)

Install XWiki  header auth module

From your wiki’s administration page, locate Extension Manager from the menu on the left, then click Add Extensions. Search for Headers Authenticator for XWiki. Locate the plugin in the table at the bottom and click Install, then wait for installation to complete.

On my XWiki 6.4.1 installation, this process never completed successfully. It kept downloading the file into a temp directory over and over and wouldn’t stop until I forcibly restarted the XWiki service. I had to download the plugin jar, manually place it into /usr/lib/xwiki/WEB-INF/lib, and restart the service.

Configure XWiki for headers authentication

Finally, you’re going to configure XWiki to use the headers Nginx is feeding to it. Add the following to /etc/xwiki/xwiki.cfg:

Finally, restart your XWiki Tomcat container with service tomcat7 restart (or whatever is appropriate for your installation type).

Wrapping up

When you browse to https://xwiki.mydomain.com, you should now see a Google Apps login screen. After providing your login credentials, you should be prompted to provide basic account information to the Google Developer app that you created earlier. Once you authorize the app to use your credentials, you should see your account logged into XWiki automatically.

2 Comments

  1. Great tutorial !

    About “this process never completed successfully. It kept downloading the file into a temp directory over and over and wouldn’t stop until I forcibly restarted the XWiki service.”. I work on XWiki and I was not able to reproduce this (and never saw this behavior), if you still can and have some time it would be great if I could debug that with you.

  2. Marinos Stylianou

    26 February, 2015 at 3:00 AM

    Very nice tutorial.

    My two cents:
    I managed to implement the signout by:

    1. Edit the access.lua file and replace the following lines in the signout part:
    if uri == signout_uri then
    — ngx.header[“Set-Cookie”] = “AccessToken=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT”
    — return ngx.redirect(cb_scheme..”://”..server_name)
    ngx.header[“Set-Cookie”] = “OauthAccessToken=deleted; path=/; OauthExpires=Thu, 01 Jan 1970 00:00:00 GMT”
    return ngx.redirect(“https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=”..cb_scheme..”://”..server_name)
    end

    2. Add the xwiki signout link to the nginx configuration
    set $ngo_signout_uri “/xwiki/bin/logout/XWiki/XWikiLogout”;

    What I could not do is populate the Profile fields in the user when a new user is created. Any ideas?

Leave a Reply to Thomas Mortagne Cancel reply

Your email address will not be published.

© 2017 @jgoldschrafe

Theme by Anders NorenUp ↑