Single Sign-On (SSO) distilled
Hello folks. Welcome to this blog post about SSO. Here, through a series of posts, I will be writing all about SSO and ways of implementing it in your applications. I will also talk about the obstacles we faced while implementing this recently and the ways we overcame them.
So… let's start without any further ado. 😃
First, let's get some basic info about SSO.
What is SSO?
Single Sign-on(aka SSO) is an identification system that makes it easy for applications to verify users by using other trusted sites. This enables businesses to avoid the hassle of storing and managing user details like passwords and also cuts down on troubleshooting login-related issues. With SSO configured, the applications check with an SSO provider (such as Okta, Google, Microsoft) to see if it can verify the identity of the user. If it can, the application takes their word for it.
Types of SSO
There are different standards and protocols when working with SSO. The prominent ones are as below,
- Security Access Markup Language (SAML)
- Open Authorization (OAuth)
- OpenID Connect (OIDC)
Details for each type can be found at SSO Information
In our example implementation details we will be using SAML 2 as a standard for the authentication flow. Also, we will be building the Service Provider(SP) initiated authentication workflow using SAML 2. To know more details about sign-in flows initiated by Service Provider or the Identity Provider(IdP), please read them on SAML Details
Implementation
For our implementation use case, let's assume we have 2 microservices, one running the UI for the application and the other dealing with authentication stuff on the backend. The SAML 2 authentication flow can be described with the help of the diagram below,
Thanks to Klaus Nji for putting together this workflow diagram.
Various steps in the workflow are as below,
- The login request is initiated by the UI when a user enters his/her email and clicks Login.
- The backend then handles this request and redirects the user to the IdP. (This can also be handled differently and I will share that in another post soon)
- IdP fetches this request and loads up the login for the user.
- The user enters the login credentials as configured with the IdP.
- This login request is sent to the IdP for processing. This is where IdP authenticates this user.
- IdP then sends back an encoded assertion response that has authentication details along with the user’s demographic information requested by our application. IdP sends this response to /saml/acs endpoint that will have to be exposed by the application.
- Backend service then performs some actions to maybe persist this data and finally redirects back to the application’s homepage.
Hurray! The user is now authenticated and can access the application. As you might have noticed, the login request was initiated by our application which is the service provider and hence this is Service Provider(SP) initiated SAML 2 auth workflow.
For our implementation, we happened to use this SAML library for handling the core workflows for SAML 2-based auth. It supports both use cases of initiating authentication requests as an SP as well as IdP. It's a rich library with clear contract interfaces for critical operations that allows you to have a customized implementation for them.
So, in a nutshell, this is one way of handling SAML 2-based SP initiated authentication. Seems easy, isn't it? Ya.. we thought the same but wasn't as easy as it looks like. We faced multiple challenges along our way in implementing this that I will discuss in my next posts.
Stay tuned…Until then, Happy coding!