How to setup nuxt-auth v6 authentication with the "credentials" provider on nuxt3 project
Tags: nuxtauth, vue, nuxt, webdev
Published: 2023-07-22 13:09:14



> **nuxt-auth** is an open source Nuxt module that provides authentication for non-static Nuxt 3 applications.  - [sidebase](https://sidebase.io/nuxt-auth/getting-started)
> The easiest way to get started with nuxt-auth is using the sidebase Merino stack: - [sidebase](https://sidebase.io/nuxt-auth/getting-started)

My Opinion:

It disappoints when I have to go through the entire documentation of a module for a basic implementation. This happened to me when I was setting up nut-auth on my client’s project. Coming from Nuxt 2 to Nuxt 3 a lot had changed. And with such changes came newer Nuxt modules, most of which had a different implementation. It took me a considerable amount of time to set up nuxt-auth for the first time. I’m going to write about my implementation so that you don’t have to go through the same “struggle” as I did.

A BTW: What did the senior dev say to the junior dev? 'I am the documentation!' 

**TLDR;**
Setting up nuxt-auth with credentials provider: Quick

Note: This guide assumes that your api lives in a different environment.

Lets dive in.

## Step 1: Create a new Nuxt app.

Open your favourite terminal, navigate to your projects folder and run this command.
```console
npx nuxi@latest init my-app
```
If you have already setup a nuxt project, you can skip to the next step.

## Step 2: Install nuxt-auth module.
Install nuxt-auth by running this command on the root folder of your project

```console
// npm
npm i -D @sidebase/nuxt-auth

// yarn
yarn add @sidebase/nuxt-auth
```
For this article, I used `"@sidebase/nuxt-auth": "0.6.0-beta.3",`

## Step 3: Add nuxt-auth to nuxt.config.ts
Open the project on your favourite editor, preferably VSCode. 
Open nuxt.config.ts file located in the root of your project, look for the modules option and add `@sidebase/nuxt-auth`

It should look like this:

```ts
export default defineNuxtConfig({
   modules: ['@sidebase/nuxt-auth'],
})
```

## Step 4: More configs on nuxt.config.ts
While on the nuxt.config.ts file, at the same level as modules, add the auth configs as shown below. Each option has comments. For more options, checkout the official documentation.
```ts
/* Auth */
  auth: {
    globalAppMiddleware: true,
    baseURL: process.env.NUXT_PUBLIC_API_URL,
    provider: {
      type: 'local',
      endpoints: {
        signIn: { path: '/identity/accounts/login', method: 'post' },
        signOut: { path: '/identity/accounts/logout', method: 'get' },
        signUp: { path: '/identity/accounts/register', method: 'post' },
        getSession: { path: '/identity/me', method: 'get' }
      },
      pages: {
        login: '/signin'
      },
      token: {
        signInResponseTokenPointer: '/accessToken'
      },
      sessionDataType: {}
    },
    enableSessionRefreshPeriodically: 5000,
    enableSessionRefreshOnWindowFocus: true,
    globalMiddlewareOptions: {
      allow404WithoutAuth: true, // Defines if the 404 page will be accessible while unauthenticated
      addDefaultCallbackUrl: ‘/' // Where authenticated user will be redirected to by default
    }
  }
```

Here I have explained each of the options above.

**`globalAppMiddleware`** 
Setting this to `true` protect all routes by default. 

If you want to exempt a route from the auth middleware, add this code on the page’s [definePageMeta macro:](https://nuxt.com/docs/api/utils/define-page-meta#definepagemeta)

```ts
definePageMeta({
  auth: false,
})
```

If you want a page to be accessible only when logged out, add this to definePageMeta macro:

```ts
definePageMeta({
  auth: {
    unauthenticatedOnly: true,
    navigateAuthenticatedTo: ‘/‘, // Where the user should be redirected if not logged in
  },
})
```

**`baseURL`** - The base api url to your auth module

**`provider`**
The authentication provide. For this article, we are going to focus on the local provider. Inside here, we will define the provider type and options.

        `type: ‘local'` - We’re going to use the local provider
	`endpoints` - define the authentication endpoints for:
		`signIn`
		`signOut`
		`signUp`
		`getSession` - This is the url for fetching the logged in user data

**`token`** 
Takes in **`signInResponseTokenPointer`** which is basically the key that contains the accessToken after a successful login.

**Note: This was the most confusing part for me. **
For instance, if the login response looks like this:

```ts
{
    accessToken: 'Bearer <token>',
    status: 'success'
}
```

Then the token option should look like this:
```ts
token: {
  signInResponseTokenPointer: '/accessToken'
}
```

To read more about all the possible options checkout the [nuxt-auth options documentation](https://sidebase.io/nuxt-auth/configuration/nuxt-config).

## Step 5: Setup your signIn, signUp, signOut, getSession components

### SignIn

```vue
<script lang="ts" setup>

const { signIn } = useAuth() // uses the default signIn function provided by nuxt-auth
const formData = reactive({
  email: '',
  password: '',
})


const login = async (e) => {
    try {
      e.preventDefault()
      let res = await signIn(
        { ...formData },
        { callbackUrl: '/home' } // Where the user will be redirected after a successiful login
      )

      console.log("res", res);

    } catch (error) {
      console.log("error", error);
    } 
}

definePageMeta({
  title: 'Signin',
  layout: 'empty',
  public: true,
  auth: {
    unauthenticatedOnly: true,
    navigateAuthenticatedTo: '/',
  },
})


</script>

<template>
  <div>
    <div class="custom-bg mb-14 p-14 text-center text-white">
      <h1>Sigin</h1>
    </div>
    <form @submit.prevent="login" class="card custom-card mx-auto w-11/12 max-w-md bg-white p-6 shadow-lg">
      <input type="email" v-model="formData.email" name="email" placeholder="email here.." />
      <input type="password" v-model="formData.password" name="password" />
      <button type="submit">Sign In</button>
    </form>
  </div>
</template>
```

### SignUp
You can implement the signup. Its way similar to signIn. It can even be a fetch or [axios](https://axios-http.com/docs/intro) request.

### SignOut

```vue
<script lang="ts" setup> const { signOut, token} = useAuth()
async function _signOut() {
  try {
    await signOut({
      callbackUrl: '/account/signin/',
      redirect: true
    })
   // Add after logout logic here, could be removing the session data from localstorage or whatever
  } catch (error: any) {
    toast.add({ severity: 'error', summary: 'error', detail: error?.data?.message || error?.message, life: 5000 });
  }
}
</script>
<template>
<button @click="_signOut()">
   Sign Out
</button>

</template>
```

### getSession

Add a home page. This will be protected by default by the **globalAppMiddleware**.

```vue
<script lang="ts" setup>

definePageMeta({
  title: 'Home',
  layout: 'home',
  public: true
})

const { data, status, getSession } = useAuth()

// data - authenticated user data returned from getSession option that we setup on nuxt.config.ts
// status - unauthenticated | authenticated
// getSession - call this function asynchronusly to get the session data. i.e. The authenticated user data

</script>

<template>
  <div class="flex flex-col items-start justify-center p-5 sm:p-14">
    <h1 class="text-white text-2xl md:text-4xl  mb-5">
      Hello, 
      <span v-if="status === 'authenticated'">{{ data?.first_name + ' ' + data?.last_name }}</span>
    </h1>
    <p class="text-white opacity-60">Welcome back</p>
	<Logout></Logout>
  </div>
</template>
```

## How to run the project

Add a `.env` file at the root of your project and add this config file:

```env
NUXT_PUBLIC_API_URL=<your-api-endpoint>
```

Start a dev server by running this command in terminal at the root of your project:
`npm run dev`

The project should now be accessible at:
`http://localhost:3000`

## Findings

If you navigate to `/home` you will be redirected to `/signin` since the route is protected.

Navigating to `/` works when authenticated or unauthenticated

Navigating to `/sigin` while authenticated should redirect you to `/home`

Clicking `Logout` button while at `/home` should log you out, and redirect you to `/signin`

## Conclusion

If you have followed these steps, you should have a working nuxt-auth implementation! You can find the complete project on [Github](https://github.com/geraldmuvengei06/nuxt-3-auth-credentials).