Skip to content

Commit

Permalink
refactor(auth): migrate to h3
Browse files Browse the repository at this point in the history
  • Loading branch information
dargmuesli committed Sep 29, 2024
1 parent 625fd15 commit 84d9f10
Showing 1 changed file with 64 additions and 54 deletions.
118 changes: 64 additions & 54 deletions src/utils/auth.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,65 @@
import type { IncomingMessage, ServerResponse } from 'node:http'

import type { Client } from '@urql/vue'
import { consola } from 'consola'
import { parse, serialize } from 'cookie-es'
import { type H3Event, setCookie } from 'h3'
import { decodeJwt } from 'jose'
import type { Store } from 'pinia'

import { useVioAuthStore } from '../store/auth'
import { JWT_NAME } from './constants'

export const getJwtFromCookie = ({ req }: { req: IncomingMessage }) => {
if (req.headers.cookie) {
const cookies = parse(req.headers.cookie)
export const getJwtFromCookie = () => {
const cookie = useCookie(JWT_NAME())

if (cookies[JWT_NAME()]) {
const cookie = decodeJwt(cookies[JWT_NAME()])
if (!cookie.value) {
consola.debug('No token cookie.')
return
}

if (cookie.exp !== undefined && cookie.exp > Date.now() / 1000) {
return {
jwt: cookies[JWT_NAME()],
jwtDecoded: cookie,
}
} else {
consola.info('Token expired.')
}
} else {
consola.debug('No token cookie.')
}
} else {
consola.debug('No cookie header.')
const jwt = decodeJwt(cookie.value)

if (jwt.exp === undefined || jwt.exp <= Date.now() / 1000) {
consola.info('Token expired.')
return
}

return {
jwt: cookie.value,
jwtDecoded: jwt,
}
}

export const jwtStore = async ({
$urqlReset,
store,
res,
event,
isInProduction,
jwt,
store,
}: {
$urqlReset: () => void
store: Store
res?: ServerResponse
$urqlReset: () => Client
event?: H3Event
isInProduction: boolean
jwt?: string
store: ReturnType<typeof useVioAuthStore>
}) => {
$urqlReset()

consola.trace('Storing the following JWT: ' + jwt)
;(store as unknown as { jwtSet: (jwtNew?: string) => void }).jwtSet(jwt)
store.jwtSet(jwt)

if (import.meta.server) {
res?.setHeader(
'Set-Cookie',
serialize(JWT_NAME(), jwt || '', {
expires: jwt ? new Date(Date.now() + 86400 * 1000 * 31) : new Date(0),
httpOnly: true,
path: '/',
sameSite: 'lax', // Cannot be 'strict' to allow authentications after clicking on links within webmailers.
secure: true,
}),
)
if (event) {
setCookie(event, JWT_NAME(), jwt || '', {
expires: jwt ? new Date(Date.now() + 86400 * 1000 * 31) : new Date(0),
httpOnly: true,
path: '/',
sameSite: 'lax', // Cannot be 'strict' to allow authentications after clicking on links within webmailers.
secure: isInProduction,
})
} else {
try {
await $fetch('/api/auth', {
method: 'POST',
...(jwt ? { headers: { Authorization: `Bearer ${jwt}` } } : {}),
})
} catch (error: unknown) {
} catch (error) {
console.error(error)
return Promise.reject(Error('Authentication api call failed.'))
}
Expand All @@ -74,42 +69,57 @@ export const jwtStore = async ({
export const useJwtStore = () => {
const { $urqlReset, ssrContext } = useNuxtApp()
const store = useVioAuthStore()
const runtimeConfig = useRuntimeConfig()

return {
async jwtStore(jwt?: string) {
await jwtStore({
$urqlReset: $urqlReset as () => void,
store,
res: ssrContext ? ssrContext.event.node.res : undefined,
$urqlReset: $urqlReset as () => Client,
event: ssrContext?.event,
isInProduction: runtimeConfig.public.vio.isInProduction,
jwt,
store,
})
},
}
}

export const signOut = async ({
$urqlReset,
// client,
event,
isInProduction,
store,
res,
}: {
$urqlReset: () => void
store: Store
res?: ServerResponse
}) => await jwtStore({ $urqlReset, store, res })
$urqlReset: () => Client
client: Client
event?: H3Event
isInProduction: boolean
store: ReturnType<typeof useVioAuthStore>
}) => {
await jwtStore({ $urqlReset, event, isInProduction, store })
// await authenticationAnonymous({
// $urqlReset,
// client,
// event,
// isInProduction,
// store,
// })
}

export const useSignOut = () => {
const { $urqlReset, ssrContext } = useNuxtApp()
const { $urql, $urqlReset, ssrContext } = useNuxtApp()
const store = useVioAuthStore()

if (typeof $urqlReset !== 'function')
throw new Error('`$urqlReset` is not a function!')
const runtimeConfig = useRuntimeConfig()

return {
async signOut() {
await signOut({
$urqlReset: $urqlReset as () => void,
$urqlReset: $urqlReset as () => Client,
client: ($urql as Ref<Client>).value,
event: ssrContext?.event,
isInProduction: runtimeConfig.public.vio.isInProduction,
store,
res: ssrContext ? ssrContext.event.node.res : undefined,
})
},
}
Expand Down

0 comments on commit 84d9f10

Please sign in to comment.