Wednesday, March 29, 2017

Website Authentication through SAML

Single Sign On (SSO) is a way to separate the authentication mechanism from the rest of the service, such as a webpage or mobile app. The first benefit of using SSO is that the service does not need to implement its own authentication logic. The second benefit is that the same authentication mechanism can be used across multiple services. The third benefit is that a service can support multiple authentication options. Single Sign On does not mean that multiple services share users. A user of one service does not have to be able to access all services.

SAML is a Single Sign On solution. Most webpages about SAML describe it at a high, very abstract level because the specification allows some flexibility to the implementation. But I've only seen SAML implemented one way and I thought it would be useful to explicitly describe that scenario: Someone using SAML to log into a website.

Important Vocabulary SAML:

User: In our case, the browser. More generically, whatever is trying to access the SP.
SP (Service Provider): In our case, the protected web page the User wants to access. More generically, whatever service the User is trying to access. The SP relies on the IdP for authentication.
IdP (Identity Provider): In our case, the webapp that authenticates users and creates SAML Assertions. More generically, whatever is responsible for identification.
SAML Assertion: A message created by the IdP and used by the SP. This message identifies a User who is authenticated.

How SAML Works:

Before an actual request comes in, the IdP and SP are configured to know about each other, know each other's SAML relevant urls, and to trust each other. The IdP and SP will never directly communicate with each other (unless you're using Single Logout).

The complete SAML flow looks like this:

  1. The User requests a protected resource (say, the index page) from the SP. The SP sees the user has no session in the SP (by comparing against a header or cookie in the HTTP Request.) So the SP redirects the user to the IdP url that is used for generating SAML Assertions.
  2. The User requests a SAML Assertion for the SP from the IdP. The IdP has no session for the user, so redirects the User to a url (either local or remote) where they must authenticate.
  3. The User requests the login page and then fills out the login form.
  4. The User posts the login information and is authenticated to the IdP. The user is redirected back to the IdP url to get a SAML Assertion.
  5. The User requests a SAML Assertion for the SP from the IdP. The IdP now has a session for the user, so it creates an encrypted SAML Assertion and returns it to the User. The IdP redirects the User to the SP url that is used for validating SAML Assertions.
  6. The User posts the SAML Assertion to the SP url. The SP validates the SAML Assertion. Using information included in the SAML Assertion (for example, an email or special uid), the SP can match the SAML Assertion to an internal user. The SP will create a session and redirect the User to the original resource they requested.
  7. The User requests a protected resource from the SP. The SP sees the User has a valid session and serves the resource.
The Confusing Bits

Does the IdP ever contact the SP for Authentication?

No. At least not that I've ever seen. The SAML Assertion is transported by the User. The SAML Assertion is encrypted so there's no need to be concerned about the Assertion being misused. Note that if the IdP is being used for Single Logout, then the IdP will need to be able to contact the SP.

IdP Initiated vs. SP Initiated?

You see these terms when you're looking into SAML. It seems confusing, but all it really means is whether the User goes to the SP first or the IdP first. So, following the flow I listed, it decides whether you start at Step 1 or Step 2. There's no other difference. It doesn't mean that SP communicates with the IdP. SP Initiated is almost certainly what you need to do and gives you more flexibility in what resource the User gets at the end.

Logout?

Logout is a special case that requires extra decisions. If a user logs out or is removed from an SP, should they be logged out of all SPs? Probably not. If a user's session or the user themselves are removed from the IdP, should they immediately be logged out of all SPs? This is up to the security requirements. If the User is not removed, the User will remain authenticated to the SP until the User needs a new session. This could be a long time. If the User is removed immediately, then the IdP will need a way to tell the SPs whenever a SAML Assertion is invalidated. This functionality probably requires the IdP to be able to contact the SPs. There's no right way of handling logout, it all depends on how the security of the system needs to work.

So how do I implement this?

OAuth is much more popular nowadays, but in case you need to support SAML for whatever reason, implementation is fairly straightforward. You generally write your own authentication piece, configure an IdP to know about you, and then point to the IdP. The IdP I'm familiar with is OpenAM, which was once upon a time called OpenSSO.

No comments: