migration-to-firebase-jwt-authentication-for-service-oriented-architecture
Engineering
Nov 4, 2022

Migration to Firebase JWT Authentication for Service-Oriented Architecture

Ahmed Ashraf
Backend Engineer

Our Supply Tools team helps GetYourGuide’s global suppliers deliver unforgettable travel experiences. As part of a wide-reaching move from a monolithic application towards microservices, migrating user credentials became a priority. Here’s how we did it.

{{divider}}

The Supply Tools team is responsible for providing the tools our suppliers need to help them deliver incredible experiences to our customers. Historically, the suppliers’ API project was one of many in our monolithic application. The authentication method we relied on before was session-based. That meant the entire monolith was aware of how to store the sessions, with a module to handle the login and retrieve different user types' information.

The authentication method worked well, but following the company-wide strategy to extract all APIs from a monolithic application to separate services (read more here), the Supply Tools team was faced with a new challenge: how to securely manage credentials of thousands of suppliers within the new infrastructure?

In this article, we will share how the GetYourGuide Supply Team migrated authentication and supplier credentials from session-based authentication to Firebase.

Moving to Microservices

In a microservices world, APIs are primarily stateless. That means session-based authentication is not going to work. One of the available authentication standards is JWT (JSON Web Tokens). The advantage of using this standard is that we don’t need to worry about storing the generated tokens in the backend; rather, client applications will store and send the token with every request to any of the supplier APIs. The API gateway will handle the validation of the token before passing supplier data to the targeted service.

JWT is a combination of three parts: header, payload, and signature. In the payload part, we can share public supplier info and permissions (claims). This means we know from the token if the supplier has access to the requested information or not. The signature is used to verify that the message wasn't changed along the way. You can read more about JWT here.

Firebase

Firebase is an application development platform. One of its features is Firebase Authentication. From Google’s description on the Firebase website:

“Firebase Authentication aims to make building secure authentication systems easy, while improving the sign-in and onboarding experience for end users. It provides an end-to-end identity solution, supporting email and password accounts, phone auth, and Google, Twitter, Facebook, and GitHub login, and more.

For the GetYourGuide engineering team, Firebase fulfills our use requirement of having JWT authentication with multiple ways to log in. We can readily enable login by email and password, as well as Google login, which is what we supported in the monolithic application.

Next Steps: Migrating Data

Having decided about technologies, the next step was to migrate suppliers' authentication data (name, email, password) from our database to Firebase. Then, allow the API gateway to validate the tokens coming with API requests and pass the information needed to the Supplier Service API. The result is that our and other services have access to the user information and permissions to decide whether to process the request or return an error response.

Solving the Password Problem

We expected migrating the records of the suppliers from the database to Firebase to be easy. Our proposed solution was to write a small script to iterate over suppliers and move each one to Firebase. That would take a couple of hours to finish, and only a single day to migrate all data.

However, it was not as straightforward as we had initially thought. Although Firebase Authentication supports several algorithms to hash passwords, the one algorithm we were using was not supported. We store hashed passwords and we cannot decode them into plain text. We had to think of another way to finish the migration.

After several iterations with one of GetYourGuide’s engineering guilds, we decided to migrate the data in a few steps.

First, we created a random unique password for every supplier. Passwords were generated during the migration script runtime and sent to Firebase. The team would never know the suppliers’ passwords.

Next, we modified the login logic in the monolith application to update the passwords. The monolith application updates the password in Firebase with every successful login.

Then in the frontend application, we modified the login page to talk to Firebase first with the email and password. If the Firebase login attempt fails, the application attempts to log in to the monolith. If that succeeds, the monolith updates the Firebase and the next login attempt to Firebase will succeed. The frontend receives a valid JWT token.

After deploying these changes, we started to see a few password migrations on the Firebase dashboard. We also set up our DataDog metrics to see how many users were fully migrated. A big percentage of our users were migrated in around two days.

Lastly, we dropped all sessions of our authenticated users to force them to log in again and speed up the password migration.

Move to Firebase Authentication

By this point we had most of our suppliers migrated to Firebase, the frontend was using Firebase SDK to handle logins, and the monolith was supporting both sessions and JWT authentication.

In order to finish the migration, remove the session tokens completely and make the system fully stateless, we implemented the JWT SDK in the API gateway. The API gateway validates the JWT token from the header and extracts the data from the payload (JWT claims) and sends it to the API endpoint of a Supplier Service API as new headers. That allows the Supplier Service and other services to authorize API requests without the complexity of JWT tokens.

For the monolith application, the API is protected by a middleware that always expects the user data decoded by the API gateway in headers. It loads the user object and persists it in the login module to support all of the internal packages and projects. This solution makes it easy to roll back to session-based authentication in case of any incident.

During our work on this migration, a big percentage of our suppliers were migrated and we were safe to just drop the monolith API fallback. Should Firebase return invalid credentials, the user can just reset their password through the forgot password page. Because suppliers are able to change their name, email, and other data, the internal API has access to Firebase to synchronize all these changes.

Conclusion

The process of migration was straightforward as we did not need to change the data or have a completely different way to authenticate users. The only bigger obstacle was the password hashing algorithm that Firebase did not support. If it was supported, we would simply loop over the suppliers’ data and migrate the hashed passwords. The migration process required multiple steps to ensure a good user experience for migrated users.

Thank you to former GetYourGuide Backend Engineer Ahmed Ashraf for writing this post.

Other articles from this series
No items found.

Featured roles

Marketing Executive
Berlin
Full-time / Permanent
Marketing Executive
Berlin
Full-time / Permanent
Marketing Executive
Berlin
Full-time / Permanent

Join the journey.

Our 800+ strong team is changing the way millions experience the world, and you can help.

Keep up to date with the latest news

Oops! Something went wrong while submitting the form.