The `@authdog/nuxt` SDK adds browser authentication state to Nuxt through a Vue plugin and composables, plus Nitro helpers for reading and clearing the `authdog-session` cookie.

`@authdog/nuxt` is not yet published to npm (`npm view @authdog/nuxt` returns 404 at the time of writing). Version `0.1.0` is set to publish publicly from the `web-sdk` repository, so install it from there until it lands on the registry.

## Install

```package-install
@authdog/nuxt
```

Requires Vue `^3.5` (provided by Nuxt). The package ships two entry points: `@authdog/nuxt` (plugin and composables) and `@authdog/nuxt/server` (Nitro helpers). Expose your environment's public key (`pk_...`) through Nuxt runtime config, for example as `runtimeConfig.public.authdogPublicKey`.

## Register the plugin

`createAuthdog` validates the public key once and throws on startup if it is missing, malformed, or points at an untrusted identity host:

```ts
// plugins/authdog.ts
import { createAuthdog } from "@authdog/nuxt"

export default defineNuxtPlugin((nuxtApp) => {
  const config = useRuntimeConfig()
  nuxtApp.vueApp.use(
    createAuthdog({ publicKey: config.public.authdogPublicKey as string }),
  )
})
```

On the client the plugin accepts a `?token=` only when it has three JWT-shaped segments, stores it in `localStorage`, strips it from the URL, and reloads once. A value that is not JWT-shaped is stripped and discarded. This check is not signature, issuer, audience, or expiry validation. Otherwise the plugin hydrates the token from `localStorage`.

## Composables

Each composable throws if the plugin is not installed.

| Composable | Returns |
| --- | --- |
| `useSession()` | `{ session, isLoading }`, where `session` is `{ token, isAuthenticated }` |
| `useUser()` | `{ user, isLoading, error, isAuthenticated, load }` |
| `useSignIn()` | `{ signIn(redirectUri?) }` |
| `useSignUp()` | `{ signUp(redirectUri?) }` |
| `useSignOut()` | `{ signOut(redirectTo?) }` |

`load()` calls the OIDC `userinfo` endpoint with the stored token and never throws. It resolves to `null` and sets `error` on failure. `signIn` and `signUp` redirect the browser to the OIDC `authorize` flow (sign-up adds `prompt=signup`); `redirectUri` defaults to `window.location.origin`. The public key comes from the plugin, so you do not pass it.

```vue
<script setup lang="ts">
import { useSession, useUser, useSignIn, useSignOut } from "@authdog/nuxt"

const { session, isLoading } = useSession()
const { user, load } = useUser()
const { signIn } = useSignIn()
const { signOut } = useSignOut()
</script>

<template>
  <button v-if="!session.isAuthenticated" @click="signIn()">Sign in</button>
  <template v-else>
    <button @click="load()">Load profile</button>
    <button @click="signOut('/')">Sign out</button>
    <pre>{{ user }}</pre>
  </template>
</template>
```

## Server helpers

Import from `@authdog/nuxt/server` in Nitro routes:

```ts
// server/api/me.ts
import { getServerSession } from "@authdog/nuxt/server"

export default defineEventHandler((event) => {
  const token = getServerSession(event)
  return { authenticated: !!token }
})
```

- `getServerSession(event)` accepts an H3 event or a Web `Request` and returns the raw `authdog-session` cookie value, or `null`. It performs no validation.
- `logoutResponse(request)` returns a `302` that clears the `authdog-session` cookie and redirects to the sanitized `redirect_uri` query parameter, defaulting to `/`. `Secure` is added only when `NODE_ENV` is `production`.
- `getServerSidePayloadPublicKey(publicKey)` returns the validated public-key payload as a JSON string.

## Sign out

`useSignOut().signOut()` clears only the browser token in `localStorage`, and navigates to `redirectTo` if given. To clear the server cookie, route the user through a handler that returns `logoutResponse(request)`.

## Caveats

- The plugin does not set the `authdog-session` cookie, and no cookie callback exchange is included. For server-side authentication, set an HttpOnly cookie after validating the token with a [backend SDK](/docs/backend).
- `session.isAuthenticated` reflects token presence only. Treat composable state and `getServerSession()` as untrusted input, and enforce [authorization](/docs/concepts/authorization) in server routes.

## Next steps

- [Sign up & sign in](/docs/authentication): the flows the plugin drives.
- [Backend requests](/docs/backend): validate sessions on your API.
