Reputation: 73
I am trying to add auth0 to my nuxt3 application, but I am having trouble how to approach it. The auth-nuxt module is still not available for nuxt3 and the auth0-spa-js cannot make it work with SSR, I followed this tutorial.
import createAuth0Client from "@auth0/auth0-spa-js";
let auth = await createAuth0Client({
domain: "dev-......com",
client_id: "Z0...................0T6I",
redirect_uri: '<MY_CALLBACK_URL>'
});
export default auth;
import auth from "../store/authfile";
export default defineNuxtRouteMiddleware(async (to, from) => {
let isAuthenticated = await auth.isAuthenticated();
if (to.path === "/" && !to?.query?.code) {
return;
}
if (!isAuthenticated) {
const query = to?.query;
if (query && query.code && query.state) {
await auth.handleRedirectCallback();
} else {
await auth.loginWithRedirect();
}
} else {
console.log("logged in ", to.path);
}
const router = useRouter();
if (to.path === "/") {
to.fullPath = "/";
}
navigateTo(to.path);
});
500 document is not defined
at getAll (C:\Users\vesel\Desktop\nuxt-app\node_modules\es-cookie\src\es-cookie.js:68:18) at Object.get (C:\Users\vesel\Desktop\nuxt-app\node_modules\es-cookie\src\es-cookie.js:72:12) at Object.get (C:\Users\vesel\Desktop\nuxt-app\node_modules@auth0\auth0-spa-js\dist\lib\auth0-spa-js.cjs.js:4550:40) at Object.get (C:\Users\vesel\Desktop\nuxt-app\node_modules@auth0\auth0-spa-js\dist\lib\auth0-spa-js.cjs.js:4585:35) at Auth0Client. (C:\Users\vesel\Desktop\nuxt-app\node_modules@auth0\auth0-spa-js\dist\lib\auth0-spa-js.cjs.js:5258:45) at step (C:\Users\vesel\Desktop\nuxt-app\node_modules@auth0\auth0-spa-js\dist\lib\auth0-spa-js.cjs.js:186:23) at Object.next (C:\Users\vesel\Desktop\nuxt-app\node_modules@auth0\auth0-spa-js\dist\lib\auth0-spa-js.cjs.js:130:20) at C:\Users\vesel\Desktop\nuxt-app\node_modules@auth0\auth0-spa-js\dist\lib\auth0-spa-js.cjs.js:107:71 at new Promise () at __awaiter (C:\Users\vesel\Desktop\nuxt-app\node_modules@auth0\auth0-spa-js\dist\lib\auth0-spa-js.cjs.js:89:12)`
Upvotes: 3
Views: 5174
Reputation: 149
I went with using this module: nuxt-oidc-auth
I had some issues with opaque tokens being returned but I solved it by setting a default audience in my Auth0 settings:
Check out a working example here nuxt3-auth0
Upvotes: 0
Reputation: 428
After spending few hours trying to upgrade my small project from nuxt 2 to nuxt 3 I was very disappointed that the old auth-next
plugin was not working yet(anymore).
I tried to integrate @auth0/auth0-vue
as Dylan above was suggesting, but I had few issues with session storage.
Then I discovered @supabase/nuxt-auth
which is a nuxt3 wrapper for NextAuthJs that works out "of the box" with minimal configuration and supports many other providers as well.
It works on client and server sides.
On the server side I had configured it like this - server/api/auth/[...].ts
file:
import { NuxtAuthHandler } from '#auth'
import Auth0Provider from 'next-auth/providers/auth0'
export default NuxtAuthHandler({
secret: useRuntimeConfig().authSecret,
providers: [
// @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point
Auth0Provider.default({
clientId: useRuntimeConfig().auth0.clientId,
clientSecret: useRuntimeConfig().auth0.clientSecret,
issuer: useRuntimeConfig().auth0.issuer,
})
]
})
And login page would look like:
<template>
<div>
<a v-if="!isAuthenticated" @click="login">
<slot>Log In</slot>
</a>
<a v-else @click="logout">
<slot>
Log Out {{ user }}
</slot>
</a>
</div>
</template>
<script lang="ts" setup>
const ses = useSession({ required: false })
const login = () => ses.signIn('auth0')
const logout = () => ses.signOut('auth0')
const isAuthenticated = computed(() => {
return ses.status.value === 'authenticated'
})
const user = computed(() => {
return ses.data.value?.user?.name
})
</script>
The only difference here is that to configure Auth0Provider
one would need both clientId
and clientSecret
and it requires server-side, which might not be suitable for SPA or client-only pages.
Upd: regarding server-side session, there is one special case with universal rendering where headers needs to be passed additionally to have session on the first load:
const headers = useRequestHeaders(['cookie']) as HeadersInit
const { pending, data } = useLazyFetch(`${config.public.apiUrl}/data`, { headers })
Upvotes: 1
Reputation: 106
Auth0 has a Vue3 package that can be configured as a Nuxt3 plugin.
First, follow only the configuration steps and installation steps outlined in their quickstart.
Next, add it as a Nuxt3 plugin, create a new file named auth.ts in the Plugin folder with the following code. Here we instantiate the auth0 as a plugin and add an 'auth' middleware that re-routes authenticated pages. Remember to add the middleware to pages that require them using definePageMeta:
import { createAuth0 } from '@auth0/auth0-vue'
export default defineNuxtPlugin((nuxtApp) => {
const auth0 = createAuth0({
domain: 'xxxx.auth0.com',
client_id: 'xxx',
redirect_uri: 'http://localhost:3000',
})
if (process.client) {
nuxtApp.vueApp.use(auth0)
}
addRouteMiddleware('auth', () => {
if (process.client) {
auth0.checkSession()
if (!auth0.isAuthenticated.value) {
auth0.loginWithRedirect({
appState: {
target: useRoute().path,
},
})
}
}
})
})
Now we can create a login button Vue component (Login.vue) that references this plugin. Note, the Login button can only perform auth0 functionality on the client, thus our default is Log In and will refreshes when the isAuthenticated data gets updated.
<template>
<div>
<a
v-if="!isAuthenticated"
@click="login"
>
<slot>Log In</slot>
</a>
<a
v-else
@click="logout"
>
<slot>Log Out</slot>
</a>
</div>
</template>
<script lang="ts" setup>
import { useAuth0 } from '@auth0/auth0-vue'
// Composition API
const auth0 = process.client ? useAuth0() : undefined
const isAuthenticated = computed(() => {
return auth0?.isAuthenticated.value
})
const login = () => {
auth0?.checkSession()
if (!auth0?.isAuthenticated.value) {
auth0?.loginWithRedirect({
appState: {
target: useRoute().path,
},
})
}
}
const logout = () => {
navigateTo('/')
auth0?.logout()
}
</script>
More functionality for this package can be found at the Github Repo.
Side note: This middleware only runs on the client side, thus you should assert that all pages do not return sensitive information by default. Auth0 describes NextJS serverless architecture authentication here.
Upvotes: 9