web

WordPress

WordPress

In this quickstart, you are going to build an application with WordPress and integrate it with FusionAuth. You’ll be building it for ChangeBank, a global leader in converting dollars into coins. It’ll have areas reserved for users who have logged in as well as public facing sections.

The Docker Compose file and source code for a complete application are available at https://github.com/FusionAuth/fusionauth-quickstart-wordpress-web.

Prerequisites

For this Quickstart, you’ll need:

  • Docker 20 or later, which is the quickest way to start FusionAuth. (There are other ways.)

General Architecture

While this sample application doesn't have login functionality without FusionAuth, a more typical integration will replace an existing login system with FusionAuth.

In that case, the system might look like this before FusionAuth is introduced.

UserApplicationView HomepageClick Login LinkShow Login FormFill Out and Submit Login FormAuthenticates UserDisplay User's Account or OtherInfoUserApplication

Request flow during login before FusionAuth

The login flow will look like this after FusionAuth is introduced.

UserApplicationFusionAuthView HomepageClick Login Link (to FusionAuth)View Login FormShow Login FormFill Out and Submit Login FormAuthenticates UserGo to Redirect URIRequest the Redirect URIIs User Authenticated?User is AuthenticatedDisplay User's Account or OtherInfoUserApplicationFusionAuth

Request flow during login after FusionAuth

In general, you are introducing FusionAuth in order to normalize and consolidate user data. This helps make sure it is consistent and up-to-date as well as offloading your login security and functionality to FusionAuth.

Getting Started

In this section, you’ll get FusionAuth up and running and create a new WordPress application.

Clone The Code

First, clone the code from the repository and change into that directory.

git clone https://github.com/FusionAuth/fusionauth-quickstart-wordpress-web.git
cd fusionauth-quickstart-wordpress-web

All shell commands in this guide can be entered in a terminal in this directory. On Windows, you need to replace forward slashes with backslashes in paths.

If you prefer to copy the files you’ll create in this guide, they already exist in the complete-application directory.

Run FusionAuth Via Docker

You'll find a Docker Compose file (docker-compose.yml) and an environment variables configuration file (.env) in the root directory of the repo.

Assuming you have Docker installed, you can stand up FusionAuth on your machine with the following.

docker compose up -d

Here you are using a bootstrapping feature of FusionAuth called Kickstart. When FusionAuth comes up for the first time, it will look at the kickstart/kickstart.json file and configure FusionAuth to your specified state.

If you ever want to reset the FusionAuth application, you need to delete the volumes created by Docker Compose by executing docker compose down -v, then re-run docker compose up -d.

FusionAuth will be initially configured with these settings:

  • Your client Id is E9FDB985-9173-4E01-9D73-AC2D60D1DC8E.
  • Your client secret is super-secret-secret-that-should-be-regenerated-for-production.
  • Your example username is richard@example.com and the password is password.
  • Your admin username is admin@example.com and the password is password.
  • The base URL of FusionAuth is http://localhost:9011/.

You can log in to the FusionAuth admin UI and look around if you want to, but with Docker and Kickstart, everything will already be configured correctly.

If you want to see where the FusionAuth values came from, they can be found in the FusionAuth app. The tenant Id is found on the Tenants page. To see the Client Id and Client Secret, go to the Applications page and click the View icon under the actions for the ChangeBank application. You'll find the Client Id and Client Secret values in the OAuth configuration section.

The .env file contains passwords. In a real application, always add this file to your .gitignore file and never commit secrets to version control.

Create A Basic WordPress Application

Next, you’ll set up a basic WordPress site. While this guide builds a new WordPress project, you can use the same method to integrate your existing project with FusionAuth.

If you simply want to run the application, there is a completed version in the complete-application directory. You can use the following commands to get it up and running if you do not want to create your own.

cd complete-application
docker compose up

Then view the application at the following URL http://localhost:3000.

Preliminary Setup

Browse to http://localhost:3000. It should automatically redirect you to http://localhost:3000/wp-admin/install.php, as this is a brand-new site.

