Integrating security in your Nuxt 3 app with Appwrite Cloud
Published: 2023-06-19 09:11:54

Security is principally concerned with verifying identities. A typical example is logging into an application using an email or password, thus allowing the system to confirm that the entered credentials match the database's credentials.

[Appwrite Cloud](https://appwrite.io/cloud/?utm_source=hackmamba&utm_medium=hackmamba-blog) is an extension of the open-source version of Appwrite. It comes with all the services included in the open-source version but now with a fully managed service and minimum friction. 

This post discusses safeguarding user profiles using [Appwrite](https://cloud.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) [Cloud’s](https://cloud.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) out-of-the-box functionalities.

## GitHub
The project’s GitHub repository can be found [here](https://github.com/Tundesamson26/nuxt-appwrite-auth).

## Prerequisites 
To follow along with this tutorial, you should have a working knowledge of the following:

- Vue, Nuxt.js, and CSS
- An Appwrite cloud account

You can request access to Appwrite Cloud [here](https://appwrite.io/cloud/?utm_source=hackmamba&utm_medium=hackmamba-blog).

## Setting up the project
You need to create a Nuxt.js starter project by navigating to the desired directory and running the command below in your terminal.
```js
npx nuxi@latest init appwrite-auth
```

The command creates a Nuxt.js project called `appwrite-auth` .

Next, you need to install Nuxt.js dependencies by running the command below in your terminal.

```js
npm install
```

Next, go to the project directory and start the development server on `localhost:3000` with the commands below.

```js
cd appwrite-auth && npm run dev
```

## Installing dependencies

**Installing Pink Design**
[Pink Design](https://pink.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) is an open-source system from Appwrite used to build consistent and reusable user interfaces. It enhances collaboration, development experience, and accessibility.

To install Pink Design, open the terminal in the project directory and run the following command

```js
npm install @appwrite.io/pink
```

To use Pink Design in your project, import it into your project’s files like this:

```js
import '@appwrite.io/pink';
import '@appwrite.io/pink-icons';
```

**Installing Appwrite**
[Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) is a development platform that provides a powerful API and management console for building backend servers for web and mobile applications. To install it, run the command below:

```js
npm install appwrite
```
## Creating an Appwrite Cloud project

To get started, log into your Appwrite cloud, click the **Create project** button, input `appwrite-nuth-auth` as the name, and then click **Create**.

![Create-New-Project] (https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iu760i57zn55ok53tuga.png)

The project dashboard will appear on the console. Next, copy the **Project ID** you’ll use this to set up your Next.js application.

![Project-ID](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8kgizy2oa5c4qo3u4he8.png)

**Creating an Auth user**
On the left side of the Appwrite Cloud dashboard, click on the **Auth** tab.

![Auth-Tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ut3hoyxoyhvtqtge16p8.png)

Click the **Create user** button to fill in the **User** form with the necessary information. 

![Create-a-user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zemgsku1t9qnrwpcqtsm.png)

![User-data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g44z1n6ubnw73t7xa1v2.png)

After applying the necessary configurations on Appwrite, let’s start building the application.

## Integrating Appwrite Cloud into the Nuxt.js project

To integrate Appwrite into the UI, create a `utils/web-init.js` file. The file should look like this.

```js
import { Client, Account } from "appwrite";
    export const client = new Client();
    export const account = new Account(client);
    client
      .setEndpoint("https://cloud.appwrite.io/v1")
      .setProject("643fee63b2b5b506495c");
```
The code above does:

- Import the module `Client` and `Account` from appwrite
- Instantiates the `Client` and `Account` objects
- Uses the client object to set the endpoint and project

## Creating the signup page
Let’s create a signup page where people who will later be assigned roles to perform certain operations within the database can generically create an account. To do this, you will create  a `components/Sign-up.vue` and add the code below:

```vue
<template>
      <section>
        <div
          class="card u-cross-center u-width-full-line u-max-width-400"
          style="margin: 40px auto"
        >
          <form
            method="post"
            @submit.prevent="signUp"
            class="form u-margin-block-start-24"
          >
            <ul class="form-list">
              <li class="form-item">
                <label class="label">Email</label>
                <div class="input-text-wrapper">
                  <input
                    type="email"
                    class="input-text u-padding-inline-end-56"
                    placeholder="email address"
                    name="email"
                    v-model.lazy="email"
                  />
                </div>
              </li>
              <li class="form-item">
                <label class="label">Password</label>
                <div class="input-text-wrapper">
                  <input
                    type="password"
                    class="input"
                    placeholder="password"
                    name="password"
                    v-model.lazy="password"
                  />
                </div>
              </li>
              <li class="form-item">
                <label class="label">Confirm Password</label>
                <div class="input-text-wrapper">
                  <input
                    type="password"
                    class="input"
                    placeholder="password"
                    name="password"
                    v-model.lazy="confirmPassword"
                  />
                </div>
              </li>
            </ul>
            <div class="form-footer">
              <div class="u-flex u-main-end u-gap-12">
                <button class="button" type="submit">Signup</button>
              </div>
            </div>
          </form>
        </div>
      </section>
</template>
<script>
    import "@appwrite.io/pink"; // optionally, add icons import "@appwrite.io/pink-icons";
</script>
```

The code block above achieves the following:
- Imports the Appwrite Pink Design for styling
- Created a form to accept **email**, **password**, and **confirm** **password** for users to sign up

**Adding the signup functionality** 
Your interface will need to be connected to Appwrite to authenticate users. You will add the following code in the `<script>` tag of your `components/Signup.vue` file to do this.

```js
<script lang="ts">
    import "@appwrite.io/pink";
    import "@appwrite.io/pink-icons";
    import { account, client } from "~/utils/web-init";
    
    export default {
      data: () => ({
        name: "",
        email: "",
        password: "",
        confirmPassword: "",
      }),
      methods: {
        signUp: async function () {
          if (this.password.length >= 8) {
            if (this.password === this.confirmPassword) {
              try {
                await account.create(
                  "unique()",
                  this.email,
                  this.password,
                  this.name
                );
                alert("account created successfully");
                window.location.href = "/signin";
              } catch (e) {
                console.log(e);
              }
            } else {
              alert("password do not match");
            }
          } else {
            alert("password length should be up to 8 characters");
          }
        },
      },
    };
</script>
```
The code block above achieves the following:
- Imports the Appwrite SDK initialized in the `utils/web-``init.js` file
- Creates the `signUp` function in the `methods` property, which performs the following functions:
- Verifies that the password length is equal to or greater than eight characters
- Confirms that the characters in `password` and `confirmPassword` are the same
- Accesses Appwrite's services using the `account.create` to create a new account using the user's email, password, and name
- To use Appwrite's create account service, it's mandatory to add the `userId`; in this case,  `uniqueId` was used to generate one automatically
- Adding `email` and `password` is also mandatory
- The `name` option is optional; you can create an account without one
- `window.location.href` allowed us to navigate to the insight interface after successful account creation

Next, import the `components/Sign-up.vue` into the `pages/index.vue`, like so:

```vue
<template>
      <section class="u-text-center" style="margin: 50px auto;">
        <h1 class="u-font-size-32 u-text-center">Nuxt Authentication app</h1>
        <div class="u-cross-center">
            <Signup/>
        </div>
      </section>
</template>
<script>
 import "@appwrite.io/pink"; // optionally, add icons 
 import "@appwrite.io/pink-icons";
</script>
```
At this point, your signup page should look like the below:

![Sign-up-ui](https://paper-attachments.dropboxusercontent.com/s_AF732994FF42A294DE2E774CBC89ECFA7C147B938E82E51BAD937F0B1710D24F_1682102081975_image.png)

## Creating the sign-in interface
You also need to create a sign-in page that allows registered users to log in to the dashboard. To do this, you will create a `pages/Signin.vue` and add the code below:

```vue
<template>
   <section>
        <div
          class="card u-cross-center u-width-full-line u-max-width-400"
          style="margin: 100px auto"
        >
          <div class="u-flex u-main-space-between u-cross-center">
            <h6 class="heading-level-6">Welcome back!</h6>
            <button class="icon-x"></button>
          </div>
          <form
            method="post"
            @submit.prevent="signIn"
            class="form u-margin-block-start-24"
          >
            <ul class="form-list">
              <li class="form-item">
                <label class="label">Email</label>
                <div class="input-text-wrapper">
                  <input
                    type="email"
                    class="input-text u-padding-inline-end-56"
                    placeholder="email address"
                    name="email"
                    v-model.lazy="email"
                  />
                </div>
              </li>
              <li class="form-item">
                <label class="label">Password</label>
                <div class="input-text-wrapper">
                  <input
                    type="password"
                    class="input"
                    placeholder="password"
                    name="password"
                    v-model.lazy="password"
                  />
                </div>
              </li>
            </ul>
            <div class="form-footer">
              <div class="u-flex u-main-end u-gap-12">
                <button class="button" type="submit" @click="updateData">
                  Login
                </button>
              </div>
            </div>
          </form>
        </div>
  </section>
</template>
<script>
   import "@appwrite.io/pink";
   import "@appwrite.io/pink-icons";
   import {account, client} from '~/utils/web-init'
    
    export default {
      data() {
        return {
          email: "",
          password: "",
        };
      },
      methods: {
        signIn: async function () {
          try {
             await account.createEmailSession(
              this.email,
              this.password
            );
            alert("user signed in");
            this.$router.push({ path: `/profile` });
          } catch (e) {
            console.log(e);
          }
        },
      },
    };
</script>
```
The code snippet above does the following:
- Imported the Appwrite SDK initialized in the `utils/web-init.js` file
- Created a form to accept a valid email and password combination
- Created a function called `signIn` that does the following:
1. Accesses Appwrite's services using the `account.createEmailSession` to create a new account session using the user's email and password 
2. `this.$router.push` allows you to navigate to the profile interface after successful user login

After applying the configurations, the application will look like this:

![Appwrite’s Authentication page](https://paper-attachments.dropboxusercontent.com/s_AF732994FF42A294DE2E774CBC89ECFA7C147B938E82E51BAD937F0B1710D24F_1681991834119_image.png)

## Creating the profile page

The profile page is displayed when the user has been authenticated. Create a new `profile.vue` file inside the `pages` directory and paste the code below in it: 

```html
<template>
   <article class="card u-text-center">
      <img
        class="avatar is-size-x-large u-margin-inline-auto"
        src="https://source.unsplash.com/LaK153ghdig/132x132"
        alt="Kristin Watson"
        width="66"
        height="66"
      />
      <h3 class="body-text-2 u-margin-block-start-16">Kristin Watson</h3>
      <p class="u-margin-block-start-4 u-color-text-gray">kristin.watson@appwrite.io</p>
      <button class="button u-margin-inline-auto u-margin-block-start-24">
        <span class="text">Edit profile</span>
      </button>
   </article>
</template>
```
At this point, your application should look like this:

{% embed
https://www.loom.com/share/2c364cbb900e4e3ea8017b31a8023146?sid=1c69d460-f553-46e4-bc95-89f2fb741c7f %}

## Conclusion
This article discussed using [Appwrite](https://appwrite.io/cloud?utm_source=hackmamba&utm_medium=hackmamba-blog) [Cloud’s](https://appwrite.io/cloud?utm_source=hackmamba&utm_medium=hackmamba-blog) security management system and protocol to safeguard user profiles integrated into Nuxt 3 app.

## Resources
- [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite Cloud](https://appwrite.io/cloud?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite’s Authentication Guide](https://appwrite.io/docs/authentication?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite Pink Design](https://pink.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog)