Sign In

@authon/nuxt

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@authon/nuxt

Authon Nuxt 3 module — auto-imported composables and middleware

Source
npmnpm
Version
0.3.0
Version published
Weekly downloads
29
-19.44%
Maintainers
1
Weekly downloads
 
Created
Source

English | 한국어

@authon/nuxt

Nuxt 3 integration for Authon — client plugin, composables, route middleware, and social buttons.

Install

npm install @authon/nuxt @authon/js

Requires nuxt >= 3.0.0.

Setup

1. Create the Authon plugin

Create plugins/authon.client.ts — the .client suffix ensures it only runs in the browser:

// plugins/authon.client.ts
import { createAuthonPlugin } from '@authon/nuxt'

export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig()
  const authon = createAuthonPlugin(config.public.authonKey, {
    theme: 'auto',
    locale: 'en',
  })
  return { provide: { authon } }
})

2. Expose the key via runtime config

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      authonKey: process.env.NUXT_PUBLIC_AUTHON_KEY,
    },
  },
})

3. Access auth state in pages

<!-- pages/index.vue -->
<script setup lang="ts">
const { $authon } = useNuxtApp()
const { client, isSignedIn, user } = $authon
</script>

<template>
  <div v-if="isSignedIn">
    <p>Welcome, {{ user?.displayName }}</p>
    <button @click="client.signOut()">Sign out</button>
  </div>
  <div v-else>
    <button @click="client.openSignIn()">Sign in</button>
  </div>
</template>

API Reference

createAuthonPlugin(publishableKey, config?)

Creates the Authon state object for use as a Nuxt plugin. Returns AuthonPluginState:

interface AuthonPluginState {
  client: Authon        // full @authon/js client instance
  user: AuthonUser | null
  isSignedIn: boolean
  isLoading: boolean
}

useAuthon()

Convenience wrapper — in practice, access the client through useNuxtApp().$authon:

const { $authon } = useNuxtApp()
const { client, isSignedIn, user, isLoading } = $authon

useUser()

const { $authon } = useNuxtApp()
const { user, isLoading } = $authon

createAuthMiddleware(authon, redirectTo?)

Factory for creating route middleware that guards authenticated pages.

// middleware/auth.ts
import { createAuthMiddleware } from '@authon/nuxt'

export default defineNuxtRouteMiddleware((to, from) => {
  const { $authon } = useNuxtApp()
  return createAuthMiddleware($authon, '/login')(to, from)
})

Apply it per page:

<!-- pages/dashboard.vue -->
<script setup>
definePageMeta({ middleware: 'auth' })
</script>

The middleware redirects unauthenticated users to redirectTo (default: '/sign-in') and preserves the original URL in ?redirect=.

renderSocialButtons(options)

Renders branded OAuth provider buttons into a container element. Returns a cleanup function.

import type { SocialButtonsConfig } from '@authon/nuxt'

Options:

OptionTypeDefaultDescription
clientAuthonrequiredAuthon client instance
containerHTMLElementrequiredTarget DOM element
onSuccess() => voidCalled after successful OAuth sign-in
onError(error: Error) => voidCalled on OAuth error
compactbooleanfalseIcon-only square buttons in a row
gapnumber10 / 12Gap between buttons in px
labelsRecord<provider, string>Override button labels per provider
borderRadiusnumber10Button border radius in px
heightnumber48Button height in px
sizenumber48Icon button size in px (compact mode)

Examples

Sign-in page with email + OAuth

<!-- pages/login.vue -->
<template>
  <div class="login">
    <div ref="socialContainer" />

    <form @submit.prevent="handleSignIn">
      <input v-model="email" type="email" placeholder="Email" />
      <input v-model="password" type="password" placeholder="Password" />
      <button type="submit" :disabled="loading">Sign in</button>
      <p v-if="error">{{ error }}</p>
    </form>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { renderSocialButtons } from '@authon/nuxt'

const { $authon } = useNuxtApp()
const router = useRouter()

const socialContainer = ref<HTMLElement>()
const email = ref('')
const password = ref('')
const loading = ref(false)
const error = ref('')
let cleanupSocial: (() => void) | undefined

onMounted(() => {
  if (socialContainer.value) {
    cleanupSocial = renderSocialButtons({
      client: $authon.client,
      container: socialContainer.value,
      onSuccess: () => router.push('/dashboard'),
      onError: (e) => { error.value = e.message },
    })
  }
})

onUnmounted(() => cleanupSocial?.())

async function handleSignIn() {
  loading.value = true
  error.value = ''
  try {
    await $authon.client.signInWithEmail(email.value, password.value)
    router.push('/dashboard')
  } catch (e: any) {
    error.value = e.message
  } finally {
    loading.value = false
  }
}
</script>

OAuth sign-in

<script setup lang="ts">
const { $authon } = useNuxtApp()

async function signInWithGoogle() {
  await $authon.client.signInWithOAuth('google')
}
</script>

Protected page with middleware

<!-- pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })

const { $authon } = useNuxtApp()
const { user } = $authon
</script>

<template>
  <h1>Welcome, {{ user?.displayName }}</h1>
</template>

MFA setup

<script setup lang="ts">
import { ref } from 'vue'

const { $authon } = useNuxtApp()
const qrCodeSvg = ref('')
const secret = ref('')
const backupCodes = ref<string[]>([])
const verifyCode = ref('')

async function initMfaSetup() {
  const res = await $authon.client.setupMfa()
  qrCodeSvg.value = res.qrCodeSvg
  secret.value = res.secret
  backupCodes.value = res.backupCodes
}

async function confirmSetup() {
  await $authon.client.verifyMfaSetup(verifyCode.value)
  alert('MFA enabled')
}
</script>

MFA verification on sign-in

<script setup lang="ts">
import { ref } from 'vue'
import { AuthonMfaRequiredError } from '@authon/js'

const { $authon } = useNuxtApp()
const mfaToken = ref('')
const totpCode = ref('')

async function signIn(email: string, password: string) {
  try {
    await $authon.client.signInWithEmail(email, password)
  } catch (e) {
    if (e instanceof AuthonMfaRequiredError) {
      mfaToken.value = e.mfaToken
    }
  }
}

async function verifyMfa() {
  await $authon.client.verifyMfa(mfaToken.value, totpCode.value)
}
</script>
<script setup lang="ts">
import { ref } from 'vue'

const { $authon } = useNuxtApp()
const email = ref('')
const sent = ref(false)

async function sendMagicLink() {
  await $authon.client.sendMagicLink(email.value)
  sent.value = true
}
</script>

Passwordless — email OTP

<script setup lang="ts">
import { ref } from 'vue'

const { $authon } = useNuxtApp()
const email = ref('')
const otp = ref('')
const step = ref<'email' | 'verify'>('email')

async function sendOtp() {
  await $authon.client.sendEmailOtp(email.value)
  step.value = 'verify'
}

async function verifyOtp() {
  const user = await $authon.client.verifyPasswordless({ email: email.value, code: otp.value })
  console.log('Signed in as:', user.email)
}
</script>

Passkeys

<script setup lang="ts">
const { $authon } = useNuxtApp()

// Register (user must be signed in)
async function registerPasskey() {
  const credential = await $authon.client.registerPasskey('My Device')
  console.log('Registered:', credential.id)
}

// Authenticate
async function loginWithPasskey() {
  const user = await $authon.client.authenticateWithPasskey()
  console.log('Signed in as:', user.email)
}
</script>

Web3 wallet authentication

<script setup lang="ts">
const { $authon } = useNuxtApp()

async function signInWithWallet() {
  const address = '0xYourWalletAddress'

  const { nonce, message } = await $authon.client.web3GetNonce(address, 'evm', 'metamask')

  const signature = await window.ethereum.request({
    method: 'personal_sign',
    params: [message, address],
  })

  const user = await $authon.client.web3Verify(message, signature, address, 'evm', 'metamask')
  console.log('Signed in as:', user.email)
}

async function listLinkedWallets() {
  const wallets = await $authon.client.listWallets()
  console.log(wallets)
}
</script>

Profile update

<script setup lang="ts">
const { $authon } = useNuxtApp()

async function saveProfile() {
  const updated = await $authon.client.updateProfile({
    displayName: 'Jane Doe',
    avatarUrl: 'https://example.com/avatar.png',
    phone: '+1234567890',
  })
  console.log('Updated user:', updated)
}
</script>

Session management

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { SessionInfo } from '@authon/shared'

const { $authon } = useNuxtApp()
const sessions = ref<SessionInfo[]>([])

onMounted(async () => {
  sessions.value = await $authon.client.listSessions()
})

async function revokeSession(sessionId: string) {
  await $authon.client.revokeSession(sessionId)
  sessions.value = sessions.value.filter(s => s.id !== sessionId)
}
</script>

Plugin options (AuthonModuleOptions)

OptionTypeDefaultDescription
publishableKeystringrequiredYour Authon publishable key
config.theme'light' | 'dark' | 'auto''auto'UI theme
config.localestring'en'Language code
config.apiUrlstring'https://api.authon.dev'Custom API base URL
config.appearancePartial<BrandingConfig>Override branding colors and logo
globalMiddlewarebooleanfalseEnable global auth middleware for all routes

TypeScript

import type { AuthonPluginState, AuthonModuleOptions, SocialButtonsConfig } from '@authon/nuxt'
import type { AuthonUser, SessionInfo, PasskeyCredential, Web3Wallet } from '@authon/shared'

Documentation

authon.dev/docs

License

MIT

Keywords

authon

FAQs

Package last updated on 09 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts