DEV Community

Cover image for How to setup nuxt-auth v6 authentication with the "credentials" provider on nuxt3 project
Gerald
Gerald

Posted on

How to setup nuxt-auth v6 authentication with the "credentials" provider on nuxt3 project

nuxt-auth is an open source Nuxt module that provides authentication for non-static Nuxt 3 applications. - sidebase
The easiest way to get started with nuxt-auth is using the sidebase Merino stack: - sidebase

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.

npx nuxi@latest init my-app
Enter fullscreen mode Exit fullscreen mode

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

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

// yarn
yarn add @sidebase/nuxt-auth
Enter fullscreen mode Exit fullscreen mode

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:

export default defineNuxtConfig({
   modules: ['@sidebase/nuxt-auth'],
})
Enter fullscreen mode Exit fullscreen mode

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.

/* 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
    }
  }
Enter fullscreen mode Exit fullscreen mode

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:

definePageMeta({
  auth: false,
})
Enter fullscreen mode Exit fullscreen mode

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

definePageMeta({
  auth: {
    unauthenticatedOnly: true,
    navigateAuthenticatedTo: /, // Where the user should be redirected if not logged in
  },
})
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

{
    accessToken: 'Bearer <token>',
    status: 'success'
}
Enter fullscreen mode Exit fullscreen mode

Then the token option should look like this:

token: {
  signInResponseTokenPointer: '/accessToken'
}
Enter fullscreen mode Exit fullscreen mode

To read more about all the possible options checkout the nuxt-auth options documentation.

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

SignIn

<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>
Enter fullscreen mode Exit fullscreen mode

SignUp

You can implement the signup. Its way similar to signIn. It can even be a fetch or axios request.

SignOut

<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>
Enter fullscreen mode Exit fullscreen mode

getSession

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

<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>
Enter fullscreen mode Exit fullscreen mode

How to run the project

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

NUXT_PUBLIC_API_URL=<your-api-endpoint>
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (10)

Collapse
 
oussamalkd profile image
Oussama Louelkadi

Thank you so much for your time.
This Article is clear enough and helped me to use auth module.

Collapse
 
geraldmuvengei06 profile image
Gerald

You're welcome!

Collapse
 
gold_collect_f4ea8cff451d profile image
gold collect

this code help me and I like this

Collapse
 
axon profile image
Jeff Spurlock

Thanks for this. i found it right as i was about to give up because Sidebase and the nuxt-auth documentation is fucking terrible.

'how do you make a cake?'
sidebase: "oh, easy, you just combine the ingredients and bake it at the right temp."
'Uh... OK, mind telling me the ingredients and how long to bake it and at what temp?'
Sidebase: "hahahahaha, no fuck you."

Collapse
 
geraldmuvengei06 profile image
Gerald

Just read this 😂😂

Collapse
 
fabiovaz profile image
Fabio Vaz

Thank you!

and to implement authentication with Google instead of local, but in the same code pattern

Collapse
 
geraldmuvengei06 profile image
Gerald

I will to a complete Nuxt auth series. We can build a simple project while at it.

Collapse
 
geraldmuvengei06 profile image
Gerald

Nice suggestion. I'll write one for third party authentication

Collapse
 
jeppepepp profile image
JeppePepp

What about handling refresh tokens? Also can you show a example of how to in smart way use your cookie/jwt to make calls to a custom backend api?

Collapse
 
geraldmuvengei06 profile image
Gerald

I'm working on an all round nuxt app with all the auth cases