We’ve been quietly testing this for quite some time, but we’re happy to announce our LinOTP module for SimpleSAMLphp, which is available on GitHub.

It’s based on a module created by the LinOTP developers, but we’ve extended it to provide what SimpleSAMLphp calls an ‘authproc filter’ — the ability to insert a step into the authentication process when someone is logging into a SAML-based service. In this way we can provide a second factor of authentication, registered with a LinOTP server (be it a smartphone app like Google Authenticator, a YubiKey, SMS code, or anything else you might have configured your LinOTP server to handle).

But let’s wind back a step. Why would you want this and how can you use it?

To show you why this is so cool, it will probably help to tell the whole story. Much has been made for quite some time about how terrible passwords are and the need for second factors of authentication (often shortened to 2FA, you may have heard the mantra “something you know and something you own”). On the 2FA side of things we started out with the YubiKey devices made by Yubico (note we’re partners) which we still use and adore. The reasons we started with, and continue to use these devices are several:

  1. they’re open source;
  2. there’s a great library of code behind them you can leverage;
  3. they’re reasonably priced;
  4. they’re incredibly easy to use;
  5. we have confidence in Yubico remaining at the cutting edge of 2FA tech.

We found we could reasonably easily implement YubiKey authentication against our own Yubico endpoint, using freely available software, and tie it into our applications. We were authenticating with LDAP, we could install a schema that allowed us to store a YubiKey ID in an LDAP user object, and then we could have our applications do a double-check. First, are the provided LDAP credentials valid (username and password), second, is their associated YubiKey OTP valid. As it happens this all works like a charm, we use it in a few places, including with Linux’s own authentication software, PAM.

That’s fine, but there’s no standardisation around the open source Yubico API. So implementation becomes something we have to maintain, especially in our apps. No one has made a YubiKey plugin for our ticketing system, Redmine, for example, and we don’t have any Ruby developers, so that’s a pain. We have to implement our own custom code in a lot of places, and few other organisations will assist us or share code around it.

Enter SAML 2.0, which is a recognised and very widely used authentication standard (it’s implemented by Microsoft ADFS — same stuff). Lots of organisations use it, almost all software has some kind of SAML implementation available, so if we could get YubiKeys and SAML 2.0 to play nice together, we would have something we could easily roll out to all our applications, SymfonyRedmineDrupalRocket.ChatGitLab CEeverything and without having to write or maintain any code!

To start we needed a SAML implementation we could work with. At this point we turned to SimpleSAMLphp. It’s a versatile PHP implementation of SAML that can play both the roles of identity provider (IdP) and/or service provider (SP — a consumer of an IdP). Here we’re using it as an IdP, essentially, it’s the glue in the authentication process. It sits between an authentication source (Microsoft Active Directory, OpenLDAP, OpenID, Google Apps, there are many options) and an application that wants to verify the identity of someone requesting a login. The application that wants to verify someone hits SimpleSAMLphp, they login there, SimpleSAMLphp checks their credentials against the specified authentication source and tells the application whether that set of credentials should be allowed to login or not.

SimpleSAMLphp ships with some useful modules, such as LDAP and OpenID authentication I mentioned already, and it can be extended with modules. Remember, what we’re trying to do here is authenticate with normal user credentials (OpenLDAP in our case) and then verify identity with a second step (a YubiKey). Well looky here, one of the SimpleSAMLphp developers has made a YubiKey ‘authproc filter’.

Happy days! I installed that, tried it out with AWS logins, and, sure enough, once I got the config correct I was able to login to SimpleSAMLphp with my LDAP credentials, then I was challenged with a YubiKey prompt and if I entered a valid YubiKey I was taken on to my AWS console.

So to recap, now I can install SAML 2.0 integration for all my various apps and configure SimpleSAMLphp to take care of 2FA for me, via the YubiKey module above, to make the organisation less reliant on passwords. Whoop!

BUT, now I have to send everyone a YubiKey. I don’t mind issuing them to staff, but they’re $40 a pop and we don’t have any customer user limits (nor do I want to start imposing them). So this is where LinOTP finally enters the fray. It’s another piece of glue, this one sits between applications that want to verify the authenticity of a one-time password (as generated as part of a 2FA workflow) and the back office bits — like the Yubico API I mentioned earlier — to give you a single, very simple API you can interact with that supports a myriad of possible second factor methods. Including YubiKeys!

Like Yubico, the makers of LinOTP ship a PAM module for Linux, so that part was pretty easy — it just worked. And it has the built in ability to pull in your LDAP users, so we could seed LinOTP with all our users. The only sticking point, which is still the case at time of writing, is I had to patch it to support a custom Yubico API endpoint (remember, we run our own, we don’t use YubiCloud, Yubico’s public endpoint). That patch is available on GitHub and I hope it will make the next LinOTP release so I can quit maintaining it!

But with that small patch in place, suddenly I can login to the “self service” section of LinOTP, register my YubiKey (and my phone, and my smartphone app) then go and authenticate against something — might be a website, might be SSH on a Linux server, might be something else entirely — login with my LDAP credentials and use any one of the 2FA options I’ve registered with LinOTP for the final authenticity check. I usually still use my YubiKey, because it’s so easy, but if I left it downstairs I can use my smartphone instead.

And also, I no longer have to send all my client users a YubiKey. They can enrol with their smartphone. Which is a huge win.

Of course, the LinOTP API has the same problem the YubiKey API has, very few people directly support it. LinOTP themselves had made an authentication module for SimpleSAMLphp, but I needed an ‘authproc filter’, like the one I found for the YubiKey API and linked to above. And it didn’t exist. And that is why I wrote the module this blog post is about. So SimpleSAMLphp can still be my glue for authentication, and it can check in with LinOTP mid-process to verify an OTP before giving a response to the requesting application. All within a standards-based authentication framework that even works with Microsoft ADFS.

So let’s recap on the flow here, as you almost certainly got lost there. I know I almost did and I’m writing it! Let’s pretend the application is our GitLab CE version control system. It goes like this:

  • user visits GitLab login page and clicks login button;
  • user is taken to SimpleSAMLphp and challenged for LDAP login;
  • SimpleSAMLphp checks LDAP credentials against back-end OpenLDAP server and proceeds if correct;
  • user is challenged for a valid OTP;
  • user presses YubiKey / enters code in SMS / enters smartphone app code;
  • SimpleSAMLphp checks with LinOTP the OTP is valid and proceeds if OK;
  • SimpleSAMLphp passes message back to GitLab this user is good to go;
  • GitLab opens a session for user.

It’s the bit in italics that I’m announcing the software for today. That was the missing piece of the puzzle. And of course, you can swap GitLab with almost anything you can think of, there aren’t many pieces of software out there that don’t implement SAML 2.0, that’s the beauty of it!

And that’s all I have for you today. If you want to do this for your organisation, all the information you need is linked to from this article. If you don’t have the time or the inclination, you can always contact us and we can implement it for you. Once running, a system like this only costs about $300 a month. Not bad for an Enterprise ready, standards-based, 2FA enabled authentication system.

Written by

Greg Harvey