Choose “English (United States)” and click Continue.

On the next page:

  • Set Site Title to Change Bank.
  • Set Username to admin and Password to password.
  • Enable Confirm use of weak password .
  • Set Your Email to admin@example.com.
  • Click Install WordPress.
Wordpress configuration

On the success page, click Log In. On the login page, enter the username admin and password password and click Log In. (You can return to this page later by browsing to http://localhost:3000/wp-login.php.)

Create Placeholder Pages

Before you do any FusionAuth work, you’ll create three placeholder pages:

  • A home page that anonymous users can see.
  • A make change page that only logged in users can see.
  • An account page that only logged in users can see.

Under Settings -> Permalinks , change Permalink structure to Post name and click Save Changes. This sets page URLs to be more human-readable than the default numbered URLs.

Permalinks

To add the placeholder pages, first delete the default pages:

  • Click Pages in the sidebar.
  • Select the two existing sample pages.
  • On the Bulk Actions dropdown, select Move to Trash and click Apply.

Now create new blank pages:

  • Click Add New.
  • Under Add Title enter Home.
  • Under Page on the far right, view the Template field and modify it. Do so by clicking Pages, and select Blank on the dropdown.
  • Click Publish, confirm, and note the URL has been updated to one you can browse to.
  • Click the WP icon on the top left to return to the pages screen.
  • Repeat these steps to create and publish two more pages, one with the title Account and one with the title Change.

You now have three blank pages.

Add page

Browse to Settings -> Reading . Change Your homepage displays to A static page and under Homepage select Home. Save your changes. Now http://localhost:3000 points to your homepage.

Homepage

Finally, browse to Appearance -> Editor -> Templates -> Blank . Here you are editing the page style template for all three of your new pages. Click on the paragraph (This is the Post Content block ...) twice to select it. Open the settings menu by clicking the Settings icon to the right of the blue Save button on the top right. On the Block tab and under the Layout section, disable Inner blocks use content width. Click Save and confirm. This changes each page to use the full browser width.

Full width setting

Authentication

You now have a basic WordPress site with three blank pages. Currently, a user authenticates against the Wordpress user database. Next, you will enable WordPress to use FusionAuth for authentication so that your users can use the same FusionAuth login credentials with this site as any future sites you make or other applications.

On the WordPress dashboard, click Plugins -> Add new . In the search box on the right, paste “OpenID Connect Generic Client”. On the first plugin in the results, by daggerhart, click Install Now, then Activate.

Add a plugin

Browse to Settings -> Open ID Connect Client and enter the following settings:

  • Client ID - E9FDB985-9173-4E01-9D73-AC2D60D1DC8E
  • Client Secret Key - super-secret-secret-that-should-be-regenerated-for-production
  • OpenID Scope - openid
  • Login Endpoint URL - http://localhost:9011/oauth2/authorize
  • Userinfo Endpoint URL - http://fusionauth:9011/oauth2/userinfo
  • Token Validation Endpoint URL - http://fusionauth:9011/oauth2/token
  • End Session Endpoint URL - http://localhost:9011/oauth2/logout
  • Nickname Key - sub
  • Display Name Formatting - {email} (this is what will be displayed to the user in the WordPress admin screen)
  • Enable Link Existing Users - this marks a user in your local WordPress database who has the same email in FusionAuth as the same user, instead of duplicating them.

Requests from the browser will use the endpoint http://localhost:9011 to communicate with the FusionAuth container whilst for container to container communication the internal network name for the FusionAuth container specified in docker compose is fusionauth so the endpoint http://fusionauth:9011 is used.

Click Save Changes.

Configure FusionAuth

Now if you browse to http://localhost:3000/wp-login.php, you can click Login with OpenID Connect and log in on FusionAuth with email richard@example.com and password password.

Prevent Default Login

For a simpler user experience, you can remove the option to log in with WordPress. This is an optional step.

Open a terminal and run the following command to overwrite the default wp-login.php file.

docker cp ./complete-application/wp-login.php fusionauth-quickstart-wordpress-web-wordpress-1:/var/www/html/wp-login.php

The new file starts commenting out the login form on line 1424 with <!--, and ends the comment on line 1504 with -->.

Now http://localhost:3000/wp-login.php looks much neater.

Restrict Pages To Logged In Users

Currently, if you log out, you can still browse to the pages that should be restricted, like http://localhost:3000/account. Let’s prevent that.

At Plugins -> Add New , search for “simple page access restriction” and install and activate the one by Plugins & Snippets. Browse to the plugin settings in the sidebar. Set the following values:

  • Login Redirect Type - “URL”.
  • Login Redirect URL - http://localhost:3000/wp-login.php.
  • Click Save Changes.
Restrict pages

Back in Pages , for both the account and change pages, click Edit, enable For Logged-In Users Only at the bottom right, and click Update. Now if you log out and browse to either page, you won’t be able to view it.

Page settings

Send User To Account After Log In

The final improvement you can make to the login process is to send the user directly to their account page instead of the dashboard after login.

Search for and install the plugin “Remove Dashboard Access” by TrustedLogin.

Browse to Settings -> Dashboard Access . Change the value of Redirect URL to http://localhost:3000/account. Click Save Changes.

Page settings

Now if you log out and log in as richard@example.com, who is not an administrator, you’ll be redirected to the account page. Log in again as admin@example.com to continue editing the site.

Customization

You now have everything you need to configure FusionAuth authentication on your site. To complete this demonstration application, you’ll add some content to the three blank pages. There are many ways to create custom pages on WordPress, including:

  • Editing the theme.
  • Making a child theme and editing that.
  • Adding new template files for each page.
  • Making custom shortcodes.
  • Making custom blocks.
  • Making custom plugins.

The easiest way to demonstrate the ChangeBank sample pages is to paste custom content into a plugin, but note that is not the most maintainable solution for a real site. If your site is large or complex, take the time to study custom themes and create your own.

For now, search for and add the plugin “WP Coder” by WPCoder.

Add An Image

Browse to Media in the sidebar. Click Add New and select money.jpg from the complete-application directory.

Add image

Click on the image once it has been uploaded. Copy the “File URL” to use later. It should look like http://localhost:3000/wp-content/uploads/2023/09/money.jpg.

Add Custom Page Shortcodes

You’ll now create three shortcodes with the HTML, CSS, and JavaScript for each page.

Browse to WP Coder . Click Add New. In the title box at the top, enter home. In the HTML Code box, copy and paste the following code.

<div id="page-container">
    <div id="page-header">
      <div id="logo-header">
        <img
          src="https://fusionauth.io/cdn/samplethemes/changebank/changebank.svg"
        />
        <a class="button-lg" href="/login"> Login </a>
      </div>

      <div id="menu-bar" class="menu-bar">
        <a class="menu-link">About</a>
        <a class="menu-link">Services</a>
        <a class="menu-link">Products</a>
        <a class="menu-link" style="text-decoration-line: underline">Home</a>
      </div>
    </div>

    <div style="flex: 1">
      <div class="column-container">
        <div class="content-container">
          <div style="margin-bottom: 100px">
            <h1>Welcome to Changebank</h1>
            <p>
              To get started,
              <a href="/login">log in or create a new account</a>.
            </p>
          </div>
        </div>
        <div style="flex: 0">
          <img src="http://localhost:3000/wp-content/uploads/2023/09/money-scaled.jpg" style="max-width: 800px" />
        </div>
      </div>
    </div>
  </div>
</div>

In the <img src at the bottom of this code, enter the file URL for the money image you uploaded.

Click the CSS tab, and paste the following code.

h1 {
    color: #096324;
  }

  h3 {
    color: #096324;
    margin-top: 20px;
    margin-bottom: 40px;
  }

  a {
    color: #096324;
  }

  p {
    font-size: 18px;
  }

  .header-email {
    color: #096324;
    margin-right: 20px;
  }

  .fine-print {
    font-size: 16px;
  }

  body {
    font-family: sans-serif;
    padding: 0px;
    margin: 0px;
  }

  .h-row {
    display: flex;
    align-items: center;
  }

  #page-container {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
  }

  #page-header {
    flex: 0;
    display: flex;
    flex-direction: column;
  }

  #logo-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
  }

  .menu-bar {
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
    height: 35px;
    padding: 15px 50px 15px 30px;
    background-color: #096324;
    font-size: 20px;
  }

  .menu-link {
    font-weight: 600;
    color: #FFFFFF !important;
    margin-left: 40px;
  }

  .menu-link {
    font-weight: 600;
    color: #FFFFFF !important;
    margin-left: 40px;
  }

  .inactive {
    text-decoration-line: none;
  }

  .button-lg {
    width: 150px;
    height: 30px;
    background-color: #096324;
    color: #FFFFFF !important;
    font-size: 16px;
    font-weight: 700;
    border-radius: 10px;
    text-align: center;
    padding-top: 10px;
    text-decoration-line: none;
  }

  .column-container {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }

  .content-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 60px 20px 20px 40px;
  }

  .balance {
    font-size: 50px;
    font-weight: 800;
  }

  .change-label {
    font-size: 20px;
    margin-right: 5px;
  }

  .change-input {
    font-size: 20px;
    height: 40px;
    text-align: end;
    padding-right: 10px;
  }

  .change-submit {
    font-size: 15px;
    height: 40px;
    margin-left: 15px;
    border-radius: 5px;
  }

  .change-message {
    font-size: 20px;
    margin-bottom: 15px;
  }

  .error-message {
    font-size: 20px;
    color: #FF0000;
    margin-bottom: 15px;
  }

  .app-container {
    flex: 0;
    min-width: 440px;
    display: flex;
    flex-direction: column;
    margin-top: 40px;
    margin-left: 80px;
  }

  .change-container {
    flex: 1;
  }

