Skip to content

Commit

Permalink
feat: local with cookie session
Browse files Browse the repository at this point in the history
  • Loading branch information
benjipott committed Nov 13, 2023
1 parent 24c31b8 commit 36e55ce
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 20 deletions.
11 changes: 6 additions & 5 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { defineNuxtModule, useLogger, createResolver, addTemplate, addPlugin, addServerPlugin, addImports, addRouteMiddleware } from '@nuxt/kit'
import { addImports, addPlugin, addRouteMiddleware, addServerPlugin, addTemplate, createResolver, defineNuxtModule, useLogger } from '@nuxt/kit'
import { defu } from 'defu'
import { joinURL } from 'ufo'
import { genInterface } from 'knitwork'
import type { DeepRequired } from 'ts-essentials'
import { joinURL } from 'ufo'
import { getOriginAndPathnameFromURL, isProduction } from './runtime/helpers'
import type { ModuleOptions, SupportedAuthProviders, AuthProviders } from './runtime/types'
import type { AuthProviders, ModuleOptions, SupportedAuthProviders } from './runtime/types'

const topLevelDefaults = {
isEnabled: true,
Expand Down Expand Up @@ -35,8 +35,9 @@ const defaultsByBackend: { [key in SupportedAuthProviders]: DeepRequired<Extract
signInResponseTokenPointer: '/token',
type: 'Bearer',
headerName: 'Authorization',
maxAgeInSeconds: 30 * 60,
sameSiteAttribute: 'lax'
maxAgeInSeconds: undefined,

Check failure on line 38 in src/module.ts

View workflow job for this annotation

GitHub Actions / test-module

Type 'undefined' is not assignable to type 'number'.
sameSiteAttribute: 'lax',
name: 'auth:token'
},
sessionDataType: { id: 'string | number' }
},
Expand Down
12 changes: 6 additions & 6 deletions src/runtime/composables/local/useAuth.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { readonly, Ref } from 'vue'
import { callWithNuxt } from '#app'
import { CommonUseAuthReturn, SignOutFunc, SignInFunc, GetSessionFunc, SecondarySignInOptions } from '../../types'
import { _fetch } from '../../utils/fetch'
import { readonly, Ref } from 'vue'
import { jsonPointerGet, useTypedBackendConfig } from '../../helpers'
import { CommonUseAuthReturn, GetSessionFunc, SecondarySignInOptions, SignInFunc, SignOutFunc } from '../../types'
import { getRequestURLWN } from '../../utils/callWithNuxt'
import { _fetch } from '../../utils/fetch'
import { useAuthState } from './useAuthState'
// @ts-expect-error - #auth not defined
import type { SessionData } from '#auth'
import { useNuxtApp, useRuntimeConfig, nextTick, navigateTo } from '#imports'
import { navigateTo, nextTick, useNuxtApp, useRuntimeConfig } from '#imports'

type Credentials = { username?: string, email?: string, password?: string } & Record<string, any>

