Migration From Frontegg

Overview

This document will help you migrate users from Frontegg to FusionAuth.

This guide is a low-level, technical tutorial focusing on calling APIs and preparing data when migrating users from Frontegg. To understand how to plan a migration at a higher level, please read the FusionAuth migration guide.

Prerequisites

To follow this tutorial, you need:

  • Node.js to run the migration scripts, and npm.
  • FusionAuth. The easiest way to run FusionAuth locally is to use Docker with the configuration file provided later in this tutorial.

Planning Considerations

Obtaining User Data

While the Frontegg platform allows you to export your user data using its API, it does not allow you to export user password hashes. This means you cannot migrate your user passwords into FusionAuth and allow your users to log in if you do a bulk migration. Your users will need to use the FusionAuth forgot password flow to set a new password and log in.

Here is how a bulk migration process might work:

  1. Export all user data from the Frontegg API, except password hashes.
  2. Convert the user data into FusionAuth-compatible objects and import the data into FusionAuth.
  3. Have your users use the forgot password flow to change their passwords.

If you are willing to perform a gradual migration, also known as a slow migration, you can allow your users to log in to Frontegg via FusionAuth, and have FusionAuth transparently migrate their data. Slow migrations in FusionAuth use Connectors, a paid feature.

A slow migration would look like this:

  1. Export all user data from the Frontegg API, except password hashes.
  2. Configure a FusionAuth Connector to call an intermediary web service whenever a user logs in.
  3. Write the intermediary web service that will call Frontegg with the user’s credentials and save the password to FusionAuth.
  4. Once you have migrated a large enough portion of your users, you can switch off the Connector and cancel your Frontegg subscription.

This tutorial will cover all the bulk and slow migration steps.

Mapping User Attributes

The attributes of the User object in FusionAuth are well documented.

If there is an attribute in your Frontegg user which cannot be directly mapped to a FusionAuth attribute, you can place it in the user.data field. This field can store arbitrary JSON values and will be indexed and searchable.

Social Logins

Frontegg also provides integrations with other social login providers such as Twitter, Google or Facebook. Review the supported FusionAuth Identity Providers to ensure your social providers are supported.

If not supported explicitly, a provider may work with an OIDC or SAML connection. Otherwise, please open a feature request.

Migrating users with social logins such as Apple or Facebook requires that you have an existing user Id for that provider. What this unique user Id looks like depends on the particular social identity provider. The unique Id may be an email address, an integer, UUID, or a random string.

Configure the appropriate FusionAuth Identity Provider with the same values (client_id, etc) as the original user management system you are migrating away from.

Import users with the Import API, assigning each user with a social login a random password such as a UUID.

Your next step depends on whether the social login provider’s unique identifier is available as part of your migration data. If you have the social login provider’s unique identifier, for each user, use the Link API to create a link with the appropriate User Id, Identity Provider Id and Identity Provider User Id.

  • The User Id is the Id of the recently created FusionAuth User.
  • The Identity Provider Id is found on the corresponding Identity Provider API documentation. Look for identityProvider.id .
  • The Identity Provider User Id is the existing social provider user identifier exported or otherwise extracted from the original system.

You do not need to migrate the social network token, which may or may not be accessible. During the first login of a newly migrated user, FusionAuth finds the unique user in the social login provider based on the migrated Identity Provider User Id, and completes the login. During this process, FusionAuth stores a token on the Link, if the social provider returns one. Depending on the configuration of the social provider, users may see a prompt asking if they want to allow FusionAuth to have access to user data such as email address.

IdP Linking Strategies are available since version 1.28.0. Before that version, users were linked on email.

If you do not have the social login provider’s identifier, you need to decide if you want to transparently link the two accounts, which is easier for the end user, or if you want to ask the user to manually link the accounts, which is more accurate, but may be confusing.

To transparently link the accounts, choose a linking strategy of Link On Email or Link On Username, which will create the user if they don’t exist. However, if the user has an email address at their social provider which differs from the email address that was used to sign up for your application and which you imported to FusionAuth, then two accounts will be created.

For example, if the user has a Google account richard@gmail.com, but signed up for your application with richard@fusionauth.io, then if you use the Link On Email strategy, two different accounts will be created, since FusionAuth is trying to match on email address and they don’t. The same holds true for usernames with the Link on Username strategy.

To prompt the user to link the accounts, choose a linking strategy of Pending, which will prompt the end user to sign into FusionAuth after they sign into the social provider, authoritatively linking the two accounts.

Here’s more information about IdP Linking Strategies.

Other Entities

There are often other important entities, such as connections or roles, that need to be migrated. There are usually fewer of these, so an automated migration may not make sense, but plan to move this configuration somehow.

Be aware that functionality may not be the same between Frontegg and FusionAuth. This is different from user data; as long as you can somehow migrate a login identifier (a username or email) and a password hash, a user will be authenticated and successfully migrated. You can download FusionAuth before you begin a migration and build a proof of concept to learn more about the differences.

A partial list of what may need to be migrated for your application to work properly includes the following:

  • In Frontegg, a role is a collection of permissions that can be assigned to a user or application. FusionAuth has roles that are configured on an application-by-application basis and made available in a token after successful authentication.
  • With Frontegg, you can use groups to organize a collection of user identities to manage access to applications. FusionAuth also has Groups.
  • Frontegg uses tenants to define sets of users and help you manage users. You can also manage a set of users via a Tenant in FusionAuth.

Identifiers

When creating an object with the FusionAuth API, you can specify the Id. It must be a UUID.

This works for users, applications, and tenants, among others.

Frontegg User Structure

Frontegg has customers (that’s you) called vendors. Each vendor has customers called users, grouped into tenants. Tenants are grouped into environments (such as development, QA, and production). Below is an illustration of an example user structure in Frontegg.

Frontegg user structure

Note that tenants are called accounts in the Frontegg web portal. FusionAuth also uses tenants to group users.

Permissions work slightly differently in the two systems. FusionAuth and Frontegg both group permissions into roles, and assign roles to users. A user then has all the permissions associated with that user’s roles.

However, Frontegg also supports assigning permissions directly to a user using features. FusionAuth does not support this. If you have used Frontegg features, you will need to map features to FusionAuth Roles in your migration script. Below is a Frontegg illustration of the platform’s permissions structure (which Frontegg calls entitlements).

Frontegg entitlements

Bulk Migration

Be aware that the steps outlined for bulk migrating users from Frontegg will not export password hashes, and users will need to change their passwords using the forgot password flow on FusionAuth.

Exporting User Data From Frontegg

In this section, you create two sample Frontegg users in the web portal and export them with the API.

If you have existing users, you can use them to follow this migration tutorial. If not, add users as described below.

  • Log in to your account at https://portal.frontegg.com.
  • Add an environment, like Development.
  • Navigate to Environments -> Development -> Env settings and note your Client ID, API Key, and Login URL.
Frontegg environment settings
  • In the environment’s Backoffice -> Accounts , create a new account (tenant) called a.
  • In Backoffice -> Users , create two new users called a and b assigned to account a. Assign roles for the users. The default roles available are “Admin” and “Read Only”. For the user email addresses, you can use most web email addresses with an alias. For instance, if you use Gmail and your address is myemail@gmail.com, you can give the two new users the email aliases myemail+a@gmail.com and myemail+b@gmail.com. Emails sent to the users will come to your inbox.
  • For each user, open the hamburger menu on the right and click Edit user & Metadata . Give them some JSON metadata (like {"country": "france"}) and save.
  • When you receive the welcome emails for these users, verify them by clicking the link.

You’re now done working with the Frontegg web portal and have sample user data to test a migration.

Export The Users With The API

