5-Minute Setup Guide
This is a 5-minute guide to set up and integrate with FusionAuth. Starting… now!
At the end of this guide, you’ll have a running Node application which will use FusionAuth for authentication, authorization and user management.
Requirements
This guide assumes that you have installed either a MySQL or PostgreSQL database and have a superuser name and password for the database that is able to create schemas and databases. If you do not have a database installed, follow the instructions in our Database Installation Guide to install a database.
You also need to have Node installed. This code has been tested with node 14, but should work with other versions.
$ node -v
v14.4.0
$ psql --version
psql (PostgreSQL) 12.3
Overview
Here are the steps that we need to take to setup FusionAuth as a login provider (also known as an identity provider) for your application:
Steps similar to these will be used for integrating with any OAuth identity provider. These also work for an OpenID Connect (OIDC) identity provider. Since FusionAuth supports both OAuth and OIDC, we’ll use the latter since it is the modern standard. Let’s get into the details of each step.
You can also watch a video of this tutorial:
1. Install FusionAuth
FusionAuth is simple to set up on your laptop, desktop or any server. You can also purchase a basic hosting plan on the FusionAuth Cloud platform.
Our installation guide covers all of the different methods you can use to install FusionAuth including Docker, Homebrew, Debian packages and our quick start script. You can follow any of the methods in the installation guide. For this document, we’ll use the Fast Path installation process using one of the commands below. You may optionally install Elasticsearch to be used as the user search engine.
macOS
Please feel free to read these install scripts before running them. Always a good idea.
sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh"
sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh -s - -s"
Linux
Please feel free to read these install scripts before running them. Always a good idea.
sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh -s - -z"
sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh -s - -z -s"
sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh"
sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh -s - -s"
Windows
Please feel free to read these install scripts before running them. Always a good idea.
. { iwr -useb https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.ps1 } | iex; install
. { iwr -useb https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.ps1 } | iex; install -includeSearch 1
Once the Fast Path installer completes, we will see this output on the console:
Downloading zip packages
######################################################################## 100.0%
######################################################################## 100.0%
Installing packages
Install is complete. Time for tacos.
1. To start FusionAuth run the following command
/Users/bpontarelli/dev/example/fusionauth/bin/startup.sh
2. To begin, access FusionAuth by opening a browser to http://localhost:9011
3. If you're looking for documentation, open your browser and navigate to https://fusionauth.io/docs
Thank you have a nice day.
2. Start FusionAuth
The next step is to start FusionAuth using the command that the Fast Path installer created. This script is called startup.sh
and we can execute it from the installation directory like this:
fusionauth/bin/startup.sh
This will start both the fusionauth-app
component as well as the fusionauth-search
component if you downloaded the Elasticsearch option. (Here’s a document on how to choose whether to do so.)
If you are on Windows, you’ll need to use the startup.bat
file instead.
3. Complete Maintenance Mode
After we have FusionAuth installed and running, we can open our browser to http://localhost:9011
. This is the default address for FusionAuth when running locally. This will bring up FusionAuth, which should be sitting in Maintenance Mode and ready to be configured.
FusionAuth enters Maintenance Mode any time the database is not accessible or is not properly set up. In our case, FusionAuth was able to connect, but the system was not configured. Here’s how the Maintenance Mode screen should look:

Here we need to provide the super user credentials for our database along with the name of the host of the database is running on if it isn’t running locally. We can also select either MySQL or PostgreSQL and change the database port if needed. For our example, we will be using PostgreSQL on the standard port with a super username of postgres
and a password of password
. We can also change the username and password that will be created as the primary database account that FusionAuth will access, the fusionauth
user above.
The reason that FusionAuth uses a separate username and password to connect to the database during normal operation is that if the FusionAuth configuration file is compromised and an attacker learns our database username and password, they will only have access to the FusionAuth database. This is helpful if we are using a single database server for multiple applications and databases. This is known as the principle of least privilege and FusionAuth uses this principle whenever possible.
Once we click the Submit button, we will be taken to the next step of Maintenance Mode. If you have opted to install with Elasticsearch, this step is where the FusionAuth Search component is configured, otherwise you can skip ahead to step 4, the Setup Wizard.
Our Fast Path install and startup script automatically start the fusionauth-search
component, which is a standard version of Elasticsearch. Since FusionAuth is able to connect to this search engine, all that is needed is to create the indexes inside it. This page looks like this:

Clicking the Submit button here will cause FusionAuth to exit Maintenance Mode and begin starting up. We’ll see an interstitial page that looks like this:

4. Complete the Setup Wizard
Once FusionAuth starts up successfully, we will be taken to the Setup Wizard. This is where we will create the administrator account for FusionAuth and accept the license.
Record the email and password you choose for the administrator account. You won’t be able to recover this without setting up an email server, which is beyond the scope of this tutorial.
We can also sign up for the FusionAuth newsletter, which is a great way to stay up-to-date on FusionAuth releases and new features. We never pitch you, hard-sell or sell your information, so feel free to sign up. Here’s what the Setup Wizard page looks like:

Clicking Submit here will complete the Setup Wizard and log us into the FusionAuth admin UI.
5. Create an Application and configure the OAuth settings
Once we arrive in the FusionAuth admin UI, the first thing we need to do is create an Application. An Application is something that a user can log into. This is the application we are building or that we are migrating to use FusionAuth. We’ll click the
menu option on the left side of the page or the Setup button in the box at the top of the page.
This will take us to the listing page for Applications. Next, we’ll click the green plus button (the add button) at the top of the page:

On the Application form, we’ll need to provide a name for our Application (only used for display purposes) and a couple of items on the OAuth tab. We’ll start with a simple setup that allows existing users to log into your application. Therefore, we won’t need to define any roles or registration configuration. If we click on the OAuth tab, we’ll see these options:

Most of the defaults will work, but we also need to provide these items:
-
An authorized redirect URL. This is the route/controller in our application’s backend that will complete the OAuth workflow. This is also known as the 'Backend for Frontend' or BFF pattern, and is a lightweight proxy. In our example, we set this to
http://localhost:3000/oauth-redirect
. We’ll show some Node.js example code below for this route. -
Optionally, we can specify a valid Logout URL. This is where the user will be redirected to after they are logged out of FusionAuth’s OAuth front-end: our application.
-
We need to ensure that the Authorization Code grant is selected in the Enabled Grants.
Once we have all of this configured, we’ll click the blue Save button at the top of the page.
6. Copy the OAuth login URL and add it to your application
Once the Application has been created, we’ll be back on the listing page. From here, we can click the green View button for our new Application. This will open a dialog that contains information about the Application, including the full URL for the OAuth login page. We’ll copy this URL and paste it into our application’s HTML as a link for the user to login. Most applications have a link that says, "Login" or "My Account" for this action.
Here’s how the view dialog looks:

We can add this URL as a link to our Node.js example application in the main template. The code is available on the FusionAuth GitHub, and it’s recommended you download it to follow along.
Here’s how our Pug template, which lives in views/index.pug
, looks:
extends layout
block content
h1= title
if user
p Hello #{user.firstName}
else
a(href='http://localhost:9011/oauth2/authorize?client_id='+clientId+'&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Foauth-redirect&scope=offline_access&state='+stateValue+'&code_challenge='+challenge+'&code_challenge_method=S256') Login
p Welcome to #{title}
If you are using raw HTML, here’s an anchor tag that will start the OAuth workflow the same as the Pug template above:
<a href="http://localhost:9011/oauth2/authorize?client_id=48cf2492-508d-4644-95eb-3741618821a4&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Foauth-redirect">Login</a>
Just drop this anchor tag into your HTML page and it will take the user to FusionAuth to login.
6. Grant the user permissions to your application
Next, we need to grant the user we created in the Setup Wizard permissions to log into our new Application. This can be done from the User management section of the FusionAuth admin UI. By clicking the
link in the navigation, we’ll be taken to the main user search. Since we only have one user in FusionAuth at the moment, we’ll just click on that user:
Once we are in this user’s account, we’ll click the Add Registration button. This will take us to a page that will allow us to add a registration for this user to the new Application. Here’s what this looks like:

For this example, we don’t need to provide any additional information for the registration, so we can just click the save button at the top. Now the user is set up so that they can log into the application. Keep in mind that in most cases, the process of creating a registration is done when the user signs up for our application.
Therefore, the process we just used is normally not required in order for users to log in. However, this process can be used for applications that are closed systems such as internal applications for your company. In these cases, users will be manually granted permissions to each application by an administrator.
7. Write a route (controller, action, etc) in your backend application that completes the login
Before we test the login, let’s write the route/controller in our application’s backend that will complete the OAuth workflow. After a user logs into FusionAuth’s OAuth front-end successfully, their browser will be redirected to the URL we provided in the configuration step above. This redirect will contain a query parameter called code
that contains the OAuth authorization code from FusionAuth. Our route/controller will use this code
parameter to call back to FusionAuth to exchange the code for an access token.
In order to complete this process, we’ll be using the FusionAuth typescript client library along with Express and Pug templates. This code is available on the FusionAuth GitHub. Here’s how our package.json
file looks:
{
"name": "fusionauth-node-example",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"@fusionauth/typescript-client": "^1.22.0",
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "~4.16.1",
"express-session": "1.17.0",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"pkce-challenge": "^2.1.0",
"pug": "3.0.1"
}
}
You’ll want to install this all by running npm install
after creating the above package.json
file.
Here’s the entire Express router. You want to create a file called routes/index.js
and put this code in it:
const express = require('express');
const router = express.Router();
const {FusionAuthClient} = require('@fusionauth/typescript-client');
// tag::clientIdSecret[]
const clientId = '85a03867-dccf-4882-adde-1a79aeec50df';
const clientSecret = 'NkIKQ2MGx3uMBv3uGl9TyYud0MYfdBWCOk-cPQTjiAw';
// end::clientIdSecret[]
const fusionAuthURL = 'http://localhost:9011';
const client = new FusionAuthClient('noapikeyneeded', fusionAuthURL);
const pkceChallenge = require('pkce-challenge');
/* logout home page. */
router.get('/logout', function (req, res, next) {
req.session.destroy();
res.redirect(302, '/');
});
/* GET home page. */
router.get('/', function (req, res, next) {
const stateValue = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
req.session.stateValue = stateValue;
//generate the pkce challenge/verifier dict
const pkce_pair = pkceChallenge();
// Store the PKCE verifier in session
req.session.verifier = pkce_pair['code_verifier'];
const challenge = pkce_pair['code_challenge'];
res.render('index', {user: req.session.user, title: 'FusionAuth Example', clientId: clientId, challenge: challenge, stateValue: stateValue, fusionAuthURL: fusionAuthURL});
});
// tag::fullOAuthCodeExchange[]
/* OAuth return from FusionAuth */
router.get('/oauth-redirect', function (req, res, next) {
const stateFromServer = req.query.state;
if (stateFromServer !== req.session.stateValue) {
console.log("State doesn't match. uh-oh.");
console.log("Saw: " + stateFromServer + ", but expected: " + req.session.stateValue);
res.redirect(302, '/');
return;
}
// tag::exchangeOAuthCode[]
// This code stores the user in a server-side session
client.exchangeOAuthCodeForAccessTokenUsingPKCE(req.query.code,
clientId,
clientSecret,
'http://localhost:3000/oauth-redirect',
req.session.verifier)
// end::exchangeOAuthCode[]
.then((response) => {
console.log(response.response.access_token);
return client.retrieveUserUsingJWT(response.response.access_token);
})
.then((response) => {
if (!response.response.user.registrations || response.response.user.registrations.length == 0 || (response.response.user.registrations.filter(reg => reg.applicationId === clientId)).length == 0) {
console.log("User not registered, not authorized.");
res.redirect(302, '/');
return;
}
// tag::setUserInSession[]
req.session.user = response.response.user;
})
// end::setUserInSession[]
.then((response) => {
res.redirect(302, '/');
}).catch((err) => {console.log("in error"); console.error(JSON.stringify(err));});
// This code pushes the access and refresh tokens back to the browser as secure, HTTP-only cookies
// .then((response) => {
// res.cookie('access_token', response.response.access_token, {httpOnly: true});
// res.cookie('refresh_token', response.response.refresh_token, {httpOnly: true});
// res.redirect(302, '/');
// }).catch((err) => {console.log("in error"); console.error(JSON.stringify(err));});
});
// end::fullOAuthCodeExchange[]
module.exports = router;
This is a lot, so you can just cut and paste it. But let’s look at two specific sections.
First, to call the function on the FusionAuth client, we will also need the Client Id and the Client Secret from our Application configuration above. We’ll take those values and put them in the code. These are required so that our application can prove it is the correct application the user is logging into.
Make sure you update the code with the correct values for your Application:
//...
const clientId = '85a03867-dccf-4882-adde-1a79aeec50df';
const clientSecret = 'NkIKQ2MGx3uMBv3uGl9TyYud0MYfdBWCOk-cPQTjiAw';
//...
Second, we need a route that will respond to the path we configured in the FusionAuth admin user interface above (/oauth-redirect
). This route will pull the code
parameter from the request and exchange it for an access token. This access token can be used to prove that any client holding it is authorized.
Here’s an excerpt of some of the Node.js code for the route:
//...
// This code stores the user in a server-side session
client.exchangeOAuthCodeForAccessTokenUsingPKCE(req.query.code,
clientId,
clientSecret,
'http://localhost:3000/oauth-redirect',
req.session.verifier)
//...
If you don’t want to use a client library, you may post directly to the /oauth2/token
endpoint. This will return the access token as well as other data.
8. Store the user object in the session
The final step is to add some code to our route in our BFF that will retrieve the User object from FusionAuth using the access_token
we retrieved in the previous step. Once we have the User object, we will store it in a server side session so that it can be used in other parts of the application. We also check that the user has been registered to our application.
We can also store the access_token
from FusionAuth as a cookie if our application would rather push the state to the browser (more on that below).
In either case, the last step we take is to redirect the authorized user back to the homepage. Here’s the complete code for exchanging the token, retrieving the user and storing it in the session:
//...
/* OAuth return from FusionAuth */
router.get('/oauth-redirect', function (req, res, next) {
const stateFromServer = req.query.state;
if (stateFromServer !== req.session.stateValue) {
console.log("State doesn't match. uh-oh.");
console.log("Saw: " + stateFromServer + ", but expected: " + req.session.stateValue);
res.redirect(302, '/');
return;
}
// This code stores the user in a server-side session
client.exchangeOAuthCodeForAccessTokenUsingPKCE(req.query.code,
clientId,
clientSecret,
'http://localhost:3000/oauth-redirect',
req.session.verifier)
.then((response) => {
console.log(response.response.access_token);
return client.retrieveUserUsingJWT(response.response.access_token);
})
.then((response) => {
if (!response.response.user.registrations || response.response.user.registrations.length == 0 || (response.response.user.registrations.filter(reg => reg.applicationId === clientId)).length == 0) {
console.log("User not registered, not authorized.");
res.redirect(302, '/');
return;
}
req.session.user = response.response.user;
})
.then((response) => {
res.redirect(302, '/');
}).catch((err) => {console.log("in error"); console.error(JSON.stringify(err));});
// This code pushes the access and refresh tokens back to the browser as secure, HTTP-only cookies
// .then((response) => {
// res.cookie('access_token', response.response.access_token, {httpOnly: true});
// res.cookie('refresh_token', response.response.refresh_token, {httpOnly: true});
// res.redirect(302, '/');
// }).catch((err) => {console.log("in error"); console.error(JSON.stringify(err));});
});
//...
9. Test the application
Now that everything is written, let’s test the workflow. We can fire up the Node.js BFF using this command:
npm start
If we open our application in the browser and click the Login
link, this will take us to FusionAuth’s OAuth login page. From here, we can log in with the account we created in step 4, the Setup Wizard.
As mentioned above, the Node.js code above is available on the FusionAuth GitHub located here: https://github.com/FusionAuth/fusionauth-node-example .
Cookies for a Single Page Application
If you prefer to use cookies rather than server-side sessions, you can modify the code for your oauth-redirect
route from this:
//...
req.session.user = response.response.user;
})
//...
to this:
})
.then((response) => {
res.cookie('access_token', response.response.access_token, {httpOnly: true});
res.cookie('refresh_token', response.response.refresh_token, {httpOnly: true});
res.redirect(302, '/');
}).catch((err) => {console.log("in error"); console.error(JSON.stringify(err));});
This approach works well if you are building a single-page application (SPA) or any other type of application where cookies are preferred to server-side sessions.
Feedback
We are beginning to work on a ten minute guide and a 42 minute guide. What topics would you want to learn next? Please choose two at most.
Next Steps
From here, you can begin creating a registration page in your application or using FusionAuth’s registration tool. You can also start working with FusionAuth Themes to make the login pages look like your brand. If you want to use FusionAuth’s forgot password system, you will need to configure an SMTP server. Here are some links to additional documents that will help you continue your integration with FusionAuth.