Nuxt

Talon Auth integrates with Nuxt using a shared client plugin, a server plugin for SSR, and the <talon-login> web component for the login UI. The access token is automatically stored in a same-site cookie so server-side rendering always has access to it.

Setup

Install the package:

npm install talon-auth

Add your app ID, API URL, and cookie name to nuxt.config.ts:

export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      talon: {
        appId: process.env.TALON_APP_ID,
        apiUrl: 'https://api.talon.codes',
        cookie: 'talon-auth',
      },
    },
  },
  vue: {
    compilerOptions: {
      isCustomElement: (tag) => tag === 'talon-login',
    },
  },
})

Client plugin

Create plugins/talon.client.ts to instantiate the shared auth client and provide it to the app. The cookie option makes the client automatically store the access token in a same-site cookie after every token fetch, and clear it on logout.

// plugins/talon.client.ts
import { createClient } from 'talon-auth'

export default defineNuxtPlugin(() => {
  const { appId, apiUrl, cookie } = useRuntimeConfig().public.talon

  return {
    provide: {
      talonClient: createClient({ appId, api: apiUrl, cookie }),
    },
  }
})

Server plugin

Create plugins/talon.server.ts to verify the cookie on each SSR request and populate the user state before the page renders:

// plugins/talon.server.ts
import { createVerifier } from 'talon-auth'

export default defineNuxtPlugin(async () => {
  const { appId, cookie: cookieName } = useRuntimeConfig().public.talon
  const token = useCookie(cookieName).value
  if (!token) return
  try {
    const { user } = await createVerifier({ appId }).verify(token)
    useState('talon-user').value = user
  } catch {}
})

Composables

Add composables for user state and token access. getTalonAuthToken reads from the cookie on the server and calls getAccessToken() on the client, which handles token refresh and keeps the cookie up to date:

// composables/use-talon.ts
import type { TalonAuthUser } from 'talon-auth'

export const useTalonUser = () =>
  readonly(useState<TalonAuthUser | null>('talon-user', () => null))

export const useTalonClient = () => useNuxtApp().$talonClient

export function getTalonAuthToken() {
  if (import.meta.server) {
    const cookieName = useRuntimeConfig().public.talon.cookie
    return useCookie<string | null>(cookieName).value ?? null
  }
  return useTalonClient().getAccessToken()
}

Login UI

Import the web component client-side only and pass the shared client via :authClient (camelCase is required — Vue must set this as a DOM property, not an HTML attribute):

<script setup lang="ts">
if (import.meta.client) {
  await import('talon-auth/login')
}

const user = useTalonUser()

async function onLogin() {
  const userState = useState('talon-user')
  try {
    userState.value = await useTalonClient().getUser()
  } catch {
    userState.value = null
  }
}
</script>

<template>
  <ClientOnly>
    <talon-login :authClient="$talonClient" @login="onLogin" />
  </ClientOnly>

  <p v-if="user">Hello, {{ user.email }}</p>
</template>

Logout

Call logout() on the shared client to clear the IndexedDB token and the cookie, then clear the user state:

await useTalonClient().logout()
useState('talon-user').value = null
navigateTo('/')

Making authenticated API requests

Use getTalonAuthToken() in any function that needs to attach a Bearer token to outgoing requests. It works on both the server (reads the cookie) and the client (calls getAccessToken()):

const token = await getTalonAuthToken()
const data = await $fetch('/api/protected', {
  headers: token ? { Authorization: `Bearer ${token}` } : {},
})
Subscribe to our NewsletterGet new Feathers content as it becomes available.
Talon Auth logo

Copyright © 2012 - 2026 feathers.dev