FusionAuth provides export and import scripts under a permissive open-source license. To get the scripts, clone the Git repository.

git clone https://github.com/FusionAuth/fusionauth-import-scripts

The frontegg directory contains all the scripts you need for this tutorial, and frontegg/exampleData has the output of the scripts.

Navigate to the frontegg/src directory.

cd fusionauth-import-scripts/frontegg/src

Install the required npm dependencies by running the following command.

npm install

Export your users from Frontegg by running the command below. Use the Frontegg client Id and API key you noted in the previous section.

node 1_exportUsers.mjs yourclientid yourapikey

This command will create a users.json file in the current frontegg/src directory. The users.json file should contain user data similar to the data in exampleData/1_fronteggExport/users.json.

The 1_exportUsers.mjs script makes two calls to the Frontegg API:

  • httpClient.get('identity/resources/users/v3') gets all your users and some basic data on each.
  • httpClient.get('identity/resources/vendor-only/users/v1/' + user.id) gets comprehensive data for each user, including roles, but not features.

Create Roles For Your Users

If you look at exampleData/1_fronteggExport/users.json, you’ll see the users have two roles, ReadOnly and Admin, in the keys.

       "tenants": [
            {
                "tenantId": "1d378739-a1ac-4a79-9d2f-e7eb53e6dcd7",
                "roles": [
                    {
                        "id": "f4c43bb0-d9ae-4837-8a97-8688abcd8404",
                        "vendorId": "0d0c5e4b-6c5c-4a85-96fc-7c17b31ee36a",
                        "tenantId": null,
                        "key": "ReadOnly",
                        "name": "Read Only",

You need to add these role names in your FusionAuth Application. Users will be linked to an application through a registration object, which includes the role. If the users in your exported data have different role names to the ones in the example data, change them in the script frontegg/src/2_addRoles.mjs. The role UUIDs are random in this script — you can use any Ids you like, including the ones matching the UUIDs of your roles in Frontegg.

To use this script, you need an instance of FusionAuth running. Start a local instance of FusionAuth running in Docker by running the commands below in a new terminal.

cd fusionauth-import-scripts/frontegg/fusionAuthDockerFiles
docker compose up

FusionAuth will now be running and accessible at http://localhost:9011. You can log in to the FusionAuth admin UI with admin@example.com and password. The container is called fa.

This configuration makes use of a bootstrapping feature of FusionAuth called Kickstart, defined in fusionauth-import-scripts/frontegg/fusionAuthDockerFiles/kickstart/kickstart.json. When FusionAuth comes up for the first time, it will look at the kickstart.json file and configure FusionAuth to the specified state. In summary, the defined Kickstart sets up an API Key, an admin user to log in with, and a Test application in FusionAuth.

In another terminal, navigate to the frontegg/src/ directory. Now you can run the role creation script below.

node 2_addRoles.mjs

Now in the FusionAuth admin interface, if you browse to Applications —> Test and click the Manage Roles button, you can see the roles have been added for your sample Application.

Roles added to the import application

Prepare Users For Import To FusionAuth

The next script, 3_convertFeUserToFaUser.mjs, is the most important. It maps the fields of users.json to FusionAuth fields. You may wish to alter this script to change which fields are ignored, or where they are mapped.

The script uses stream-json, a JSON library that can incrementally read massive files with millions of users. It opens the users.json file for reading in the line new Chain([fs.createReadStream(inputFilename), parser(), new StreamArray(),]);. For more information, read https://github.com/uhop/stream-json. The processUsers() function calls getFaUserFromUser() to map the Frontegg user to FusionAuth, and then saves the user to an faUsers.json file.

The getFaUserFromUser() function does a few things:

  • Maps as many matching fields from Frontegg to FusionAuth as possible.
  • Creates a random UUID in plain text for the user password. This will require users to create a new password when logging in to your application after migration.
  • Stores all Frontegg user details that don’t map to FusionAuth in the JSON data field. This is where the Frontegg metadata field is saved to.
  • Adds FusionAuth User Registrations (the link between a FusionAuth User and an Application) to users. You will need to change these Ids to match those of your application when doing a real migration. This section is marked with TODO.

Carefully read this function and make sure that the user information you need is imported correctly. If any information is not needed, you can comment out the related lines.

If you are uncertain about what a user attribute in FusionAuth does, read more in the user guide, as linked in the general migration guide recommended earlier.

In a terminal in the fusionauth-import-scripts/frontegg/src directory, run the script with the following command.

node 3_convertFeUserToFaUser.mjs

The script will output users ready to import to FusionAuth to the faUsers.json file.

Save The User Details To FusionAuth

Now you’ll run the Node.js import script to import the users into FusionAuth.

In a terminal in the fusionauth-import-scripts/frontegg/src directory, run the command below.

node 4_import.mjs

This script uses the FusionAuth SDK for Node.js @fusionauth/typescript-client. It’s used only for a single operation, fa.importUsers(importRequest). For more information, read the FusionAuth Typescript Client Library documentation.

The script imports users individually. If this is too slow when running the production migration, wrap the importUsers() FusionAuth SDK call in a loop that bundles users in batches of 1000.

Verify The Import

Log in to the FusionAuth admin UI with admin@example.com and password password. Review the user entries for the test application to ensure the data was correctly imported.

List of imported users

Manage users by clicking on the Manage button (black button) to the right of the user in the list of users. Review the details of the imported user’s profile. In the Source tab, you can see all the user details as a JSON object.

Slow Migration

This step of the tutorial is optional. In this section, you’ll learn how to create a Connector for FusionAuth to import your users’ passwords individually as each user logs in.

FusionAuth Reactor logo

This feature is only available in paid plans. Please visit our pricing page to learn more.

If you don’t need to do this, please skip to the What To Do Next section below.

Create A User With A Password

To test the slow migration, you need a user with a password you know. To create a user with a password that you can use to test authentication, alter your login form in the Frontegg web portal as follows:

  • Click Go to builder on the sidebar in Frontegg dashboard.
Go to builder in Frontegg
  • Disable all sign-in types on the left, except for Email sign on with Password, which you enable.
  • Enable Allow signup.
  • Use the Review to Publish button at the top right to review and publish this change.
Customize signup in Frontegg

Confirm the changes when asked and then publish the changes to your environment.

Get the signup URL for your environment:

  • Log in to your account at https://portal.frontegg.com.
  • Go to the environment, like Development.
  • Go to Environments -> Development -> Env settings and note down the Login URL.
Get login URL

Now visit the signup URL by appending /account/sign-up to the login URL to get a URL such as https://app-xyhd7853hsngq.frontegg.com/oauth/account/sign-up.

Create a new user with an alias like myemail+test@gmail.com and password password.

If you did not go through the steps mentioned earlier in the bulk migration section, get export scripts by going through the steps in the Export The Users With The API and Create Roles For Your Users sections. The steps are summarized below.

Export the new user by running the frontegg/src/1_exportUsers.mjs script.

node 1_exportUsers.mjs yourclientid yourapikey

If not already created, create roles in FusionAuth by running the frontegg/src/2_addRoles.mjs script.

node 2_addRoles.mjs

In the frontegg/src/3_convertFeUserToFaUser.mjs script, comment out the following code lines that assign a random password and require a password change.

  faUser.password = uuidv4();
  faUser.passwordChangeRequired = true;
  faUser.passwordChangeReason = "Administrative";

Map the users in the exported users.json file to FusionAuth-compatible objects by running the 3_convertFeUserToFaUser.mjs script.

node 3_convertFeUserToFaUser.mjs

Configure A Connector Between FusionAuth And Frontegg

FusionAuth Reactor logo

This feature is only available in paid plans. Please visit our pricing page to learn more.

Now configure a FusionAuth Connector to point to an intermediary web service between FusionAuth and Frontegg. The web service will expose an API endpoint that can be called from a FusionAuth Connector to retrieve the user’s details to be imported to FusionAuth.

For a general overview of Connectors, please see this video.

In your FusionAuth admin UI, browse to Settings —> Connectors.

Click the dropdown button on the top right and select Add Generic connector.

Create a Connector in FusionAuth

Enter the field values below.

  • Name: FronteggConnector
  • Authentication URL: http://host.docker.internal:6252. If you are running FusionAuth directly on your machine and not in Docker you can use http://localhost:6252.
  • Adjust the timeout values to higher values to cater for network latency when the API requests are being made
  • Enable Debug enabled

You may need to update your hosts file to include an entry for 127.0.0.1 host.docker.internal if it’s not already present. On macOS and Linux you can achieve this by running the following command:

echo "127.0.0.1 host.docker.internal" | sudo tee -a /etc/hosts
Connector details in FusionAuth

If your FusionAuth instance is hosted on a remote web server and you want to host the web service in a different location, you have several options for creating a publicly accessible API endpoint that allows the Connector to communicate with the web service.

  • Using Microsoft Azure, you can create an HTTP trigger on an Azure function app.
  • You can use an API gateway with a Lambda function on AWS.
  • During testing you can create a self-hosted endpoint locally and make it accessible on the internet using a service like ngrok.

To use ngrok you can download it at https://ngrok.com. There are free and paid plans available. For testing a free plan suffice.

Follow this quickstart to get ngrok up and running.

When ngrok is installed, you can start it with this command.

ngrok http 6252

Take note of the URL ngrok prints to your terminal. You can then use this URL as the Authentication URL value when setting up a Connector in FusionAuth. The URL should look something like https://random-ngrok-string.ngrok-free.app.

In production, you will want to add some authentication to the web service.

Now browse to Tenants and do the following.

  • Click Edit on the default tenant.
  • Click the Connectors tab.
  • Click Add policy.
  • Select FronteggConnector.
  • Leave Domains with the value * to apply this Connector to every user.
  • Enable Migrate user so that FusionAuth will no longer use Frontegg for subsequent logins of the same user.
  • Click Submit.
Connector policy details in FusionAuth

Move the FronteggConnector policy to the top of the list. Use the arrow buttons to move the policy if necessary. With this configuration, all users are checked against this Connector the first time they are seen. If they log in, they’ll be migrated to the FusionAuth user database.

After configuration, the Connector entry form should look similar to this:

Connector policy list in FusionAuth

Save the changes by clicking the save icon at the top right.

Build An Authentication Intermediary Web Service

The next step is to write the small service available on port 6252 that forwards the user’s login Id and password to Frontegg and returns the user details that will be saved to FusionAuth if the login is successful.

Documentation on the inputs and outputs a Connector expects is here.

The Connector makes a POST request to the URL you specify, and expects a JSON object back containing a user.

An example web service is in frontegg/src/5_connectorService.mjs.

This file has an Express HTTP POST handler that gets the login Id and password from the request and forwards them to Frontegg by calling the following function.

await isLoginValid(email, request.body.password);

A 404 is returned if the credentials are not valid.

If the credentials are valid, the user’s details stored in the faUsers.json file are returned. Unfortunately, the Frontegg API method https://docs.frontegg.com/reference/vendoronlyusers_verifyuserpassword you call in the service does not return a user Id. The search for the user Id is done in the following function.

await getUserDetailsFromFile(email);

Run this web service now using the command below.

node 5_connectorService.mjs yourfronteggclientid yourfronteggapikey

Log In With A Test User

In the FusionAuth admin interface, browse to Applications and click the magnifying glass next to the Test application. Copy the value of the OAuth IdP login URL and open it in an incognito window in your browser (if you don’t use an incognito window, you need to log out of the FusionAuth admin session to prevent the active session from interfering with the test). This URL is a login page for the Test application so that you can test the web service and Connector.

Test application login URL

Log in with the username and password you entered earlier, such as myemail+test@gmail.com and password. Your web service should show Request received on the console and the login request succeeding.

After a successful test login, the user will be redirected to a URL like https://example.com/?code=2aUqU0ZhQCjtz0fnrFL_i7wxhIAh7cTfxAXEIpJE-5w&locale=en&userState=AuthenticatedNotRegistered.

This occurs because you haven’t set up a web application to handle the authorization code redirect yet. This is an important next step, but it’s beyond the scope of this document. Consult the 5-minute setup guide for an example of how to do this.

If you log out and log in again with the same user, you’ll notice that Request received will not show in the web service console. This is because FusionAuth is now using its own authentication service as the original user password has been hashed and saved in the FusionAuth database.

The user has been successfully migrated, and Frontegg is no longer needed for them.

Debug The Connector Service

If you encounter errors in this process, try the following:

  • View the System Event Logs in the bottom left of the FusionAuth web interface.
  • Add console.log lines to the 5_connectorService.mjs file to see where any errors are occurring.
  • Adjust the timeout values of the Connector to higher values to cater for network latency between API calls.

Estimate The Slow Migration Timeline

When using a slow migration, you can estimate how many accounts will be migrated in a given period.

You can calculate a timeline by knowing the following:

  • How frequently the average user logs in
  • What the distribution of your users’ login behavior is
  • What your migration goal is

Determining these values precisely is beyond the scope of this guide. However, a good rule of thumb is to determine how often your average user logs in to your application. Then you can use this formula to find out when a certain percentage of users have migrated: S = [(1 - (1 - P)^D)*100]%.

Breaking that equation down, you have:

  • P is the probability of any single user authenticating in a given day. So if your users log in once a week on a business day, it is 0.2 (one out of five days). If they log in once a year, it is 0.0027 (one out of 365 days).
  • D is the number of days of the migration period.
  • S is the percentage of users who have migrated.

For P = 0.2 and D = 10, S = 89%. Therefore, if your users log in one out of every five days, in ten days almost nine out of ten will be migrated to FusionAuth.

For P = 0.0027 and D = 370, S = 63.7%; if your users log in once a year on average, in about a year, almost two thirds of accounts will be migrated to FusionAuth.

Using the above calculations should help you estimate the duration of a migration.

After this period, you may want to bulk migrate the rest of the users, or treat them as inactive and not migrate them. Plan to disable the Connector and remove the tenant’s Connector policy after the slow migration is complete.

Learn more about general slow migration considerations.

What To Do Next

Check what roles and features are used in Frontegg for your real application and create similar permissions and roles in FusionAuth. Update the sample user conversion script to map the role names from Frontegg to the roles in FusionAuth.

You now have your users migrated, or a plan to do so. Congratulations! What is next?

You need to migrate additional configurations, as mentioned in Other Entities . Since the type of configuration varies, it is hard to provide a full list of how to import these items, but the general pattern will be:

  • Identify corresponding FusionAuth functionality.
  • Configure it in your FusionAuth instance, either manually or by scripting it using the client libraries or API.
  • Update your application configuration to use the new FusionAuth functionality.

Make sure you assign your users to the appropriate FusionAuth applications. You can do this either:

  • As part of your import process by adding registrations at import time.
  • After users have been migrated with the Registrations API.

You’ll also need to modify and test each of your applications, whether custom, open source, or commercial, to ensure:

  • Users can successfully log in.
  • The authorization code redirect is handled correctly.
  • Users receive appropriate permissions and roles based on the JWT.
  • The look and feel of the hosted login pages matches each application’s look and feel.

If your application uses a standard OAuth, SAML or OIDC library to communicate with , the transition should be relatively painless.

Additional Support

If you need support in your migration beyond that provided in this guide, you may: