Build Custom Authentication Using Appsmith and APISIX
Tags: webdev, api, security, lowcode
Published: 2023-06-06 07:39:55

Authentication flow is a fundamental part of web applications. It ensures the security and privacy of user data while they are using your app. While there are many off-the-shelf authentication solutions available, building an authentication system using **a low-code UI development platform** and **API management solution** allows you to create secure web applications with ease. You can create an application **without having knowledge of both frontend and backend technologies and tools**. You do not need to know Python, Java, HTML, CSS, or other JavaScript frameworks. In this post, you’ll learn how to build a custom simple login flow and pages on UI to secure your application using [Appsmith](https://www.appsmith.com/), [Apache APISIX](https://apisix.apache.org/), and [JWT](https://jwt.io/).

> Appsmith is a powerful low-code development platform that enables users to easily create web applications and dashboards. It provides a visual interface and a comprehensive set of pre-built components, making it accessible to developers and non-developers.

## Learning objectives

You will learn the following throughout the article:

- Design an authentication process in low-code environment.
- Set up the backend authentication API with APISIX.
- Create UI Pages using widgets in Appsmith.
- Enable token-based authentication.

## Design the Authentication Architecture

Before diving into implementation, it is important to first design the architecture of your authentication system for your application. Consider the key components such as user registration, login, password, session management, and JWT token-based authentication. Define the flow of information between Appsmith and APISIX, ensuring a clear and efficient authentication workflow.

![Build Custom Authentication Using Appsmith and APISIX.png](https://static.apiseven.com/uploads/2023/06/03/LrWHv3rg_Build%20Custom%20Authentication%20Using%20Appsmith%20and%20APISIX.png)

We are going to **build a simple mobile app** that has 3 pages *Registration, Login, and Main* pages respectively. Tasks we do divide into two parts. In the first part, We will **set up the backend API** with [Apache APISIX](https://apisix.apache.org/) API Gateway that will handle authentication requests. We use existing API Gateway endpoints to achieve user registration, login, and token generation flows. In the second part, we use Appsmith’s drag-and-drop interface with ready UI components to build the *Registration, Login, and Main* pages and finally, we connect them to API to handle form submissions.  Let’s start with building these components in the following sections.

![Registration, Login, and Main](https://static.apiseven.com/uploads/2023/06/03/KWAQpniy_Build%20Custom%20Authentication%20Using%20Appsmith%20and%20APISIX%20%281%29.png)

## Part 1: Set Up the backend authentication API

We start by setting up the backend API that will handle authentication requests from the mobile app. APISIX can be utilized to enforce authentication to protect API endpoints. APISIX allows you to validate user credentials, issue authentication tokens, and control access to your APIs. By integrating APISIX into your mobile authentication system, you can add an additional layer of security and ensure that only authenticated users can access your protected resources.

### Prerequisites

- [Docker](https://docs.docker.com/get-docker/) is used to installing the containerized etcd and APISIX.
- [curl](https://curl.se/) is used to send requests to APISIX Admin API. You can also use tools such as [Postman](https://www.postman.com/) to interact with the API.

### Step 1: Install Apache APISIX

APISIX can be easily installed and started with the following quickstart script:

```bash
curl -sL https://run.api7.ai/apisix/quickstart | sh
```

### Step 2: Configure the backend service (upstream)

Next, we configure our backend service. For demo purposes, it can be any API service that serves our backend logic. You can replace it with your service too. I use a mock public server http://httpbin.org/ that randomly generates responses. For simplicity, we will have a single endpoint that returns the public IP address of our machine in this endpoint http://httpbin.org/ip.  

To route requests to the backend service for the mock API, you'll need to configure it by adding an upstream server in Apache APISIX via the [Admin API](https://apisix.apache.org/docs/apisix/admin-api/).

```bash
curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -X PUT -d '
{
   "name":"Mock API upstream",
   "desc":"Register Mock API as the upstream",
   "nodes":{
      "httpbin.org:80":1
   }
}'
```

### Step 3: Create a new plugin config

This step involves configuring a plugin (using the [Plugin Config](https://apisix.apache.org/docs/apisix/terminology/plugin-config/) object) for a route we create in the next step. So, APISIX enables the JWT plugin to secure our endpoints. Each time we request the endpoint, it checks JWT credentials in the request header.

```bash
curl http://127.0.0.1:9180/apisix/admin/plugin_configs/1 -X PUT -d ' 
{
   "plugins":{
      "jwt-auth": {}
   }
}'
```

### Step 4: Create a Route for the backend API

We create a new [Route object](https://apisix.apache.org/docs/apisix/terminology/route/) in APISIX that intercepts all GET requests to `/ip` URI, and uses the existing upstream and plugin configurations to enable the routing mechanism and authentication policies. It checks for the JWT plugin in the header, and if it exists and valid, forwards the request to our mock server. Otherwise, it returns an unauthorized error immediately and the request will not reach the actual service.

```bash
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -X PUT -d '
{
   "name":"Mock API server route",
   "desc":"Create a new route in APISIX for the mock server endpoint",
   "methods":[
      "GET"
   ],
   "uri":"/ip",
   "upstream_id":"1",
   "plugin_config_id":1
}'
```

### Step 5: Create a Route for signing the JWT token

We implemented token-based authentication for our API. APISIX can also act as an identity provider to generate and validate tokens. To do so, you need to set up a Route for a new API endpoint that signs the token using the [public-api](https://apisix.apache.org/docs/apisix/plugins/public-api/) plugin:

```bash
curl http://127.0.0.1:9180/apisix/admin/routes/login -X PUT -d '
{
    "uri": "/login",
    "plugins": {
        "public-api": {
            "uri": "/apisix/plugin/jwt/sign"
        }
    }
}'
```

By executing the above curl command, we registered a new route called `login` with the URI path `/login` that signs a new token whenever an existing user attempts to log in from the Login page on the mobile app using their emails.

## Part 2: Create User Registration and Login Forms in Appsmith

Using Appsmith's low-code interface, we can create user registration and login forms. Appsmith provides a wide range of [pre-built widgets](https://docs.appsmith.com/reference/widgets) that can be easily customized. Design the forms with input fields for username, password, and any additional information you require in the dashboard.

### Before you begin

I am going to miss the installation part of Appsmith on your machine. You can learn how to [install Appsmith using Docker](https://docs.appsmith.com/getting-started/setup/installation-guides/docker) on the Appsmith website. Make sure that you installed Appsmith and you can access it at [http://localhost](http://localhost/). When you deploy and run Appsmith, an application titled `My first application` is added by default. You can use this application to build your first app.

![My first application Appsmith](https://static.apiseven.com/uploads/2023/06/03/UjAxSeQv_My%20first%20application%20Appsmith.png)

### Step 1: Create a Registration page

In our case, a new user first registers on a mobile app from the Registration page. Start by creating a [new page](https://docs.appsmith.com/learning-and-resources/tutorials/building-a-store-catalog-manager#creating-your-first-page) called **RegistrationPage** in your application. Add [Input widgets](https://docs.appsmith.com/reference/widgets/input) for email (named **EmailInput**), username (named **UsernameInput**), and password (**PasswordInput**). Also, add Register(named **RegisterButton**) and Login (named **LoginButton**) [Button widgets](https://docs.appsmith.com/reference/widgets/button) to the drawing board. The final result looks like below:

![RegistrationPage](https://static.apiseven.com/uploads/2023/06/03/mQbt72Fc_Registration%20page%20Appsmith.png)

When a user presses the Register button with provided input details, you'll need a query to handle communication with the APISIX Admin API endpoint to register a new API consumer in the API Gateway.  Create an [API query](https://docs.appsmith.com/core-concepts/connecting-to-data-sources/authentication/connect-to-apis) (named **APISIX_Admin_Add_Consumer_API**) with APISIX consumers endpoint URI `/apisix/admin/consumers`. Place the **Input widgets** text into your query body. Accessing the Input widgets should look something like this:

![API query for JWT token](https://static.apiseven.com/uploads/2023/06/03/P7xRYHuD_API%20query%20for%20Auth%20JWT.png)

> Note that we use the address of `host.docker.internal` instead of [localhost](http://localhost) because APISIX is running inside its own container on a different docker network than Appsmith.
>

After the query is sent to APISIX, it registers the new consumer, and the consumer object will use `jwt-auth`plugin with key and secret. You can test if the consumer is registered in the system successfully but fetching the specified consumer by username `appsmithuser`. Run this curl command:

```bash
curl http://127.0.0.1:9180/apisix/admin/consumers/appsmithuser
```

While existing users can go directly to the Login page. See in the next section.

### Step 2: Create a Login page

Back on the application canvas, add a new page called **Login page** and set up the **Login form**'s with Input (for entering the user’s email) and Button (for login) widgets.  

![Login page](https://static.apiseven.com/uploads/2023/06/03/CkfwcZV0_Login%20page.png)

Then create an [API query](https://docs.appsmith.com/core-concepts/connecting-to-data-sources/authentication/connect-to-apis) (named **login_api**) for for APISIX login route URI path `/login` and set `key` param to `{{EmailInput.text}}`. If you test the query and push the run button, on a successful response, our authentication API Gateway endpoint should return a valid access token. In the example below, the `jwt` key is a token that indicates that the user has been authenticated on the APISIX side.

![Rest call to login endpoint](https://static.apiseven.com/uploads/2023/06/03/zxaz4jMu_Rest%20call%20to%20login%20endpoint.png)

To run the **login_api** query via the **Login** button, you need to set the query **onClick** property.

![login_api](https://static.apiseven.com/uploads/2023/06/03/Dn0rP5iI_login_api.png)

It is also possible to store the JWT token in the [Appsmith store](https://docs.appsmith.com/reference/appsmith-framework/widget-actions/store-value) and then take the user to the **MainPage.** To do so, insert the below code to the `login_api` action of **Login page** in the **onClick** property:

```js
{{login_api.run(() => {
  const jwt = login_api?.data;
  if (jwt) {
    storeValue('jwt', jwt);
    navigateTo('MainPage', {});
  } else {
    showAlert('Login failed!', 'error');
  }
})}}
```

![login_api on click](https://static.apiseven.com/uploads/2023/06/03/whABl4t3_login_api%20on%20click.png)

If the user fails to authenticate with APISIX, [show an alert message](https://docs.appsmith.com/reference/appsmith-framework/widget-actions/show-alert) as a callback to tell the user that there was an error.

### Step 3: Create a Main page

Finally, now, it's time to configure the **MainPage** of the mobile app to allow access to logged-in users and show some data. You can use the same canvas to build your UI from widgets. Once the user successfully logged in, our logic navigates to **MainPage**, and on the first-page load, it makes an API call automatically to **the route** http://127.0.0.1:9080/ip in APISIX using the query you add (named **main_page_data_api**) and retrieves the IP address from the upstream server (we created in Part 1 and at step 2).

![main_page_data_api](https://static.apiseven.com/uploads/2023/06/03/9tdtPHbr_main_page_data_api.png)

You may notice in the `Authorization` header the value `{{appsmith.store.jwt}}` the `jwt` value that we saved in the Appsmith store in the previous step which is used to prove to your application that the user is recognized. If the `jwt` value does not exist in the [Appsmith store](https://docs.appsmith.com/reference/appsmith-framework/widget-actions/store-value), we show an unauthorized error to the user.

In my case, I added two [Text widgets](https://docs.appsmith.com/reference/widgets/text) to the **MainPage** and set the text field value of the second to `{{main_page_data_api.data}}` which is simply output data from `main_page_data_api`call. See the result.

![Main page](https://static.apiseven.com/uploads/2023/06/03/4dEFnUAx_MainPage.png)

## Next steps

You can also add one **Unauthorized page** for redirecting unauthorized users to that page, show the error and suggest they log in or register to create a new account. Provide your users with the ability to [log out of your app](https://docs.appsmith.com/advanced-concepts/custom-authentication#log-out-users) with a button widget when they're finished which can help increase the security of your data.

## Conclusion

By following the above steps, we created the personalized authentication system using Appsmith and APISIX. Appsmith is suitable for a wide range of use cases, from building internal tools and admin dashboards to prototyping and developing full-fledged applications. With APISIX, you can not only enforce authentication for your users but also introduce additional security measures such as rate limiting, IP blocking, and consumer restriction to maintain the security of our custom authentication solution.

### Related resources

- [API Gateway Authentication.](https://api7.ai/blog/api-gateway-authentication)
- [Apache APISIX Authorization Policy: Protect Your APIs.](https://api7.ai/blog/apisix-permission-policy)
- [Deep Dive into Authentication in Microservices.](https://api7.ai/blog/understanding-microservices-authentication-services)

### 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/)

### About the author

Follow me on Twitter: [@BoburUmurzokov](https://twitter.com/BoburUmurzokov)

Visit my blog: [www.iambobur.com](https://www.iambobur.com/)