lukk-nuxt
lukk-nuxt
Nuxt module for lukk — first-party Laravel JWT auth for Nuxt, plus the data layer that rides on it: an auth-aware fetch and reactive forms for your own Laravel API. SSR / SPA / SSG, Nuxt 3 and 4, in BFF or direct mode — one composable API either way.
npm i lukk-nuxt
Pre-1.0.
lukk-nuxtis0.x(versioned in lockstep withlukk-core); the public API may change between minor versions per SemVer §4. Pin an exact version and read the UPGRADE guide before upgrading.
Setup
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['lukk-nuxt'],
lukk: {
baseURL: 'https://api.example.com/auth', // your lukk auth routes
mode: 'bff', // 'bff' (default) or 'direct'
user: { endpoint: '/api/me' }, // your app's authenticated user route
},
})
In bff mode also set a session secret (≥ 32 chars):
NUXT_LUKK_SESSION_PASSWORD=change-me-to-a-long-random-string
Modes
| Mode | How | Use for |
|---|---|---|
bff (default) |
A Nitro proxy holds tokens in a sealed cookie; the browser never sees a token. | SSR / served SPA — most secure. |
direct |
The client talks to lukk directly (no proxy). | SSG / static, or a simple SPA. |
mode is a config switch — your app code never changes between them.
Composables (auto-imported)
<script setup lang="ts">
// Auth
const { user, loggedIn, login, logout, pendingTwoFactor, verifyTwoFactor } = useLukkAuth()
const { enable, confirm, disable, recoveryCodeCount } = useLukkTwoFactor()
const { confirmPassword } = useLukkConfirmation()
const { register, login: passkeyLogin, list, remove } = useLukkPasskeys()
// Your own Laravel API
const api = useLukkFetch() // auth-aware fetch
const form = useLukkForm({ email: '', password: '' }) // reactive form + 422 binding
</script>
Auth
useLukkAuth— password + 2FA login, logout, session restore,revokeOtherSessions, the reactiveuser.useLukkTwoFactor— enrol / confirm / disable / recovery-code count (behind step-up).useLukkConfirmation— earn a step-up confirmation token (auto-attached to gated requests).useLukkPasskeys— register / passwordless login / step-up confirm / list / remove.
Your Laravel API
useLukkFetch— a typed, transport-aware fetch for your own app API: forwards the session cookie on SSR (a bare$fetchdoesn't → silent 401), attaches the bearer in direct mode with single-flight 401 refresh, and rejects with a typedLukkError.useLukkForm— a reactive form (Inertia-useForm-style) overuseLukkFetch: holdsdata, submits it (post/put/patch/delete/get), and binds a Laravel422bag to per-fielderrors— withprocessing/wasSuccessful/recentlySuccessful/isDirty,onSuccess/onError/onFinishhooks, chainablereset/defaults/transform, automaticmultipart/form-dataforFile/Blobfields, andcancel().
Guard pages with the route middleware — lukk-auth (require login) or
lukk-guest (bounce already-authenticated users, e.g. off /login):
<script setup lang="ts">
definePageMeta({ middleware: 'lukk-auth' })
</script>
BFF: authenticating your own API
In bff mode the browser holds no token, so your own API (and user.endpoint) must
be authenticated server-side. Proxy it through lukk-nuxt:
lukk: { mode: 'bff', api: { path: '/api', target: 'https://api.example.com' } }
Now call it with useLukkFetch() — it forwards the session cookie on SSR (a bare
$fetch doesn't, so it 401s server-side), sends Accept: application/json, and rejects
with a typed LukkError:
const api = useLukkFetch()
const { data } = await useAsyncData('me', () => api('/me')) // SSR-authenticated
Or read the token yourself in a Nitro route via getLukkAccessToken(event). Full guide:
Authenticating your own API.
Security
No token in the browser (BFF), a __Host--prefixed sealed session, origin-scoped
credentials, and CSRF + SSRF guards on both proxies. See the
Architecture & security model.
[!NOTE] Stateless-API consumers: make your Laravel app return JSON
401s forapi/*(the client sendsAccept: application/json; also configure exception rendering for those paths). Otherwise Laravel's defaultunauthenticated()redirects to aloginroute and the proxy surfaces a confusing 500. App-side, not a lukk bug.
Options
| Key | Default | Description |
|---|---|---|
baseURL |
'' |
Your lukk auth URL incl. the route prefix. |
mode |
'bff' |
'bff' or 'direct'. |
user.endpoint |
'' |
Authenticated user route. bff: a same-origin proxied path; direct: URL/path with the bearer attached. |
api.path / api.target |
'' |
BFF-only: proxy ${path}/** → fixed target, injecting the bearer server-side. |
api.forceJson |
true |
Force Accept: application/json on proxied requests → clean JSON 401/422 from Laravel. |
confirmationHeader |
'X-Lukk-Confirmation' |
Header carrying the step-up token. |
session.password |
env NUXT_LUKK_SESSION_PASSWORD |
BFF sealed-session secret (≥ 32 chars). |
Documentation
Full guides — installation, configuration, both transport modes, forms, 2FA, passkeys, and step-up confirmation — live in the lukk docs.
License
MIT
Related Packages
Reusable Nuxt authentication module for bearer-token APIs with Redis sessions an...
The Nuxt module for Idenzy: the Vue bindings, plus a server render seeded from t...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.12.0 | ^3.0 | MIT | |
| 0.11.0 | ^3.0 | MIT | |
| 0.10.1 | ^3.0 | MIT | |
| 0.10.0 | ^3.0 | MIT | |
| 0.9.0 | ^3.0 | MIT | |
| 0.8.0 | ^3.0 | MIT | |
| 0.7.1 | ^3.0 | MIT | |
| 0.7.0 | ^3.0 | MIT | |
| 0.6.0 | ^3.0 | MIT | |
| 0.5.0 | ^3.0 | MIT | |
| 0.4.0 | ^3.0 | MIT | |
| 0.3.0 | ^3.0 | MIT | |
| 0.2.1 | ^3.0 | MIT | |
| 0.2.0 | ^3.0 | MIT | |
| 0.1.0 | ^3.0 | MIT |