Friday, September 11, 2015

Getting OpenID Connect, Microsoft Accounts and Azure AD working with mod_auth_openidc

I've been very busy lately working on lots of very geeky things.  I've been doing quite a bit of work with Hans Zandbelts Apache mod_auth_openidc getting it to work with various and sundry Open ID Connect providers or OP's.  In this post, I'll be describing the steps I used to get the new preview version of Microsoft consolidated Open ID Connect implementation for single signon or SSO.

I won't go into how to configure Open ID Connect in detail, this post assumes you either have or have the knowledge to set up a basic mod_auth_openidc deployment.

The first thing you need to do is to register your app at  https://apps.dev.microsoft.com.

Use the "Application ID" for your client_id in the mod_auth_openidc configuration, then click on "Generate New Password" and save this off to use as your client_secret.

If you want the nitty gritty of Microsoft's implementation, have a look at: https://azure.microsoft.com/en-us/documentation/articles/active-directory-appmodel-v2-overview/

Everything should be configured per the normal mod_auth_openidc documentation.  I'm using the OIDCMetaDataDir directive so that I can specify multiple open ID connect providers as described in the README file for mod_auth_openidc.

If you want to see the configuration directives that map to the Apache Conf file, look in  the auth_openidc.conf file in the source tree.

There are 3 files included in a meta setup for each OP.  xxx.provider, xxx.conf and xxx.client.

The contents of the .provider file can be gleaned from the following URL:

https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

The Microsoft documentation is incorrect and has .well-known/configuration, which returns a 404 error.

Now here's where the secret sauce comes in.  When you name your xxx.provider, .conf and .client files, name them like the following with the following contents:



login.microsoftonline.com%2F%7Btenantid%7D%2Fv2.0.client

{
        "client_id" : "app/client id from apps.dev.microsoft.com",
        "client_secret" : "generated password from apps.dev.microsoft.com"
}

login.microsoftonline.com%2F%7Btenantid%7D%2Fv2.0.conf

{
        "scope" : "openid",
        "response_type" : "id_token",
        "response_mode" : "form_post"
}

login.microsoftonline.com%2F%7Btenantid%7D%2Fv2.0.provider


Now restart your Apache server.  Load a protected URL, on said server, so that you get the discovery page that shows links to your configured OP's.  You should see one for login.microsoftonline.com%2F%7Btenantid%7D%2Fv2.0.

Click on the link from your discover page and login with a Microsoft Online account.

At this point your Web Server will throw an error.  If you look in your Apache error log you should see something like the following, if everything else is configured correctly:

oidc_proto_validate_jwt: requested issuer (login.microsoftonline.com/{tenantid}/v2.0/) does not match received "iss" value in id_token (login.microsoftonline.com/xxxxyyyyzzzz/v2.0)


The problem is that {tenantid} is a placeholder and will not work to authenticate. xxxxyyyyzzzz above should be your valid tenantid. This to appears to be a bug/missing documentation on Microsofts part.  To finish making this work do the following:


  1. Edit login.microsoftonline.com%2F%7Btenantid%7D%2Fv2.0.provider and change login.microsoftonline.com/{tenantid}/v2.0/ to be login.microsoftonline.com/xxxxyyyyzzzz/v2.0
  2. Now change the names of your meta files to be:

    login.microsoftonline.com%2Fxxxxyyyyzzzz%2Fv2.0.client
    login.microsoftonline.com%2Fxxxxyyyyzzzz%2Fv2.0.conf
    login.microsoftonline.com%2Fxxxxyyyyzzzz%2Fv2.0.

Now the big caveat to all of this is that this is a preview version, and is not meant for production.  Microsoft may make changes to the above and break any implementation you might care to deploy, according to the Microsoft documentation.  That being said, the above seems to work great for logging in to your web app using Microsoft as an OP and mod_auth_openidc as the Relying Party (RP).