Single-Sign-On with SAML
Nowadays single sign-on authentication scheme is extremely popular. A lot of web services provide a convenient way of authentication - “Single-Sign-On” or SSO. It allows users to use just a few accounts of SSO providers to authenticate in the many apps.
There are several reasons why Single-Sign-On was designed. The first is that it improves the end-user experience. People usually don’t like to remember a whole lot of passwords from all the web sites or applications they use. With SSO, users only need to maintain a small number of accounts that they can use for the purpose. On the other side, developers don’t need to create a reliable and secure user database. This task is delegated to single-sign-on providers.
There are different algorithms that implement SSO. Some of them do authentication but others do authorization only. In this article, we’ll take a closer look into SAML flow, which deals with authentication. Though it’s rather old it is still very common.
SAML model
There are two parties in the SAML protocol. The first are Service Providers (SP) – apps that use SSO for authentication. The second are Identity Providers (IdP) – ones that provide SSO service. IdPs manage user accounts: they store credentials, check passwords, etc. IdPs are usually either tech-giants or services created specifically for Single-Sign-On needs. Behind the scenes, SAML uses XML for data exchange and PKI signatures for data assertion.
Sign on
When a user logs in to an app implementing SAML here is what happens:
- User accesses the App (Service Provider) and clicks “login”
- App creates a request to an Identity Provider asking for authentication.
- Identity provider checks if the user is logged in or prompts the user to enter their credentials.
- Identity provider builds a response including authenticated user id. Then it signs the response using an X.509 certificate and sends it back to the Service Provider.
- Service Provider receives the response from IdP and checks its validity. If the response is correct it logs the user in, establishing the user’s session in the App.
The picture below illustrates the concept
It’s worth mentioning that if IdP doesn’t have a session yet it will ask the user to provide credentials. But once IdP establishes the user’s session there is no need to enter credentials each time the user logs in.
Sign out
Sign-out flow requirements differ from app to app, and its implementation with SAML always depends on the architecture of the given SP. Because of that, sign-out flow is a little bit tricky, and there isn’t any standard approach everyone uses. Moreover, it always has some flaws in it, because of the next reason: If a user uses SAML to log in to apps, there are sessions in every app and in the identity provider. Let’s take a look at a couple of scenarios, that are the examples of so-called “Service Provider initiated sign-out”. “Service Provider initiated sign-out” literally means that the user pressed the “logout” button in the SP.
If SP kills the IdP session during sign-out then the user will have to re-enter credentials to access IdP. This is especially bad if IdP is something like Google because SAML IdP is only a minor feature of it’s widely used Google Accounts system. Imagine you used Google to authenticate in the App, which kills IdP session during sign out. If you log out of it and go to Gmail, you will be suddenly asked for a Google password. This is because SP removed the IdP session as well, without letting you know. It’s not something you expected to happen, isn’t it? Well, I doubt if this trick works with Google, it’s here only to give an idea.
But, if SP only kills its session and doesn’t affect IdP session, it may become a serious vulnerability. Imagine you logged into an app from another’s device, or from a corporate device, which many people use. The IdP session will live there even after you pressed “log out” because it is not removed by SP. Next time anyone tries to log in to the same app you did before, the SSO prompt will bring them to your account.
The solution for these problems depends on the way your app uses SAML, the IdP you use, and many other factors. However, there are a few approaches you can take to resolve the issues:
- Provide the user with a choice: to log out from SP only or from IdP as well.
- Use short-lived sessions in Service Providers and Identity Provider or sessions that expire when a browser tab is closed.
Next, there is an IdP initiated log out. This may be used if a user wants to log out from every Service Provider at once. There are also a few options on how to do this. Logout from IdP only may be enough if SPs maintain short-lived sessions, so they will expire soon. This is called “simple logout”.The other way is to kill sessions on both SPs and IdP ends which is “single logout”. The flow is the following:
- IdP gets the list of all Service Providers that user previously logged in to.
- IdP makes several consistent requests to SPs forcing each one to log out
- Once every SPs logged out the user, it clears its session.
The idea is illustrated below
Usually, this flow is harder to implement because IdP needs to store the list of all Service Providers that the user logged in to. Also, it requires more complex error handling. For example, this flow has to deal with sign-out errors in Service Providers, for whatever reason SP may refuse to log users out - either they are already logged out or due to server error.
To sum up, single sign-on can help to improve user experience and enhance your app’s security. Make sure you implement it in a way that fits your needs the best, as it provides a lot of customization.