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
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
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'],
})
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
}
}
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,
})
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
},
})
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:
{
accessToken: 'Bearer <token>',
status: 'success'
}
Then the token option should look like this:
token: {
signInResponseTokenPointer: '/accessToken'
}
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>
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>
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>
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>
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)
Thank you so much for your time.
This Article is clear enough and helped me to use auth module.
You're welcome!
this code help me and I like this
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."
Just read this 😂😂
Thank you!
and to implement authentication with Google instead of local, but in the same code pattern
I will to a complete Nuxt auth series. We can build a simple project while at it.
Nice suggestion. I'll write one for third party authentication
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?
I'm working on an all round nuxt app with all the auth cases