From volverjs-auth-vue
Integrates OAuth2/OpenID Connect authentication into Vue 3 apps using @volverjs/auth-vue. Handles login/logout, authorization-code + PKCE flow, token refresh, route guards, and reactive auth state.
How this skill is triggered — by the user, by Claude, or both
Slash command
/volverjs-auth-vue:volverjs-auth-vueThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`@volverjs/auth-vue` is a thin, reactive Vue 3 wrapper around [oauth4webapi](https://github.com/panva/oauth4webapi) for the **OAuth 2.0 Authorization Code flow with PKCE** (and OpenID Connect). It runs **in the browser only** and gives you reactive `loggedIn` / `accessToken` state, automatic token persistence, refresh, and logout.
@volverjs/auth-vue is a thin, reactive Vue 3 wrapper around oauth4webapi for the OAuth 2.0 Authorization Code flow with PKCE (and OpenID Connect). It runs in the browser only and gives you reactive loggedIn / accessToken state, automatic token persistence, refresh, and logout.
Use this skill to wire it into a consuming Vue app. It does not require running this repo — it's reference for integrating the published package.
pnpm add @volverjs/auth-vue # peer dependency: vue ^3.5
initialize() is the entry point you call on app start. After OAuth-server discovery it automatically:
?code=... is present in the URL (returning from the IdP),authorize() sends the user to the IdP to log in. logout() sends them to the IdP to log out.state/nonce are persisted to localStorage by default (scoped under an oauth. key prefix).main.ts:
import { createOAuthClient } from '@volverjs/auth-vue'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
const auth = createOAuthClient({
url: 'https://my-idp.example.com', // OAuth issuer (must expose /.well-known/openid-configuration)
clientId: 'my-spa-client-id',
scopes: 'openid profile email offline_access', // offline_access → get a refresh token
redirectUri: `${location.origin}/callback`, // must be registered at the IdP
postLogoutRedirectUri: location.origin,
})
// Discovery + auto-complete login if returning from the IdP, before mount.
await auth.initialize()
app.use(auth, { global: true }) // { global: true } also exposes this.$vvAuth in Options API
app.mount('#app')
Then in any component get the client with the composable:
<script setup lang="ts">
import { useOAuthClient } from '@volverjs/auth-vue'
const auth = useOAuthClient() // must be called inside setup()
// auth.loggedIn → ComputedRef<boolean>
// auth.accessToken → readonly Ref<string | undefined>
</script>
<template>
<button v-if="!auth.loggedIn.value" @click="auth.authorize()">Login</button>
<button v-else @click="auth.logout()">Logout</button>
</template>
import { OAuthClient } from '@volverjs/auth-vue'
export const auth = new OAuthClient({
url: 'https://my-idp.example.com',
clientId: 'my-spa-client-id',
scopes: ['openid', 'profile'],
})
await auth.initialize()
// import { auth } wherever you need it; loggedIn/accessToken are reactive.
auth.authorize() → browser redirects to the IdP (with PKCE code_challenge, state, and nonce when openid is requested).redirectUri with ?code=...&state=....auth.initialize() sees the code and completes the exchange automatically — loggedIn flips to true and accessToken is populated.If you handle the callback on a dedicated route and want to do it explicitly:
import { useOAuthClient } from '@volverjs/auth-vue'
const auth = useOAuthClient()
await auth.initialize() // discovery
await auth.handleCodeResponse(new URLSearchParams(location.search))
// then router.replace('/') to drop the ?code=... from the URL
Core members used above: await initialize() (discovery + auto login/refresh), await authorize(), await handleCodeResponse(params), await refreshToken(), logout(hint?), plus reactive loggedIn / accessToken and the initialized flag. useOAuthClient(options?) returns the installed client inside setup().
For the full option table, method signatures and the confidential-client auth helpers, read references/api.md.
Attach the access token to API requests (reactive — re-reads the current token):
import { useOAuthClient } from '@volverjs/auth-vue'
export function useApi() {
const auth = useOAuthClient()
return (input: RequestInfo, init: RequestInit = {}) =>
fetch(input, {
...init,
headers: {
...init.headers,
...(auth.accessToken.value
? { Authorization: `Bearer ${auth.accessToken.value}` }
: {}),
},
})
}
Vue Router guard — require login, kicking off authorize() when needed:
router.beforeEach((to) => {
const auth = /* your singleton or app-level client */
if (to.meta.requiresAuth && !auth.loggedIn.value) {
auth.authorize() // redirects to the IdP
return false
}
})
For a browser SPA, leave clientAuthentication unset (the default is a public client) and rely on PKCE — never ship a client secret to the browser. Confidential clients with a secret set clientAuthentication with a helper; see references/api.md.
localStorage, which survives restarts and is readable by any JS on the origin (a single XSS exposes the refresh token). Prefer storageType: 'session' when you don't need persistent, cross-tab sessions, or pass a custom storage.S256) and a random state (CSRF protection) are always used; a nonce (OIDC replay protection) is added and validated only when the openid scope is requested.oauth.), so multiple instances don't collide.document/window/Web Storage. Construction is SSR-safe, but call initialize()/authorize() on the client (e.g. onMounted, a client-only plugin, or guarded by import.meta.client).offline_access scope (or the IdP's equivalent) — otherwise initialize() can't restore a session after reload and the user must log in again.openid requires an id_token: when the openid scope is set, the token response must include a (signed) id_token or the exchange fails. Standard IdPs do this; bare OAuth2 servers may not — drop openid for pure OAuth2.redirectUri mismatch is the most common setup error: it must exactly match what's registered at the IdP.?code=...&state=... stays in the address bar after initialize() completes the exchange; router.replace(location.pathname) to remove it.<script> use auth.loggedIn.value / auth.accessToken.value; in <template> they auto-unwrap.Upgrading an existing integration? The breaking change is tokenEndpointAuthMethod (a string) → clientAuthentication (a helper). Full mapping and other changes (oauth4webapi 3.x, Node ≥ 20, state/nonce) in references/migration.md.
npx claudepluginhub volverjs/auth-vue --plugin volverjs-auth-vueAdds Auth0 authentication (login, logout, user sessions, protected routes) to Vue.js 3 SPAs using @auth0/auth0-vue SDK with Vite or Vue CLI.
Vue 3 patterns with Clerk authentication: composables (useAuth, useUser, useClerk, useOrganization), Vue Router guards, and Pinia auth store integration. For plain Vue (not Nuxt).
Provides OAuth 2.0 and OpenID Connect implementation patterns including authorization code flow, PKCE, token management, security best practices, and checklists for auth with Google, GitHub providers.