How to Build a Full-Stack Authentication App
August 24, 2023
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, Authgear, and OpenID Connect (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 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.
-
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, passwordless, biometrics logins, one-time-password (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 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.
- 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 (JWT).
- 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 and users can log in using UI pages hosted by Authgear.
- 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.
- 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. - 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.
- 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.
- 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, 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.
Prerequisites
Before you begin, you'll need the following:
- A free Authgear account. Sign up if you don't have one already.
- 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 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 and select Applications on the left-hand navigation bar. Use the interactive selector to create a new Authgear OIDC Client application.
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.
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 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:
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.
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 into your local machine:
git clone https://github.com/Boburmirzo/apisix-authgear-oidc-full-stack-auth.git
Make the project directory your current working directory:
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.
After you signed up using your email, you will receive a one-time password (OTP):
Once you have authenticated, you are allowed to request API resources and you get a response from the backend service:
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.