Expand Down Expand Up @@ -49,7 +49,7 @@ const signOut: SignOutFunc = async (signOutOptions) => {
const config = useTypedBackendConfig(runtimeConfig, 'local')
const { data, rawToken, token } = await callWithNuxt(nuxt, useAuthState)

const headers = new Headers({ [config.token.headerName]: token.value } as HeadersInit)
const headers = new Headers(config.token.headerName ? { [config.token.headerName]: token.value } as HeadersInit : undefined)
data.value = null
rawToken.value = null

Expand All @@ -76,7 +76,7 @@ const getSession: GetSessionFunc<SessionData | null | void> = async (getSessionO
return
}

const headers = new Headers(token.value ? { [config.token.headerName]: token.value } as HeadersInit : undefined)
const headers = new Headers(token.value && config.token.headerName ? { [config.token.headerName]: token.value } as HeadersInit : undefined)

loading.value = true
try {
Expand Down
20 changes: 15 additions & 5 deletions src/runtime/composables/local/useAuthState.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { computed, watch, ComputedRef } from 'vue'
import { CookieRef } from '#app'
import { useCookie, useRuntimeConfig, useState } from '#imports'
import { ComputedRef, computed, watch } from 'vue'
import { useTypedBackendConfig } from '../../helpers'
import { CommonUseAuthStateReturn } from '../../types'
import { makeCommonAuthState } from '../commonAuthState'
import { useTypedBackendConfig } from '../../helpers'
import { useRuntimeConfig, useCookie, useState } from '#imports'
// @ts-expect-error - #auth not defined
import type { SessionData } from '#auth'

Expand All @@ -19,7 +19,7 @@ export const useAuthState = (): UseAuthStateReturn => {
const commonAuthState = makeCommonAuthState<SessionData>()

// Re-construct state from cookie, also setup a cross-component sync via a useState hack, see https://github.com/nuxt/nuxt/issues/13020#issuecomment-1397282717
const _rawTokenCookie = useCookie<string | null>('auth:token', { default: () => null, maxAge: config.token.maxAgeInSeconds, sameSite: config.token.sameSiteAttribute })
const _rawTokenCookie = useCookie<string | null>(config.token.name, { default: () => null, maxAge: config.token.maxAgeInSeconds, sameSite: config.token.sameSiteAttribute, secure: config.token.secure, domain: config.token.domain })

const rawToken = useState('auth:raw-token', () => _rawTokenCookie.value)
watch(rawToken, () => { _rawTokenCookie.value = rawToken.value })
Expand All @@ -28,7 +28,17 @@ export const useAuthState = (): UseAuthStateReturn => {
if (rawToken.value === null) {
return null
}
return config.token.type.length > 0 ? `${config.token.type} ${rawToken.value}` : rawToken.value

if (config.token.type.length > 0) {
switch (config.token.type) {
case 'Cookie':
return `${config.token.name}=${rawToken.value}`
case 'Bearer':
default:
return `${config.token.type} ${rawToken.value}`
}
}
return rawToken.value
})

const setToken = (newToken: string | null) => {
Expand Down
29 changes: 25 additions & 4 deletions src/runtime/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Ref, ComputedRef } from 'vue'
import { RouterMethod } from 'h3'
import type { ComputedRef, Ref } from 'vue'
import { SupportedProviders } from './composables/authjs/useAuth'

/**
Expand Down Expand Up @@ -110,6 +110,12 @@ type ProviderLocal = {
* Settings for the authentication-token that `nuxt-auth` receives from the `signIn` endpoint and that can be used to authenticate subsequent requests.
*/
token?: {
/**
* The name of the cookie to store the authentication-token in.
*
* @default auth:token Access the cookie `auth:token` from session
*/
name?: string,
/**
* How to extract the authentication-token from the sign-in response.
*
Expand All @@ -133,14 +139,14 @@ type ProviderLocal = {
* Header name to be used in requests that need to be authenticated, e.g., to be used in the `getSession` request.
*
* @default Authorization
* @example Auth
* @example Cookie
*/
headerName?: string,
/**
* Maximum age to store the authentication token for. After the expiry time the token is automatically deleted on the application side, i.e., in the users' browser.
*
* Note: Your backend may reject / expire the token earlier / differently.
* @default 1800
* @default undefined
* @example 60 * 60 * 24
*/
maxAgeInSeconds?: number,
Expand All @@ -150,7 +156,22 @@ type ProviderLocal = {
* @default 'lax'
* @example 'strict'
*/
sameSiteAttribute?: boolean | 'lax' | 'strict' | 'none' | undefined,
sameSiteAttribute?: boolean | 'lax' | 'strict' | 'none' | undefined,
/**
* Specifies the boolean value for the Secure Set-Cookie attribute. When truthy, the Secure attribute is set; otherwise it is not. By default, the Secure attribute is not set.
* Note: Be careful when setting this to true, as compliant clients will not allow client-side JavaScript to see the cookie in document.cookie.
* @default false
* @example true
*/
secure?: boolean,
/**
* Specifies the value for the Domain Set-Cookie attribute. By default, no domain is set, and most clients will consider applying the cookie only to the current domain.
*
* @default undefined use
* @example 'domain.com'
*/
domain?: boolean,

},
/**
* Define an interface for the session data object that `nuxt-auth` expects to receive from the `getSession` endpoint.
Expand Down

0 comments on commit 36e55ce

Please sign in to comment.