How to build a full-stack authentication app
Tags: webdev, authentication, javascript, programming
Published: 2023-08-31 10:11:53

Most web applications need a sign-up and login feature. But for newbies, this can be challenging. Even expert developers prefer using external services to handle authentication right from the start. When we talk about a full-stack authentication flow, it means setting up user sign-in and registration on the frontend and also securing the backend API. So, you have to work on both parts.

This post will guide you through building a full-stack authentication app with [Apache APISIX](https://apisix.apache.org/), [Authgear](https://www.authgear.com/), and [OpenID Connect](https://openid.net/developers/how-connect-works/) (OIDC). You can find the project's source code on GitHub. For a swift start with the app, simply clone the repository and execute the code sample, following the steps provided in the [README.md](https://github.com/Boburmirzo/apisix-authgear-oidc-full-stack-auth/blob/main/README.md) file.

## Learning objective

This content aims to show everyone how to set up authentication on both the backend and frontend. Additionally, it's designed to assist both beginners and experienced developers who want to become full-stack developers.

## The role of APISIX, Authgear, and OIDC in authentication

Before diving into the guide, let's introduce the tools shortly we'll be using.

- **OIDC (OpenID Connect)** is a simple identity layer built on top of the OAuth 2.0 protocol. It enables third-party applications to verify users and obtain basic profile information in a standardized manner.

- **APISIX** stands out as one of the most popular open-source API gateways. It's designed not just for API management, but also to ensure the security and protection of these APIs. One of the most prominent features in its security arsenal is the support for OIDC using its [plugin](https://apisix.apache.org/docs/apisix/plugins/openid-connect/).

- **Authgear** is a highly adaptable identity-as-a-service (IDaaS) platform for web and mobile applications. Your users can log in to your application through a built-in UI interface (You do not need to build UI for users registration and login flow), which provides them with a secure, standards-based login experience that you can customize with your own branding and various authentication methods, such as email, [social logins](https://www.authgear.com/features/social-login), [passwordless](https://www.authgear.com/features/passwordless-authentication), [biometrics logins](https://www.authgear.com/features/biometric-authentication), [one-time-password (OTP)](https://www.authgear.com/features/whatsapp-otp) with SMS/WhatsApp, and multi-factor authentication (MFA). It uses OpenID Connect (OIDC) and OAuth 2.0 to identify who a user is and grant authorization to protected resources.

## The authentication workflow

Here is a high-level architectural diagram of how the authentication process looks like:

![The authentication workflow with OIDC, APISIX and Authgear](https://static.apiseven.com/uploads/2023/08/23/LgABNvi8_Global%20Community%20Meeting%20slides%20%281%29.png)

The steps shown in the diagram are explained in detail below:

In the above diagram, the **Client** is any web application, **API Gateway** is APISIX and **Identity provider** is Authgear and **Upstream** is a backend API.

1. A web app can take various forms, from Single Page Apps (SPA) built with React, Vue, or Angular, to standard web applications crafted using frameworks like Express, NextJS, and similar platforms. The web app is our client app with frontend sends a request to an Identity Provider (Authgear) with client Id, a client secret to collect an access token like [JSON Web Tokens](https://jwt.io/) (JWT).
2. If the provided credentials are correct, Authgear replies with a JWT token to the web app. You can create as many users for your app in [Authgear portal](https://portal.authgear.com/) and users can log in using **UI pages** hosted by Authgear.
3. After having the JWT token, the client sends a request to an API Gateway (APISIX) with the access token, and backend APIs protected by the gateway.
4. Before processing the request, the APISIX needs to ensure that the provided token is valid, has not expired, and has the right scopes for the requested data or service. If the APISIX cannot locally validate the token, it sends the token introspection request to the Authgear authorization server. This request is typically made to the **`introspection`** endpoint of the server.
5. The Authgear receives the introspection request and processes it. The server checks its records to determine the token's validity, its expiration, and associated scopes, and after determining the token’s state, it responds to APISIX.
6. Based on Authgear’s token introspection response, the APISIX can then make an informed decision. If the token is valid, it forwards the request to the backend API, otherwise, it rejects the client’s request with an unauthorized HTTP status code.
7. APISIX sends the response from the backend API with the requested resources.

## Full-stack authentication app with APISIX, Authgear, and OIDC.

For the [demo project](https://github.com/Boburmirzo/apisix-authgear-oidc-full-stack-auth), we used Docker to install and run 3 components (backend, API Gateway, and frontend) with a single command. We employed [ExpressJS](https://expressjs.com/) for the frontend web app, hosting our single page app at [localhost:3000](http://localhost:3000/). The APISIX Gateway can be accessed at [localhost:9080](http://localhost:9080/), while our backend API (it can be any API you build using Python, Java, NodeJS and etc.) is set up on [localhost:9081](http://localhost:9081/).

## Prerequisites

Before you begin, you'll need the following:

- A **free Authgear account**. [Sign up](https://oursky.typeform.com/to/S5lvI8rN) if you don't have one already.
- [Docker](https://docs.docker.com/get-docker/) is used to install all services.

## Configure Authgear

To use Authgear services, you’ll need to have an application set up in the Authgear [Dashboard](https://portal.authgearapps.com/) and get Authgear OIDC Client information. This setup allows users in Authgear to sign in to the web application automatically once they are authenticated by Authgear.

### Step 1: Create an application in Authgear

To set up the application, navigate to the [Authgear Portal UI](https://portal.authgear.com/) and select **Applications** on the left-hand navigation bar. Use the interactive selector to create a new **Authgear OIDC Client application.**

![Create an application in Authgear](https://static.apiseven.com/uploads/2023/08/23/gsMzZQl3_Untitled%20%282%29%20%281%29.png)

### Step 2: Copy the app credentials

Every application in Authgear is assigned an alphanumeric, unique `CLIENT ID` and `CLIENT Secret` that your application code will use to call Authgear APIs int the web app. Record the generated Authgear `ISSUER` (for example, `https://example-auth.authgear-apps.com`), `CLIENT ID`, `CLIENT SECRET` from the output. You will use these values in the next step for the web app config.

![Copy the app credentials](https://static.apiseven.com/uploads/2023/08/23/rJUTBuc7_Untitled%20%283%29%20%283%29.png)

### Step 3: Configure Redirect URI

An **Authorized Redirect URI** of your application is the URL that Authgear will redirect to after the user has authenticated in order for the **OpenID Connect middleware** to complete the authentication process. In our case, it will be a home page for our frontend and it will run at http://localhost:3000.

Set the following [http://localhost:3000](http://localhost:3000/) accordingly to the **Authorized Redirect URIs** field. ****If not set, users will not be returned to your application after they log in.

### Step 4: Enable Access Token

Also, enable **Issue JWT as an access token** option under the **Access Token** section of the app configuration:

![Enable Access Token Authgear](https://static.apiseven.com/uploads/2023/08/23/uNRpBGaO_Enable%20Access%20Token%20Authgear.png)

### Step 5: Choose a Login method

After you created the **Authgear app**, you choose how users need to **authenticate on the login page**. From the **Authentication** tab, navigate to **Login Methods**, you can choose a **login method** from various options including, by email, mobile, or social, just using a username or the custom method you specify. For this demo, we choose the **Email+Passwordless** approach where our users are asked to register an account and log in by using their emails. They will receive a One-time password (OTP) to their emails and verify the code to use the app.

![Choose a Login method](https://static.apiseven.com/uploads/2023/08/23/GkCc2LZT_Untitled%20%284%29%20%281%29.png)

## Set up and run the demo project

With Authgear configured successfully, now we can bring the GitHub repo, configure environment variables and run the services:

Start by cloning the [project](https://github.com/Boburmirzo/apisix-authgear-oidc-full-stack-auth) into your local machine:

```bash
git clone https://github.com/Boburmirzo/apisix-authgear-oidc-full-stack-auth.git
```

Make the project directory your current working directory:

```bash
cd apisix-authgear-oidc-full-stack-auth
```

In the root directory of your project where Docker compose yaml file, create a file `.env` with the following environment variables:

```
CLIENT_ID={AUTHGEAR_APP_CLIENT_ID}
CLIENT_SECRET={AUTHGEAR_APP_CLIENT_SECRET}
ISSUER={AUTHGEAR_ISSUER}
REDIRECT_URI=http://localhost:3000
```

Replace values in the brackets with your Authgear app settings values from **Configure Authgear** section above such as `Issuer`, `ClientId`, `ClientSecret`

After you added the environment file, run the `docker compose up` command from the root directory.

## Test authentication flow

For the demo, we used Docker to install and run 3 components (backend, API Gateway, and frontend) with a single command. We employed ExpressJS for the frontend web app, hosting our single page app at localhost:3000. The APISIX Gateway can be accessed at localhost:9080, while our backend API (it can be any API you build using Python, Java, NodeJS and etc.) is set up on localhost:9081.

![Authgear login page](https://static.apiseven.com/uploads/2023/08/23/DDvhAa7J_Untitled%20%288%29%20%281%29.png)

After you signed up using your email, you will receive a one-time password (OTP):

![receive a one-time password](https://static.apiseven.com/uploads/2023/08/23/zJDVypdn_Untitled%20%289%29%20%281%29.png)

Once you have authenticated, you are allowed to request API resources and you get a response from the backend service:

![the backend service response](https://static.apiseven.com/uploads/2023/08/23/VydS3uLY_Untitled%20%2825%29.png)

APISIX enforced OIDC authentication with Authgear and provided a secure and streamlined authentication flow with easy setup.

## Next steps

This combination of tools we used ensured security allowing developers to focus on core business logic instead of the complexities of the authentication process. From now on, you have the authentication feature enabled, you can begin to build your UI for the home page, show data from API and develop other pages.

### Related resources

[Apache APISIX Authorization Policy: Protect Your APIs](https://api7.ai/blog/apisix-permission-policy)

[Set Up SSO with OIDC and Keycloak](https://docs.api7.ai/apisix/how-to-guide/authentication/set-up-sso-with-oidc-and-keycloak)

### Community

🙋 [Join the Apache APISIX Community](https://apisix.apache.org/docs/general/join/)

🐦 [Follow us on Twitter](https://twitter.com/ApacheAPISIX)

📝 [Find us on Slack](https://join.slack.com/t/the-asf/shared_invite/zt-vlfbf7ch-HkbNHiU_uDlcH_RvaHv9gQ)

💁 [How to contribute page](https://apisix.apache.org/docs/general/how-to-contribute/)