Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions docs/next/guides/authentication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
---
slug: /next/guides/auth
title: Authentication
description: Use Faust.js' built-in authentication strategies to authenticate users from your WordPress backend
---

Authentication can be a cumbersome process when building headless WordPress sites. Thankfully, Faust.js takes care of all your authentication needs in your Next.js application.

## How It Works

**TL;DR**: Authentication in Faust.js can be boiled down to 5 main steps:

1. User initiates request to authenticated data
2. Faust.js facilitates the request for an authorization code from the WPE Headless plugin. This is a short lived token that is used to request a refresh and access token
3. Faust.js facilitates the request for a refresh and access token from the WPE Headless plugin using the authorization code
4. Faust.js stores the refresh token in a secure, http only cookie. The refresh token is used to request a new access token when the current one expires
5. Faust.js stores the access token in memory to be used in subsequent authenticated requests

## Strategies

There are two authentication strategies available in Faust.js: `redirect` and `local`

### Redirect Based Authentication

<a href="/docs/img/auth-redirect-flow.png" target="_blank">
<img
src="/docs/img/auth-redirect-flow.png"
alt="Diagram of the redirect based authentication flow"
/>
</a>

Redirect based authentication is the default strategy in Faust.js. This strategy involves the user being redirected to WordPress to authenticate. Once the user has authenticated, the user is redirected back to the Next.js application with an authorization code that is then used to request a refresh and access token, thus completing the login process.

This strategy is great for use cases where your authenticated users are admins/editors/etc. and do not necessarily need a "white label" login/register experience. Typically, you would use the redirect strategy if your primary reason for authentication is previews.

Since Redirect based authentication is the default authentication method, there is no configuration needed on your end to use it. It comes out of the box, and you'll see it in action when using previews or the `useAuth` hook.

### Local Based Authentication

<a href="/docs/img/auth-local-flow.png" target="_blank">
<img
src="/docs/img/auth-local-flow.png"
alt="Diagram of the local based authentication flow"
/>
</a>

Local Based Authentication is the second strategy available in Faust.js. This strategy involves the user initiating a login request from the Next.js application via the `useLogin` hook. Upon successful login, `useLogin` returns an authorization code that is then used to request a refresh and access token, thus completing the login process.

This strategy is great for use cases where you want to support a more "white label" login/register experience. This strategy routes un-authenticated requests to your specified Next.js login page. In addition, users who wish to login/register will not have to interact with WordPress or the WordPress backend at all, giving you the flexibility to implement and fine tune your user flow.

To use this strategy, you'll need to configure your `faust.config.js` file to use the `local` authentication strategy, in addition to the route of your Next.js login page. Take the following `faust.config.js` file for example:

```tsx title=faust.config.js {15,16}
import { headlessConfig } from '@faustjs/core';

if (!process.env.NEXT_PUBLIC_WORDPRESS_URL) {
console.error(
'You must provide a NEXT_PUBLIC_WORDPRESS_URL environment variable, did you forget to load your .env file?',
);
}

/**
* @type {import("@faustjs/core").HeadlessConfig}
*/
export default headlessConfig({
wpUrl: process.env.NEXT_PUBLIC_WORDPRESS_URL,
apiClientSecret: process.env.WP_HEADLESS_SECRET,
authType: 'local',
loginPagePath: '/login',
});
```

We define the `authType` to `local` to indicate to the Faust.js config that we want to use the `local` strategy for authentication. We also define the `loginPagePath` to `/login` to indicate the route of the Next.js login page. This means un-authenticated requests will be redirected to the `/login` route in your Next.js application.

In your `login.tsx` page, you could take advantage of the `useLogin` hook to initiate a login request to the WordPress backend:

```tsx title=pages/login.tsx {9,18}
import { client } from 'client';
import { useState } from 'react';

export default function Login() {
const { useLogin } = client.auth;
const [usernameEmail, setUserNameEmail] = useState('');
const [password, setPassword] = useState('');

const { login, isLoading, data, error } = useLogin();

const errorMessage = data?.error || error?.message;

return (
<form
onSubmit={(e) => {
e.preventDefault();

login(usernameEmail, password);
}}>
<div>
<div>
<label htmlFor="usernameEmail">Username or Email</label>
</div>
<div>
<input
type="text"
value={usernameEmail}
onChange={(e) => setUserNameEmail(e.target.value)}
id="usernameEmail"
/>
</div>

<div>
<label htmlFor="password">Password</label>
</div>
<div>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
id="password"
/>
</div>

<div>
<button type="submit">Login</button>
</div>
</div>

{errorMessage ? <p>Error: {errorMessage}</p> : null}
</form>
);
}
```

The `useLogin` hook exports an object with the following properties:

- `login`: a function that initiates a request to the WordPress backend for an authorization code that accepts two arguments: `usernameEmail`, which is either the user's username or email as a string, and `password` as a string.
- `isLoading`: a boolean that indicates whether the login request is in progress.
- `data`: the response data from the login request.
- `error`: the error from the login request.

For a more detailed explanation of the `useLogin` hook, see the [`useLogin` hook docs](/docs/next/reference/custom-hooks#uselogin) .

Upon a successful login, a refresh token will be stored in a secure, http only cookie, as well as the access token in memory to use for subsequent authenticated requests. A login request can be confirmed it succeeded by checking for the `code` property in the `data` object.

Additionally, if the login page URL contains a `redirect_uri` query parameter, the user will be redirected to the specified URL upon successful login.

<video
width="100%"
src="/docs/video/next/local-auth-flow-previews.mp4"
muted
autoPlay
playsInline
controls
loop
/>

## Making Authenticated Requests

In the Faust.js client, you can use `useQuery`, `usePost`, `usePage`, etc. to make a request to the WordPress backend.

These are exported from the `client` like so:

```tsx {1,4}
import { client } from 'client';

export default function Page() {
const { useQuery } = client;

return(
...
)
}
```

Requests using the above methodology will be un-authenticated.

To make authenticated requests, use the `auth` property exported from the `client`. This is essentially a replica of the `client`, except every request gets called with an access token:

```tsx {1,4,5}
import { client } from 'client';

export default function Page() {
const { useMutation, usePreview, useAuth } = client.auth;
const { isLoading, isAuthenticated } = useAuth();

if (isLoading) {
return <div>Loading...</div>;
}

if (!isAuthenticated) {
return <div>You are not authenticated!</div>;
}

return <div>Authenticated content</div>;
}
```

**Note:** The `useAuth` hook fetches the applicable tokens and ensures that the user is authenticated. Therefore, you should check for `isAuthenticated` prior to making authenticated requests, as doing so too early will result in a request without a valid access token.
Loading