FusionAuth developer image
FusionAuth developer logo
  • Back to site
  • Expert Advice
  • Blog
  • Developers
  • Downloads
  • Account
  • Contact sales
Navigate to...
  • Welcome
  • Getting Started
    • Getting Started
    • 5-Minute Setup Guide
    • Setup Wizard & First Login
    • Register a User and Login
    • Self-service Registration
    • Start and Stop FusionAuth
    • Core Concepts
      • Overview
      • Users
      • Roles
      • Groups
      • Registrations
      • Applications
      • Tenants
      • Identity Providers
      • Authentication/Authorization
      • Integration Points
    • Example Apps
      • Overview
      • Dart
      • Go
      • Java
      • JavaScript
      • .NET Core
      • PHP
      • Python
      • Ruby
    • Tutorials
  • Installation Guide
    • Overview
    • System Requirements
    • Server Layout
    • Cloud
    • Cluster
    • Docker
    • Fast Path
    • Kubernetes
      • Overview
      • Deployment Guide
      • Minikube Setup
      • Amazon EKS Setup
      • Google GKE Setup
      • Microsoft AKS Setup
    • Kickstart™
    • Homebrew
    • Packages
    • Database
    • FusionAuth App
    • FusionAuth Search
    • Common Configuration
  • Migration Guide
    • Overview
    • General
    • Auth0
    • Keycloak
    • Amazon Cognito
    • Firebase
    • Tutorial
  • Admin Guide
    • Overview
    • Account Portal
    • Config Management
    • Editions and Features
    • Key Rotation
    • Licensing
    • Monitoring
    • Prometheus Setup
    • Proxy Setup
    • Reference
      • Overview
      • Configuration
      • CORS
      • Data Types
      • Hosted Login Pages Cookies
      • Known Limitations
      • Password Hashes
    • Roadmap
    • Securing
    • Switch Search Engines
    • Technical Support
    • Troubleshooting
    • Upgrading
  • Login Methods
    • Identity Providers
      • Overview
      • Apple
      • Epic Games
      • External JWT
        • Overview
        • Example
      • Facebook
      • Google
      • HYPR
      • LinkedIn
      • Nintendo
      • OpenID Connect
        • Overview
        • Azure AD
        • Discord
        • Github
      • Sony PlayStation Network
      • Steam
      • Twitch
      • Twitter
      • SAML v2
        • Overview
        • ADFS
      • SAML v2 IdP Initiated
        • Overview
        • Okta
      • Xbox
    • OIDC & OAuth 2.0
      • Overview
      • Endpoints
      • Tokens
    • SAML v2 IdP
      • Overview
      • Google
      • Zendesk
  • Developer Guide
    • Authentication Tokens
    • Client Libraries
      • Overview
      • Dart
      • Go
      • Java
      • JavaScript
      • .NET Core
      • Node
      • OpenAPI
      • PHP
      • Python
      • Ruby
      • Typescript
    • Events & Webhooks
      • Overview
      • Writing a Webhook
      • Securing Webhooks
      • Events
        • Overview
        • Audit Log Create
        • Event Log Create
        • JWT Public Key Update
        • JWT Refresh
        • JWT Refresh Token Revoke
        • Kickstart Success
        • User Action
        • User Bulk Create
        • User Create
        • User Create Complete
        • User Deactivate
        • User Delete
        • User Delete Complete
        • User Email Update
        • User Email Verified
        • User IdP Link
        • User IdP Unlink
        • User Login Failed
        • User Login Id Dup. Create
        • User Login Id Dup. Update
        • User Login New Device
        • User Login Success
        • User Login Suspicious
        • User Password Breach
        • User Password Reset Send
        • User Password Reset Start
        • User Password Reset Success
        • User Password Update
        • User Reactivate
        • User Reg. Create
        • User Reg. Create Complete
        • User Reg. Delete
        • User Reg. Delete Complete
        • User Registration Update
        • User Reg. Update Complete
        • User Reg. Verified
        • User 2FA Method Add
        • User 2FA Method Remove
        • User Update
        • User Update Complete
    • Guides
      • Overview
      • Advanced Registration Forms
      • Breached Password Detection
      • Multi-Factor Authentication
      • Multi-Tenant
      • Passwordless
      • Securing Your APIs
      • Silent Mode
      • Single Sign-on
    • Integrations
      • Overview
      • CleanSpeak
      • Kafka
      • Twilio
    • JSON Web Tokens
    • Key Master
    • Localization and Internationalization
    • Plugins
      • Overview
      • Writing a Plugin
      • Custom Password Hashing
    • Search And FusionAuth
    • Two Factor (pre 1.26)
    • User Control & Gating
      • Gate Unverified Users
      • Gate Unverified Registrations
      • User Account Lockout
  • Customization
    • Email & Templates
      • Overview
      • Configure Email
      • Email Templates
      • Email Variables
      • Message Templates
    • Lambdas
      • Overview
      • Apple Reconcile
      • Client Cred. JWT Populate
      • Epic Games Reconcile
      • External JWT Reconcile
      • Facebook Reconcile
      • Google Reconcile
      • HYPR Reconcile
      • JWT Populate
      • LDAP Connector Reconcile
      • LinkedIn Reconcile
      • Nintendo Reconcile
      • OpenID Connect Reconcile
      • SAML v2 Populate
      • SAML v2 Reconcile
      • SCIM Group Req. Converter
      • SCIM Group Resp. Convtr.
      • SCIM User Req. Converter
      • SCIM User Resp. Converter
      • Sony PSN Reconcile
      • Steam Reconcile
      • Twitch Reconcile
      • Twitter Reconcile
      • Xbox Reconcile
    • Messengers
      • Overview
      • Generic Messenger
      • Kafka Messenger
      • Twilio Messenger
    • Themes
      • Overview
      • Examples
      • Helpers
      • Localization
      • Template Variables
  • Premium Features
    • Advanced Threat Detection
    • Connectors
      • Overview
      • Generic Connector
      • LDAP Connector
      • FusionAuth Connector
    • Entity Management
    • SCIM
      • Overview
      • SCIM-SDK Example
    • Self Service Account Mgmt
      • Overview
      • Updating User Data & Password
      • Add Two-Factor Authenticator
      • Add Two-Factor Email
      • Add Two-Factor SMS
      • Customizing
      • Troubleshooting
  • APIs
    • Overview
    • Authentication
    • Errors
    • Actioning Users
    • API Keys
    • Applications
    • Audit Logs
    • Connectors
      • Overview
      • Generic
      • LDAP
    • Consents
    • Emails
    • Entity Management
      • Overview
      • Entities
      • Entity Types
      • Grants
    • Event Logs
    • Families
    • Forms
    • Form Fields
    • Groups
    • Identity Providers
      • Overview
      • Links
      • Apple
      • External JWT
      • Epic Games
      • Facebook
      • Google
      • HYPR
      • LinkedIn
      • Nintendo
      • OpenID Connect
      • SAML v2
      • SAML v2 IdP Initiated
      • Sony PlayStation Network
      • Steam
      • Twitch
      • Twitter
      • Xbox
    • Integrations
    • IP Access Control Lists
    • JWT
    • Keys
    • Lambdas
    • Login
    • Message Templates
    • Messengers
      • Overview
      • Generic
      • Kafka
      • Twilio
    • Multi-Factor/Two Factor
    • Passwordless
    • Reactor
    • Registrations
    • Reports
    • SCIM
      • Overview
      • SCIM EnterpriseUser
      • SCIM Group
      • SCIM Service Provider Config.
      • SCIM User
    • System
    • Tenants
    • Themes
    • Users
    • User Actions
    • User Action Reasons
    • User Comments
    • Webhooks
  • Release Notes

    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.

    Testing Node Installation
    
    $ node -v
    v14.4.0
    Testing Postgresql Installation
    
    $ 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:

    1. Install FusionAuth

    2. Start FusionAuth

    3. Complete Maintenance Mode

    4. Complete the Setup Wizard

    5. Create an Application and configure the OAuth settings

    6. Grant the user permissions to your application

    7. Write a route (controller, action, etc) in your backend application that completes the login

    8. Store the user object in the session

    9. Test the 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.

    Install in your current working directory using ZIP packages
    
    sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh"
    Install in your current working directory using ZIP packages, include Elasticsearch
    
    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.

    Install in your current working directory using ZIP packages
    
    sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh -s - -z"
    Install in your current working directory using ZIP packages, include Elasticsearch
    
    sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh -s - -z -s"
    Install for all users on the system using DEB or RPM packages, requires sudo access
    
    sh -c "curl -fsSL https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.sh | sh"
    Install for all users on the system using DEB or RPM packages, include Elasticsearch, requires sudo access
    
    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.

    Install in your current working directory using ZIP packages. Install using Windows PowerShell
    
    . { iwr -useb https://raw.githubusercontent.com/FusionAuth/fusionauth-install/master/install.ps1 } | iex; install
    Install in your current working directory using ZIP packages, include Elasticsearch. Install using Windows PowerShell
    
    . { 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:

    Fast Path install complete
    
    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:

    Startup script
    
    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:

    Maintenance Mode Database

    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:

    Maintenance Mode Search

    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:

    Interstitial

    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:

    Setup Wizard

    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 Application menu option on the left side of the page or the Setup button in the box at the top of the page.

    Dashboard to Applications

    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:

    Application Listing

    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:

    Application Form

    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:

    Application View Dialog

    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:

    Pug Template
    
    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:

    HTML Snippet
    
    <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 Users 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:

    User Search

    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:

    Registration Add Form

    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:

    package.json
    
    {
      "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:

    Node.js Express Router
    
    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:

    Node.js Client Id and Secret config
    
    //...
    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:

    Node.js 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:

    Node.js Complete OAuth Code Exchange
    
    //...
    /* 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:

    Node.js 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:

    Node.js Route Using Sessions for Token Storage
    
    //...
            req.session.user = response.response.user;
          })
    //...

    to this:

    Node.js Route With Cookie Token Storage
    
      })
      .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.

    • Core Concepts

    • Customizing users' JWTs

    • Customizing emails

    • Logging in with OIDC, SAML and social login providers

    • Making the FusionAuth pages look like your application with themes

    • MFA/Two-Factor

    • OAuth documentation

    • Registration API

    • Self service registration

    • Single Sign-on/SSO

    • Tutorials in other programming languages

    • User API

    Feedback

    How helpful was this page?

    See a problem?

    File an issue in our docs repo

    © 2022 FusionAuth
    Subscribe for developer updates