Checklist for Auth Migrations
Authentication, like every other aspect of your product, needs to evolve over time. Sometimes, this means that you need to seek out a new auth solution entirely. Whether you're choosing a new auth provider, switching your in-house auth setup to an external provider or bringing your auth in-house, there's a lot to consider as you go through the migration process. This post will walk you through all the different factors to consider before you begin. This post won't discuss the reasons to migrate, as that's best saved for a different post.
Note: If you are looking for a guide to migrating to PropelAuth specifically, check out our docs. This post is more around the process in general.
What an auth migration looks like at a high level
Auth migrations typically consist of two parts:
- Migrating your users' login data
- Migrating your application code
How much work you have to do is dependent on how complicated those two steps are. As a probably obvious example, if you have no users yet, you don't have to migrate your users' data. Similarly, if all your authentication/authorization code is encapsulated in middleware, it'll be easier to migrate than if that code is scattered throughout your codebase.
There is, however, nuance in all the details - let's start by looking at migrating user data.
Considerations when migrating users
When you are migrating users, there are a few key questions to ask yourself:
Do you have user IDs in your database already? Would you prefer to keep those IDs or potentially change them?
Almost always, if you have users, you'll have your users' IDs stored in different places. Your database schema probably has user_id in pretty much any table that stores data per user. Typically, we recommend maintaining a mapping from what their IDs were in the old system to what their IDs are now after they are created in the new system, as this is also easier to reverse if anything goes wrong. Some providers will do this automatically for you, or let you maintain the same ID altogether.
If you are using a JWT / access token model, putting this mapping in the token itself means that you don't have any latency to lookup the old ID, you can just do something like:
const userId = user.legacyUserId || user.userId
What methods are your users using to log in? Do you need to maintain those existing methods or can you change them?
The data that powers different login methods is often sensitive. In some systems, you might not be able to maintain the exact same login options before and after. For one example, you may end up needing to tell your users that their two-factor authentication was automatically reset as part of a migration and they'll need to enroll again. There are two primary cases to consider:
Simple Case: Migrating users without passwords
There are many different ways a user can login and access your product. They can use passwordless magic links, they can use social logins (e.g. sign in with Google), they can use an email address and a password, etc.
The easiest user to migrate, is one that only uses social login SSO or magic links. That's because all you have to do is create the user in your new authentication provider - you don't need to maintain any sensitive piece of information about them like their password.
For magic links, the user experience should be exactly the same - they enter their email => they receive a link => they are logged in. The only piece of information you need to migrate this user is their email address.
For social login SSO, it's exactly the same. All you are doing is verifying with an external party that the user is who they say they are. If you maintain the same client ID and client secret, you don't even need the user to re-accept the scopes you are requesting.
Harder Case: Migrating users with passwords
If you have users logging in with passwords, you first want to decide how comfortable you are with asking users to reset their password. A simple email that just says "Hey, we switched auth providers, you'll need to reset your password next time you log in" (you may want to fancy that up a bit) makes this pretty easy, as it becomes the same as the case above where the only thing you need to migrate them is their email address.
If you don't want to reset your users' passwords, you'll need to obtain their existing password hashes. Most providers have some method for creating a user with an existing password hash, which will allow the user to log in with their existing credentials.
Note: Be careful with providers that don't give you access to password hashes. AWS Cognito doesn't export password hashes, meaning if you are using them, you can't easily migrate off of them without resetting all your users passwords. Auth0 only supports exporting password hashes on a paid plan and it takes 1-2 weeks, so you need to plan accordingly.
Where is authorization information (e.g. roles, permissions, tenants, organization membership, scopes, etc.) stored, and can it remain there or does it need to move to the new provider?
If you are using an auth provider purely for authentication and you are managing the authorization yourself, you might have a simpler time migrating as you only need to migrate the authentication piece. If, however, your current or new provider also manages authorization, you'll want to make sure that you can appropriately map the user information from the old world to the new world.
Updating your code
Once your data is migrated over, you'll likely need to update your code as well. This is hard to give specific advice on, but one way to make this process easier is to keep your authentication and authorization code as contained as possible.
At PropelAuth, some of the easiest migrations we've ever done have been cases where our customer had some code that looked like this:
function requireUserIsLoggedIn(request) {
const authHeader = request.headers.authorization;
const user = // validate authHeader with existing framework
return convertToOurOwnType(user)
}
where we just had to replace a few lines of code in their well-abstracted functions. This, however, gets more challenging as the number of places in your codebase that perform authN/authZ checks increases.
Different strategies for migrating
Now that you know the broad strokes of what you need to do, let's look at a few different ways to do it.
Switch entirely in one go
One of the simplest options is to do it all in one go. You start by migrating your code and test that the migrated codebase works. Then you migrate your users and deploy the new codebase. This is one of the most common approaches and has an added advantage of being reversible as long as you didn't destroy your existing setup.
Falling back to the existing system
Another option is to try and keep both providers around for a period of time. Instead of migrating all your users, your auth code would end up checking the new system first and then falling back to the old system. This can make aspects of the migration easier (and in some cases like AWS Cognito, is the only way to avoid reseting all your user's passwords), but it does lead to a lot more code complexity than the previous approach.
Only a subset of users can use the new system
One way to do the rollout is the segment your users and use your old authentication system for some and new authentication system for others. If you are migrating because you need enterprise SSO / SAML for a large customer - you can consider having just that large customer use the new system at first.
One of the nicest ways to implement this is with OAuth. We won't cover all the details of OAuth in this post, but an easy way to think about it is for some providers (e.g. NextAuth), you are able to add other providers as an additional login option.
There still is some complexity here as you need to make sure that users are directed to the right login method, and so this is most commonly seen when you are adding something like SSO / SAML - the existing provider handles the regular users, the new provider handles the enterprise users. This has the added advantage of maintaining existing user sessions.
Summary
If you are considering switching your authentication, you'll want to have a good plan in place ahead of time. Sometimes, this is as simple as "We'll migrate all our users, swap out the codebase, and it should all work." In other cases, you can do things like "Our current provider stays in place and manages sessions, but we're adding a new provider to handle just getting the SSO customers in the door."
Looking to migrate?
If you stumbled on this post, you might be interested in switching auth providers 🙂
At PropelAuth, we've seen all different types of migrations and we'd be happy to help/advise with yours. Feel free to reach out to support@propelauth.com and we can talk through your specific case!