Click Save Changes.

Browse to WP Coder . Click Add New. In the title box at the top, enter account. In the HTML Code box, copy and paste the following code.

<div id="page-container">
  <div id="page-header">
    <div id="logo-header">
      <img src="https://fusionauth.io/cdn/samplethemes/changebank/changebank.svg" />
      <div class="h-row">
        <p class="header-email">[sv slug="sc-user-email"]</p>
        <a class="button-lg" href="/wp-login.php?action=logout"> Logout </a>
      </div>
    </div>

    <div id="menu-bar" class="menu-bar">
      <a class="menu-link inactive" href="/change">Make Change</a>
      <a class="menu-link" href="/account">Account</a>
    </div>
  </div>

  <div style="flex: 1;">
    <div class="column-container">
      <div class="app-container">
        <h3>Your balance</h3>
        <div class="balance">$0.00</div>
      </div>
    </div>
  </div>
</div>

Click the CSS tab, and paste the following code.

h1 {
    color: #096324;
  }

  h3 {
    color: #096324;
    margin-top: 20px;
    margin-bottom: 40px;
  }

  a {
    color: #096324;
  }

  p {
    font-size: 18px;
  }

  .header-email {
    color: #096324;
    margin-right: 20px;
  }

  .fine-print {
    font-size: 16px;
  }

  body {
    font-family: sans-serif;
    padding: 0px;
    margin: 0px;
  }

  .h-row {
    display: flex;
    align-items: center;
  }

  #page-container {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
  }

  #page-header {
    flex: 0;
    display: flex;
    flex-direction: column;
  }

  #logo-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
  }

  .menu-bar {
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
    height: 35px;
    padding: 15px 50px 15px 30px;
    background-color: #096324;
    font-size: 20px;
  }

  .menu-link {
    font-weight: 600;
    color: #FFFFFF !important;
    margin-left: 40px;
  }

  .menu-link {
    font-weight: 600;
    color: #FFFFFF !important;
    margin-left: 40px;
  }

  .inactive {
    text-decoration-line: none;
  }

  .button-lg {
    width: 150px;
    height: 30px;
    background-color: #096324;
    color: #FFFFFF !important;
    font-size: 16px;
    font-weight: 700;
    border-radius: 10px;
    text-align: center;
    padding-top: 10px;
    text-decoration-line: none;
  }

  .column-container {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }

  .content-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 60px 20px 20px 40px;
  }

  .balance {
    font-size: 50px;
    font-weight: 800;
  }

  .change-label {
    font-size: 20px;
    margin-right: 5px;
  }

  .change-input {
    font-size: 20px;
    height: 40px;
    text-align: end;
    padding-right: 10px;
  }

  .change-submit {
    font-size: 15px;
    height: 40px;
    margin-left: 15px;
    border-radius: 5px;
  }

  .change-message {
    font-size: 20px;
    margin-bottom: 15px;
  }

  .error-message {
    font-size: 20px;
    color: #FF0000;
    margin-bottom: 15px;
  }

  .app-container {
    flex: 0;
    min-width: 440px;
    display: flex;
    flex-direction: column;
    margin-top: 40px;
    margin-left: 80px;
  }

  .change-container {
    flex: 1;
  }

Click Save Changes.

Browse to WP Coder . Click Add New. In the title box at the top, enter change. In the HTML Code box, copy and paste the following code.

<div id="page-container">
  <div id="page-header">
    <div id="logo-header">
      <img
        src="https://fusionauth.io/cdn/samplethemes/changebank/changebank.svg"
      />
      <div class="h-row">
        <p class="header-email">[sv slug="sc-user-email"]</p>
        <a class="button-lg" href="/wp-login.php?action=logout"> Logout </a>
      </div>
    </div>

    <div id="menu-bar" class="menu-bar">
      <a class="menu-link" href="/change">Make Change</a>
      <a class="menu-link inactive" href="/account">Account</a>
    </div>
  </div>

  <div style="flex: 1">
    <div class="column-container">
      <div class="app-container change-container">
        <h3>We Make Change</h3>
        <div id="status" class="error-message">
          Please enter a dollar amount
        </div>
        <form>
          <div class="h-row">
            <div class="change-label" >Amount in USD: $</div>
            <input class="change-input" name="amount" value="0.00" id="total" />
            <input
              class="change-submit"
              type="submit"
              value="Make Change"
              onclick="makeChange(event)"
            />
          </div>
        </form>
      </div>
    </div>
  </div>
</div>

Click the CSS tab, and paste the following code.

h1 {
    color: #096324;
  }

  h3 {
    color: #096324;
    margin-top: 20px;
    margin-bottom: 40px;
  }

  a {
    color: #096324;
  }

  p {
    font-size: 18px;
  }

  .header-email {
    color: #096324;
    margin-right: 20px;
  }

  .fine-print {
    font-size: 16px;
  }

  body {
    font-family: sans-serif;
    padding: 0px;
    margin: 0px;
  }

  .h-row {
    display: flex;
    align-items: center;
  }

  #page-container {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
  }

  #page-header {
    flex: 0;
    display: flex;
    flex-direction: column;
  }

  #logo-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
  }

  .menu-bar {
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
    height: 35px;
    padding: 15px 50px 15px 30px;
    background-color: #096324;
    font-size: 20px;
  }

  .menu-link {
    font-weight: 600;
    color: #FFFFFF !important;
    margin-left: 40px;
  }

  .menu-link {
    font-weight: 600;
    color: #FFFFFF !important;
    margin-left: 40px;
  }

  .inactive {
    text-decoration-line: none;
  }

  .button-lg {
    width: 150px;
    height: 30px;
    background-color: #096324;
    color: #FFFFFF !important;
    font-size: 16px;
    font-weight: 700;
    border-radius: 10px;
    text-align: center;
    padding-top: 10px;
    text-decoration-line: none;
  }

  .column-container {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }

  .content-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 60px 20px 20px 40px;
  }

  .balance {
    font-size: 50px;
    font-weight: 800;
  }

  .change-label {
    font-size: 20px;
    margin-right: 5px;
  }

  .change-input {
    font-size: 20px;
    height: 40px;
    text-align: end;
    padding-right: 10px;
  }

  .change-submit {
    font-size: 15px;
    height: 40px;
    margin-left: 15px;
    border-radius: 5px;
  }

  .change-message {
    font-size: 20px;
    margin-bottom: 15px;
  }

  .error-message {
    font-size: 20px;
    color: #FF0000;
    margin-bottom: 15px;
  }

  .app-container {
    flex: 0;
    min-width: 440px;
    display: flex;
    flex-direction: column;
    margin-top: 40px;
    margin-left: 80px;
  }

  .change-container {
    flex: 1;
  }

Click on the JS tab, and paste the following code.

function makeChange(event) {
    event.preventDefault();
    const amount = document.querySelector('#total').value;
    const total = Math.trunc(parseFloat(amount) * 100) / 100;
    const totalString = isNaN(total) ? '' : total.toFixed(2);
    const nickels = Math.floor(total / 0.05);
    const nickelsString = nickels.toLocaleString();
    const pennies = (total - 0.05 * nickels) / 0.01;
    const penniesString = Math.ceil(Math.trunc(pennies * 100) / 100).toLocaleString();
    const hasError = !/^(\d+(\.\d*)?|\.\d+)$/.test(amount);
    let message = 'Invalid or missing amount';
    let css = 'error-message';
    if (!hasError) {
      message = 'We can make change for ' + totalString + ' with ' + nickelsString + ' nickels and ' + penniesString + ' pennies!';
      css = 'change-message';
    }
    document.querySelector('#status').innerHTML = message;
    document.querySelector('#status').className = css;
  }

Click Save Changes.

In the list tab of the WP Coder plugin, you can see the shortcodes of each page, like [wp_code id="1"]. You’ll use these codes to link the custom code to the actual page.

Add Email Shortcode Plugin

Add the plugin “Snippet Shortcodes” by Ali Colville. This plugin enables the shortcode [sv slug="sc-user-email"], which you might have noticed in the HTML of the account and change pages. The shortcode displays the user’s email on the page.

Add The Shortcodes To The Pages

Now you can use these shortcodes on the three pages. Browse to Pages and edit the account page. Click the hamburger menu at the top right and select Code editor. In the text box under the page title box, copy and paste the shortcode associated with account page which should look like [wp_code id="2"] and click Update.

Go back to the page list and edit the home page. Paste [wp_code id="1"] and click Update.

Edit the change page, paste [wp_code id="3"], and click Update.

Each of your previously blank pages now displays the custom HTML and CSS you added to the WP Coder custom shortcodes.

Run The Application

The demonstration application is now complete. Log out. Verify that you can’t browse to the account page. Log in using richard@example.com and password. The make change page will allow you to enter a dollar amount to see how many nickels and pennies you will get.

Next Steps

This quickstart is a great way to get a proof of concept up and running quickly, but to run your application in production, there are some things you're going to want to do.

FusionAuth Customization

FusionAuth gives you the ability to customize just about everything to do with the user's experience and the integration of your application. This includes:

Security

Tenant and Application Management

Troubleshooting

  • I get “This site can’t be reached localhost refused to connect” when I click the login button.

Ensure FusionAuth is running in the Docker container. You should be able to log in as the admin user admin@example.com with a password of password at http://localhost:9011/admin.

  • I get “Your browser sent a request that this server could not understand. Size of a request header field exceeds server limit”.

Open the app in an incognito browser window or clear your browser cache and cookies data.

  • docker compose command is not found.

Ensure you have the latest version of Docker, or try docker-compose instead. If on Linux, install docker.ce instead of docker.io.

  • It still doesn’t work.

Run the following in a terminal.

cd complete-application
docker compose up

Browse to http://localhost:3000 and log in with admin@example.com and password.

Now you can look around at the settings and plugins to see how the completed working application differs from yours.