This simple example app shows how you can use FusionAuth in a React app to log in, log out, and manipulate user data.
-
Make sure you have everything you need to run this app:
-
Clone this repository.
git clone https://github.com/FusionAuth/fusionauth-example-react.git
-
Configure your app in the FusionAuth admin panel (default localhost:9011).
- Go through the setup wizard if you haven't already.
- Create a new FusionAuth application.
- Set the OAuth Redirect URI to
http://localhost:9000/oauth-callback
. - Copy your app's Client ID, Client Secret, Redirect URI, Application ID, and API Key into the
config.js
file in the root directory of this project. - Register at least one user with your application.
-
Make sure FusionAuth is running, then install dependencies and start the app. The React app should automatically open in your browser at localhost:8080.
cd server npm install npm start
cd client npm install npm start
The app has three parts, each running on a different localhost
port (unless you've decided to set it up otherwise):
localhost/8080
is your React app. It has a single route (/
) and makes calls to the Express app.localhost/9000
is your Express app. It has several routes (like/login
and/logout
), which are used by the React app. The Express app makes calls to FusionAuth.localhost/9011
is your instance of FusionAuth. It has several endpoints (like/authorize
and/introspect
). It accepts calls from the Express app and sends back information, such as access tokens and user registration data.
So, the parts connect like this:
8080 <-> 9000 <-> 9011
The React app never talks directly to FusionAuth. This is important, because the React app can be easily picked apart by anyone online, which means you can't keep confidential information there. While some calls directly to FusionAuth are safe, best practice is to keep things separated like this.
When the user clicks on sign in
, the React app redirects to the Express server's /login
route, which redirects to FusionAuth's authorize
endpoint. FusionAuth renders the username/password form, authenticates the user, and redirects to the configured Redirect URI (/oauth-redirect
on the Express server) with an Authorization Code.
The Express server sends the Authorization Code (as well as its Client ID and Secret) to FusionAuth's /token
endpoint. FusionAuth validates everything and sends back an Access Token. The Express Server saves this token in session storage and redirects back to the React client.
When the user clicks on sign out
, the React app sends a request to the Express server's /logout
route, which sends a request to FusionAuth's /logout
endpoint, deletes the relevant cookie, and deletes the Access Token from session storage.
The presence of the Access Token in session storage is what defines whether or not a user is logged in, because FusionAuth will not allow retrieval or modification of user data without a valid Access Token.
When the React client mounts, it sends a request to the Express server's /user
route. If there's an Access Token in session storage, the Express server uses FusionAuth's /introspect
and /registration
endpoints to get data for the current user; these give us the token
and registration
JSON objects seen in the example app.
If there is no Access Token (or if it's expired), /user
will instead return an empty object. The React components use the existence of token
(or lack thereof) to determine whether to render the page in its logged-in or logged-out state.
All of your FusionAuth users have a registration.data
object for storing arbitrary data related to the user. The example app allows logged-in users to modify registration.data.userData
by changing its value in the <textarea>
, but all registration
information is able to be set in this way.
When the <textarea>
is changed, the React client makes a request to the Express server's /set-user-data
route, which makes a request to FusionAuth's /registration
endpoint.
If you want to use this example app as a jumping-off point for your own FusionAuth app, you can easily strip it down or expand upon it.
- remove, replace, or add React components in
/client/app/components/
and update references in/client/app/index.js
- remove, replace, or add styles in
/client/app/styles/
and update references in/client/app/index.css
- remove, replace, or add routes in
/server/routes/
and update references in/server/index.js
TODO