Simplifying Authentication: Halodoc's SSO Story

Authentication Dec 15, 2023

We all idealize a world, where we never have to memorize any passwords (from our birthdays to our favourite personalities, we drag everything into our passwords) and can directly log in to any account. SSO is a huge step forward in this direction. It is way better than the traditional way of logging in, both in terms of convenience and security. This is exactly the reason why SSO has been very popular for a while. Here is what one of Webhostingbuzz.com's reports says about SSO:

86% of people are bothered by having to create a new login for each website. 77% say that social login is a good solution.

Also, Kevin White, Marketing Manager at Gigya ( An Identity & Access Management Company) says,

Adding an SSO option typically increases sign-ups by 20-40%

What is SSO?

Single Sign-On (SSO) is like having a magical key that unlocks many doors.

It means using a single username and password to access multiple websites or applications, saving you from the hassle of remembering a bunch of different usernames and passwords.

You log in once, and that login is your master key. Whether checking your email, using social media, or shopping online, SSO enables you to move seamlessly between different websites or apps without the need to log in every time. It's like a time-saving, digital magic key that simplifies your online adventures. If you want to understand more about SSO, you can check out this blog.

Why did we decide to go with SSO at Halodoc?

We at Halodoc went live with SSO earlier this year on one of our internal websites. The non-technical staff uses this to gather, manage, and modify data on our public-facing website and native mobile application.

Earlier we had a traditional username and password kind of login. While this was okay initially, as the number of people joining and leaving the organization increased, it became a hassle to manage all the users. Every time a staff wanted access to the website, a super admin had to create an account giving a temporary username and a password which the user had to change later. Also when any staff leaves the organization, it becomes very important to delete the user from the system to ensure he cannot access it.

Even though the application itself can only be accessed through the organization's VPN, security becomes really important for a website like this, since it can be used to directly modify/access data in an attempt to harm the organization. And with SSO, it's really easy to manage this. Since a user can only log in to the website using his company email ID, and deactivating the employee's company email ID is a standard protocol post employee separation, we do not need to do anything explicitly at the website level, to block the user accessing the internal website.

How did we implement SSO?

Before diving into the technical details, I want to shed light on the tech stack used in our application. So, we are using Angular at the frontend, and Spring MVC Java framework (Java 17) for the proxy and backend and Postgres database.

First, we created a project in the Google API console for SSO specific to a single application, which will give us a clientId and clientSecret. Also, we will need to authorize domains and redirection URLs in the console as shown in the image below. This console can also be used to configure the consent screen which will be displayed to the user during login.

Authorized Javascript Origins & Redirection URLs

At Halodoc, we use the Spring Security framework to handle authentication and authorization. It is a highly popular framework used in Java applications across the globe. Spring Security supports OAuth2, we just need to install one additional package i.e. spring-security-oauth2-client . There are different libraries for different tech stacks, google-auth-library is one such popular library for Node JS.

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-oauth2-client</artifactId>
  <version>5.6.2</version>
</dependency>
pom.xml

Let me walk you through the high-level flow of how things work under the hood:

  • A user lands on the login page and clicks on 'Sign in with Google,' which looks something like this:
  • The OAuth2 login flow is initiated when the user clicks on Sign In With Google, after which the user will be redirected to a particular URL as specified in the proxy which triggers the authorization request.
  • Upon receiving the authorization request, Spring Security’s OAuth2 client redirects the user to Google's Authorization URL.
  • The user will then interact with the provider's page. If the user is not already logged in, he will be asked to log in. This is where the user can see all application names and the kind of info that will be shared with the app, if the user decides to proceed.
Provider Sign-in Page
  • If permission is granted, the provider redirects the user to the callback URL with an authorization code. If permission is denied, the user is redirected to the same callback URL with an error.
  • We should also provide a success and failure handler in the Spring Security config file. In case of an error during the OAuth2 callback, Spring Security invokes the specified failure handler, where we redirect the user to the /403 Access Forbidden page.
403 page
  • If the OAuth2 callback is successful and contains the authorization code, Spring Security exchanges the authorization code for an access token and invokes a custom user service which should extend DefaultOAuth2UserService class from Spring Security.
  • This custom user service retrieves user details and fetches the user based on email. If the user doesn't exist, an exception is thrown, invoking the failure handler. This step is necessary for our application since it is an internal one and anyone outside the org should not be able to gain access to it. A public-facing website will generally have a slightly different approach, where if the user is not present in the database then either a new account will be automatically created or he/she will be asked to sign up instead of sign in.
  • Finally, if everything is successful, the success handler is invoked, redirecting the user back to our application.

Here is a flowchart representing the same:

OAuth2 Login Flow

Let me also show you a sample code as to how spring security is configured in the proxy.

Sample code to configure SSO using spring security 

Challenges we faced

We faced 2 challenges mainly, during the process of implementation of SSO

#1. Email Collection

At Halodoc, since we had a username (which didn't have to be an email ID) and password form of authentication before SSO, we had no data regarding the user's email ID. So first we had to add a column in the user table to store the email ID.

Then we had the task of manually collecting all the active users' email IDs. Initially, when we were brainstorming about this, there was a discussion about showing a UI to the user to input their email ID as soon as he logs in with the traditional approach to automate the email collection process. But building a UI for something that we will not be using once all the users are migrated to SSO seemed like an overkill and not a good use of our time. And since the number of users who needed access to the website was relatively less i.e. around 1600, we went ahead with the manual email collection. Once the emails were collected, we ingested this data into the user table.

#2. Local Developer Setup

Now that we had built this feature, it was also necessary to create awareness about this among the other developers in the organization. Unlike other features where devs directly rebase from the master branch and run the code without any hassle, every developer had to make some changes in their local DB as well. Executing the following SQL commands:

-- Add email column to user table
ALTER TABLE {{ user table name }} ADD COLUMN email varchar(255) NULL;

-- Add unique key constaint to email column
ALTER TABLE {{ user table name }} ADD UNIQUE ("email");

--- Map email id to existing user
UPDATE {{ user table name }} SET email = '{{ company email id }}' WHERE username = '{{ previous login username }}';

Although not a big challenge, I wanted to bring this up just to highlight the impact of planning and integrating SSO early. For anyone building a new website in today's time, it's a no-brainer to integrate SSO.

Conclusion

In conclusion, the implementation of SSO at Halodoc has marked a transformative shift in user authentication, significantly enhancing both security and user experience. It has also largely, simplified and streamlined our employee onboarding and off-boarding process.

The entire implementation process, however, did pose its challenges, from the manual collection of email addresses to the adjustments in local developer setups. However, these challenges were met with strategic solutions, ensuring a smooth transition for users and developers. And building it during the initial phase can help you avoid some of the hurdles we faced.

Discussions are currently underway regarding the implementation of Single Sign-On (SSO) in our publicly accessible Halodoc application as well. However, due to the pervasive use of mobile numbers as the primary form of identification throughout our application, coupled with the challenges  of migrating a large-scale application, we are proceeding with caution. As mentioned earlier, this underscores the importance of integrating SSO during the initial phases.

As we embrace the power of SSO, we envision a future where authentication methods continue to evolve. At Halodoc, we're excited about the possibilities that SSO brings to the ever-evolving landscape of digital authentication.

References

  • Spring Security OAuth2 Documentation : https://docs.spring.io/spring-security/reference/servlet/oauth2/index.html

Join Us

Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels and if solving hard problems with challenging requirements is your forte, please reach out to us with your resume at careers.india@halodoc.com.

About Halodoc

Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke. We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 3500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allow patients to book a doctor appointment inside our application. We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek, and many more. We recently closed our Series D round and in total have raised around USD$100+ million for our mission. Our team works tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.

Pravesh S Shetty

SDE 1 at Halodoc