-
-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(#854): Add getServerSession
and getToken
to the local provider
#855
Changes from all commits
2252a69
9fa1c05
657a5a0
df4c8eb
04d6ab7
088bf4e
e18bf06
b998c30
db3cc27
70f9b36
10402c0
e9b8654
f42d8f0
44e9949
11b3dfc
e64d470
868672d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { eventHandler } from 'h3' | ||
import { getServerSession } from '#auth' | ||
|
||
export default eventHandler(async (event) => { | ||
const session = await getServerSession(event) | ||
if (!session) { | ||
return { status: 'unauthenticated!' } | ||
} | ||
return { status: 'authenticated!', text: 'im protected by an in-endpoint check', session } | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { eventHandler } from 'h3' | ||
|
||
export default eventHandler(() => ({ status: 'authenticated', text: 'you only see me if you are logged in, as a server-middleware protects me' })) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { defineEventHandler } from 'h3' | ||
import { getServerSession } from '#auth' | ||
|
||
export default defineEventHandler(event => getServerSession(event)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { defineEventHandler } from 'h3' | ||
import { getToken } from '#auth' | ||
|
||
export default defineEventHandler(event => getToken(event)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { createError, eventHandler } from 'h3' | ||
import { getServerSession } from '#auth' | ||
|
||
export default eventHandler(async (event) => { | ||
// Only protect a certain backend route | ||
if (!event.node.req.url?.startsWith('/api/protected/middleware')) { | ||
return | ||
} | ||
|
||
const session = await getServerSession(event) | ||
if (!session) { | ||
throw createError({ statusMessage: 'Unauthenticated', statusCode: 403 }) | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { NuxtAuthHandler, getServerSession, getToken } from './nuxtAuthHandler' |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { type H3Event, createError } from 'h3' | ||
import getURL from 'requrl' | ||
import { joinURL } from 'ufo' | ||
import { jsonPointerGet, useTypedBackendConfig } from '../../../helpers' | ||
import { getToken } from './getToken' | ||
|
||
// @ts-expect-error - #auth not defined | ||
import type { SessionData } from '#auth' | ||
import { useRuntimeConfig } from '#imports' | ||
|
||
function joinPathToApiURL(event: H3Event, path: string) { | ||
const { origin, pathname, fullBaseUrl } = useRuntimeConfig().public.auth.computed | ||
|
||
let baseURL | ||
if (origin) { | ||
// Case 1: An origin was supplied by the developer in the runtime-config. Use it by returning the already assembled full base url that contains it | ||
baseURL = fullBaseUrl | ||
} | ||
else { | ||
// Case 2: An origin was not supplied, we determine it from the request | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This probably needs to happen only when |
||
const determinedOrigin = getURL(event.node.req, false) | ||
baseURL = joinURL(determinedOrigin, pathname) | ||
} | ||
|
||
const base = path.startsWith('/') ? pathname : baseURL | ||
return joinURL(base, path) | ||
} | ||
|
||
export async function getServerSession(event: H3Event): Promise<SessionData | null> { | ||
const token = getToken(event) | ||
if (!token) { | ||
return null | ||
} | ||
|
||
const config = useTypedBackendConfig(useRuntimeConfig(), 'local') | ||
const { path, method } = config.endpoints.getSession | ||
|
||
// Compose heads to request the session | ||
const headers = new Headers({ [config.token.headerName]: token } as HeadersInit) | ||
|
||
try { | ||
const url = joinPathToApiURL(event, path) | ||
const result = await $fetch<any>(url, { method, headers }) | ||
const { dataResponsePointer: sessionDataResponsePointer } = config.session | ||
return jsonPointerGet<SessionData>(result, sessionDataResponsePointer) | ||
} | ||
catch (err) { | ||
console.error(err) | ||
throw createError({ statusCode: 401, statusMessage: 'Session could not be retrieved.' }) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,15 @@ | ||||||||||||
import { type H3Event, getCookie } from 'h3' | ||||||||||||
import { useTypedBackendConfig } from '../../../helpers' | ||||||||||||
import { formatToken } from '../../../utils/local' | ||||||||||||
import { useRuntimeConfig } from '#imports' | ||||||||||||
|
||||||||||||
export function getToken(event: H3Event) { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
const config = useTypedBackendConfig(useRuntimeConfig(), 'local') | ||||||||||||
const rawToken = getCookie(event, config.token.cookieName) | ||||||||||||
const token = formatToken(rawToken, config) | ||||||||||||
|
||||||||||||
if (!token) { | ||||||||||||
return null | ||||||||||||
} | ||||||||||||
return token | ||||||||||||
Comment on lines
+11
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { getToken } from './getToken' | ||
export { getServerSession } from './getServerSession' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { genInterface } from 'knitwork' | ||
import { createResolver } from '@nuxt/kit' | ||
import type { AuthProviders } from '../types' | ||
|
||
export function generateModuleTypes(provider: AuthProviders) { | ||
const { resolve } = createResolver(import.meta.url) | ||
|
||
const providerSpecificTypes: string[] = [] | ||
|
||
if (provider.type === 'authjs') { | ||
providerSpecificTypes.push(` const { getServerSession, getToken, NuxtAuthHandler }: typeof import('${resolve('./runtime/server/services/authjs')}')`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question - does this resolve relative to current path or from root? From the docs, it looks like the resolution will happen from the current path which is not correct: |
||
} | ||
|
||
if (provider.type === 'local') { | ||
providerSpecificTypes.push(` const { getServerSession, getToken }: typeof import('${resolve('./runtime/server/services/local')}')`) | ||
providerSpecificTypes.push(genInterface('SessionData', (provider as any).session.dataType)) | ||
} | ||
|
||
return [ | ||
'// AUTO-GENERATED BY @sidebase/nuxt-auth', | ||
`declare module '#auth' {`, | ||
...providerSpecificTypes, | ||
'}', | ||
'' | ||
].join('\n') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: would prefer if this was down the file as it is a helper (consumers are more interested in reading
getServerSession