JumpCloud Integration for Advertising Applications
Most of the applications we use at GumGum are accessed through JumpCloud (e.g: Slack, Zoom, Sumologic). Users are already familiar with this tool, and keeping a single login for all of them is a great advantage. However, for our GumGum developed applications, we were using Okta for handling the login, and each application had its own login.
The disadvantage of having all the applications in Okta was that it was not straightforward for the users, for the following reasons:
- They have to keep another username and password.
- The flows for forget and reset passwords were not intuitive. (They had to click a link which redirected them to another application, then received an email, and they had to complete the flow on Okta. This is customizable, but we had not prioritized improving this workflow.)
Besides all this, the information for all the internal users is already on JumpCloud and handled by our IT department, which means that we have duplicated user info in Okta.
Due to all of these reasons, we set out to completely improve the way we log into our applications and create a better user experience for all of our users. Considering all this, we decided to move forward and provide a way for the users to enter all our GumGum developed applications through JumpCloud.
Unifying our current authentication and login systems was one of the main objectives of this project. We have many applications that use different log in systems. Two of them used an Okta instance through one microservice we built, another application used a separate Okta instance through the same microservice, one of our external applications had its own login system, and two more had another self developed system. Our self developed systems also used Okta for token generation since it is required to use our central API.
We had a few different scenarios to consider:
- JumpCloud is only used for our company employees, so internal users will use JumpCloud.
- Depending on the application, we have to support both internal and external users. We will need to migrate external users separately to have a different user flow.
- GumGum recently acquired JustPremium and those users were not yet integrated into JumpCloud, so we still needed to support the old way for them using Okta accounts.
This can be summarized as follows:
- As described in the use cases, we needed to support both internal and external users, and only internal users are in JumpCloud.
- Since all the users were in Okta, we had to migrate them to our database and determine their user info, access, and roles.
- Some of our internal users were not yet on JumpCloud, so we needed to provide a temporary way for them to log into the applications until they were migrated to JumpCloud.
- In order to integrate with JumpCloud, we needed to implement SAML protocol; however, all of our applications used OAuth protocol and our API is a JWT Rest based API.
The following diagram illustrates how our applications worked with Okta:
GumGum Application could be any of our developed apps; each of these has an Okta widget login that will provide the login screen to the user. The flow as shown in the diagram would be as follows:
- User logs in, the application will get a token from Okta. This would be a two step process where first it will get an id token and then the application will use a callback to interchange this for an access token.
- Once the login is completed, the application will store the token that will be used for subsequent operations call to the backend (API).
- Users can do any operation by sending an authorization header (Bearer TOKEN). The API validates the token and if it’s valid, will return the results.
SAML Stands for Security Assertion Markup Language. The protocol is based on transferring the user’s identity from one place (the identity provider, aka IdP) to another (the service provider, aka SP). This is done through an exchange of digitally signed XML documents.
There are two SAML authentication workflows: IdP initiated SAML authentication and SP initiated SAML authentication. Some service providers only support SP initiated requests.
Logging into a Web-based Application Using IdP (Identity Provider) Initiated SAML Authentication
- A user enters their credentials in the IdP.
- The IdP authenticates and authorizes the user.
- After logging in, the user navigates to a list of web-based applications they can access, and selects the one they want to use.
- When the user clicks on the web-based application, the IdP sends a SAML assertion to the SP.
- The SP receives the SAML assertion and does a few things:
- The SP checks to make sure the assertion is valid and authentic.
- The SP finds out who the user is and how they should be logged in.
- The SP gives the user access to the application without requiring them to log in again.
Logging in to a Web-based Application Using SP (ServiceProvider) Initiated SAML Authentication
- A user navigates to a web-based application’s login page and enters their username.
- The SP behavior varies, but many detect that SAML SSO is involved, and redirect the user to an IdP login page.
- The user enters their credentials on the IdP login page.
- The IdP authenticates and authorizes the user, then sends a SAML assertion back to the SP with the information it needs.
- The user is redirected back to the SP with access to the application.
In our case, the IdP is JumpCloud, which also acts as a SSO, and SP is the service provider which could be any of our applications. We implemented both workflows as described above, so users can log into any application through JumpCloud or through the application itself.
Since most of our apps already support JWT to interchange information with our API, it was desirable to continue with this approach. So we came up with an approach that keeps the minimum set of changes on the frontend applications and backend, and allows us to keep JWT and encapsulate the complexity of supporting SAML from the existing apps. JumpCloud allows single sign-on in both directions, so users can login from the JumpCloud console or the application that we integrate it with, by implementing SAML.
We created an application that implements SAML and encapsulates all this functionality and allows the user to access all the applications without having to log in to each one of them. This application, called Advertising Auth App, is in charge of implementing SAML, and users can see this new widget on their JumpCloud console.
For creating this application, we selected Express since it’s a fast and simple framework to build Node.js applications, plus there are a good amount of libraries that offer SAML implementation that we could use. The summary of the tech stack we use is:
- Express — we use this framework to generate the Node.js application for this app.
- Samlify — this Node.js library helps implement SAML in a very simple way and encapsulates all the complexity related to SAML messages, parsing, etc.
- Advertising API — we use our existing API for getting all the user related info.
- Jose — this is a library widely used for everything related to JSON web tokens, in our case we are using it to create a secure token and decode it.
The new solution implies differences with the approach we had using Okta, which can be seen in the following sequence diagram:
The steps the users take to login with the new authentication through JumpCloud are:
- The user accesses any of our applications.
- The application validates if there is an available token in the storage and that is a valid one (if the user is already logged in or not).
- If not available, then the user is redirected to Advertising Auth App. This application is integrated with JumpCloud, and therefore if the user has not logged in, it takes the user to the login and returns a SAML response.
- Advertising Auth App generates the corresponding JWT from the information on the SAML response, and then shows the application menu to the user.
- The user selects the app to enter and then is redirected to that application with the corresponding valid token, this can be used later to call any endpoint on our API.
In the previous scenario, we show how it will be for the user when first entering the app, and requires a login. The token that we generate is long lived so it can be used for a few days; after this period it will request a new login. If the user accesses the application and the user is already logged in (means that there is an available valid token), then it will access the application directly.
Since we have implemented both sides of the integration, allowing login through JumpCloud or through the application, users can also enter through JumpCloud if they prefer. In that case, they will see a new widget that will show them a menu with all the available apps for their role.
So far we have successfully migrated three of our applications with little disruption to our users.
Since we have to also manage users’ roles and access, we created a simple UI that allows us to manage users and add roles. It will simplify the process and can be used by IT or our team whenever a new user is hired.
For now, external users are still supported as it was, and Okta has not been fully deprecated yet. Our next project will be building a solution for external users not based on Okta with our own mechanism defined for login and related flows.
There are a lot of advantages on the solution implemented that we can summarize as follows:
- Unified authentication for all GumGum developed applications.
- Simplification of users’ stored data; now users are stored in the database for application specific information (user data and roles), and for SSO we use the directory that is already in place (JumpCloud), meaning no duplication of information.
- Improved user experience for internal users. They only have to handle one password, and there is no longer need for the forgot and reset password flows that were complicated for them.
- Simplified workflow for creating new users (new hires).