Skip to content

Commit 1d07784

Browse files
committed
add sanctum token auth
1 parent d71ebc1 commit 1d07784

File tree

3 files changed

+90
-16
lines changed

3 files changed

+90
-16
lines changed

src/runtime/plugin.client.ts

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,34 @@ function createFetchClient(
3535
retry: false,
3636

3737
async onRequest(context) {
38-
let csrfToken = readCsrfCookie(authentication.csrfCookie)
39-
40-
if (!csrfToken.value) {
41-
await $fetch(authentication.csrfEndpoint, {
42-
baseURL: authentication.baseUrl,
43-
credentials: 'include',
44-
retry: false,
45-
})
46-
47-
csrfToken = readCsrfCookie(authentication.csrfCookie)
38+
// todo: move this to interceptors
39+
if (authentication.mode === 'token') {
40+
let csrfToken = readCsrfCookie(authentication.csrfCookie)
41+
42+
if (!csrfToken.value) {
43+
await $fetch(authentication.csrfEndpoint, {
44+
baseURL: authentication.baseUrl,
45+
credentials: 'include',
46+
retry: false,
47+
})
48+
49+
csrfToken = readCsrfCookie(authentication.csrfCookie)
50+
}
51+
52+
if (!csrfToken.value) {
53+
logger.warn(`${authentication.csrfCookie} cookie is missing, unable to set ${authentication.csrfHeader} header`)
54+
return
55+
}
56+
57+
context.options.headers.set(authentication.csrfHeader, csrfToken.value)
4858
}
4959

50-
if (!csrfToken.value) {
51-
logger.warn(`${authentication.csrfCookie} cookie is missing, unable to set ${authentication.csrfHeader} header`)
52-
return
60+
// todo: move this to interceptors
61+
if (authentication.mode === 'token') {
62+
const { tokenStorage } = useAppConfig().echo.authentication
63+
const token = await tokenStorage.get()
64+
context.options.headers.set('Authorization', 'Bearer ' + token)
5365
}
54-
55-
context.options.headers.set(authentication.csrfHeader, csrfToken.value)
5666
},
5767
}
5868

@@ -127,10 +137,33 @@ function prepareEchoOptions(config: ModuleOptions, logger: ConsolaInstance) {
127137
}
128138
}
129139

130-
export default defineNuxtPlugin((_nuxtApp) => {
140+
async function setupDefaultTokenStorage(nuxtApp: NuxtApp, logger: ConsolaInstance) {
141+
logger.debug(
142+
'Token storage is not defined, switch to default cookie storage',
143+
)
144+
145+
const defaultStorage = await import('./storages/cookieTokenStorage')
146+
147+
nuxtApp.runWithContext(() => {
148+
updateAppConfig({
149+
echo: {
150+
authentication: {
151+
tokenStorage: defaultStorage.cookieTokenStorage,
152+
}
153+
},
154+
})
155+
})
156+
}
157+
158+
export default defineNuxtPlugin(async (_nuxtApp) => {
131159
const config = useEchoConfig()
160+
const appConfig = useAppConfig()
132161
const logger = createEchoLogger(config.logLevel)
133162

163+
if (config.authentication?.mode === 'token' && !appConfig.echo?.authentication?.tokenStorage) {
164+
await setupDefaultTokenStorage(_nuxtApp, logger)
165+
}
166+
134167
window.Pusher = Pusher
135168
window.Echo = new Echo(prepareEchoOptions(config, logger))
136169

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { unref } from 'vue'
2+
import type { TokenStorage } from '~/src/runtime/types'
3+
import { useCookie, type NuxtApp } from '#app'
4+
5+
const cookieTokenKey = 'sanctum.token.cookie'
6+
7+
/**
8+
* Token storage using a secure cookie.
9+
* Works with both CSR/SSR modes.
10+
*/
11+
export const cookieTokenStorage: TokenStorage = {
12+
async get(app: NuxtApp) {
13+
return app.runWithContext(() => {
14+
const cookie = useCookie(cookieTokenKey, { readonly: true })
15+
return unref(cookie.value) ?? undefined
16+
})
17+
},
18+
19+
async set(app: NuxtApp, token?: string) {
20+
await app.runWithContext(() => {
21+
const cookie = useCookie(cookieTokenKey, { secure: true })
22+
cookie.value = token
23+
})
24+
},
25+
}

src/runtime/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
export interface Authentication {
2+
/**
3+
* Authentication mode 'cookie' or 'token'
4+
* @default 'cookie'
5+
*/
6+
mode: 'cookie' | 'token'
27
/**
38
* The base URL of Laravel application.
49
* @default 'http://localhost:80'
@@ -86,3 +91,14 @@ export interface ModuleOptions {
8691
*/
8792
properties?: object
8893
}
94+
95+
export interface TokenStorage {
96+
/**
97+
* Function to load a token from the storage.
98+
*/
99+
get: (app: NuxtApp) => Promise<string | undefined>
100+
/**
101+
* Function to save a token to the storage.
102+
*/
103+
set: (app: NuxtApp, token?: string) => Promise<void>
104+
}

0 commit comments

Comments
 (0)