Skip to content

Commit

Permalink
feat(refactor): ✨ Deprecated requireUserSession; Internal refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
itpropro committed Sep 19, 2024
1 parent b834ea2 commit 68d98ff
Show file tree
Hide file tree
Showing 14 changed files with 34 additions and 53 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,10 @@ In addition, if `defaultProvider` is set, the following route rules are register
You can access the user session in your server side code by using the `getUserSession` function from the `@nuxtjs/oidc-auth` module.

```ts
import { requireUserSession } from "nuxt-oidc-auth/runtime/server/utils/session.mjs"
import { getUserSession } from "nuxt-oidc-auth/runtime/server/utils/session.mjs"

export default eventHandler(async (event) => {
const session = await requireUserSession(event)
const session = await getUserSession(event)
return session.userName
})
```
Expand Down
2 changes: 1 addition & 1 deletion playground/auth.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ declare module '#oidc-auth' {
}
}

export {}
export {}
1 change: 0 additions & 1 deletion playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export default defineNuxtConfig({
validateAccessToken: false,
validateIdToken: true,
exposeIdToken: true,
callbackRedirectUrl: '',
},
auth0: {
audience: 'test-api-oidc',
Expand Down
7 changes: 1 addition & 6 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,6 @@ export default defineNuxtModule<ModuleOptions>({
route: `/auth/${provider}/callback`,
method: 'post',
})
extendPages((pages) => {
pages.push({
path: `/auth/${provider}/callback`,
})
})
// Add logout handler
addServerHandler({
handler: resolve('./runtime/server/handler/logout.get'),
Expand All @@ -307,7 +302,7 @@ export default defineNuxtModule<ModuleOptions>({
// Add global auth middleware
if (options.middleware.globalMiddlewareEnabled) {
addRouteMiddleware({
name: '00.auth',
name: '00.auth.global',
path: resolve('runtime/middleware/oidcAuth'),
global: true,
})
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/composables/oidcAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function useOidcAuth() {
const sessionState: Ref<UserSession> = useSessionState()
const user: ComputedRef<UserSession> = computed(() => sessionState.value || undefined)
const loggedIn: ComputedRef<boolean> = computed<boolean>(() => {
return Boolean(sessionState.value)
return Boolean(sessionState.value?.userName)
})
const currentProvider: ComputedRef<ProviderKeys | undefined | 'dev'> = computed(() => sessionState.value?.provider || undefined)
async function fetch() {
Expand All @@ -30,7 +30,7 @@ export function useOidcAuth() {
}

async function logout(provider?: ProviderKeys | 'dev') {
await navigateTo(`/auth${provider ? `/${provider}` : ''}/logout`, { external: true })
await navigateTo(`/auth${provider ? `/${provider}` : ''}/logout`, { external: true, redirectCode: 302 })
}

/**
Expand Down
5 changes: 2 additions & 3 deletions src/runtime/server/api/refresh.post.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { eventHandler } from 'h3'
import { refreshUserSession, requireUserSession } from '../utils/session'
import { getUserSession, refreshUserSession } from '../utils/session'

export default eventHandler(async (event) => {
await requireUserSession(event)
await getUserSession(event)
await refreshUserSession(event)

return { refreshed: true }
})
6 changes: 2 additions & 4 deletions src/runtime/server/api/session.get.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { eventHandler } from 'h3'
import { requireUserSession, sessionHooks } from '../utils/session'
import { getUserSession, sessionHooks } from '../utils/session'

export default eventHandler(async (event) => {
const session = await requireUserSession(event)

const session = await getUserSession(event)
await sessionHooks.callHookParallel('fetch', session, event)

return session
})
2 changes: 1 addition & 1 deletion src/runtime/server/handler/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import type { UserSession } from '../../types/session'
export default callbackEventHandler({
async onSuccess(event, { user, callbackRedirectUrl }) {
await setUserSession(event, user as UserSession)
return sendRedirect(event, callbackRedirectUrl as string)
return sendRedirect(event, callbackRedirectUrl || '/' as string)
},
})
3 changes: 2 additions & 1 deletion src/runtime/server/handler/dev.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { sendRedirect } from 'h3'
import { devEventHandler } from '../lib/oidc'
import { setUserSession } from '../utils/session'
import type { UserSession } from '../../types/session'

export default devEventHandler({
async onSuccess(event, { user }) {
await setUserSession(event, user)
await setUserSession(event, user as UserSession)
return sendRedirect(event, '/')
},
})
6 changes: 1 addition & 5 deletions src/runtime/server/handler/login.get.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import { sendRedirect } from 'h3'
import { loginEventHandler } from '../lib/oidc'

export default loginEventHandler({
async onSuccess(event) {
return sendRedirect(event, '/')
},
})
export default loginEventHandler()
24 changes: 9 additions & 15 deletions src/runtime/server/lib/oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async function useAuthSession(event: H3Event) {
return session
}

export function loginEventHandler({ onError }: OAuthConfig<UserSession>) {
export function loginEventHandler() {
const logger = useOidcLogger()
return eventHandler(async (event: H3Event) => {
// TODO: Is this the best way to get the current provider?
Expand All @@ -34,10 +34,7 @@ export function loginEventHandler({ onError }: OAuthConfig<UserSession>) {

if (!validationResult.valid) {
logger.error(`[${provider}] Missing configuration properties:`, validationResult.missingProperties?.join(', '))
const error = new H3Error('Invalid configuration')
if (!onError)
throw error
return onError(event, error)
oidcErrorHandler(event, 'Invalid configuration')
}

// Initialize auth session
Expand Down Expand Up @@ -78,7 +75,7 @@ export function loginEventHandler({ onError }: OAuthConfig<UserSession>) {
})
}

export function callbackEventHandler({ onSuccess, onError }: OAuthConfig<UserSession>) {
export function callbackEventHandler({ onSuccess }: OAuthConfig<UserSession>) {
const logger = useOidcLogger()
return eventHandler(async (event: H3Event) => {
const provider = event.path.split('/')[2] as ProviderKeys
Expand All @@ -88,10 +85,7 @@ export function callbackEventHandler({ onSuccess, onError }: OAuthConfig<UserSes

if (!validationResult.valid) {
logger.error(`[${provider}] Missing configuration properties: `, validationResult.missingProperties?.join(', '))
const error = new H3Error('Invalid configuration')
if (!onError)
throw error
return onError(event, error)
oidcErrorHandler(event, 'Invalid configuration')
}

const session = await useAuthSession(event)
Expand All @@ -108,7 +102,7 @@ export function callbackEventHandler({ onSuccess, onError }: OAuthConfig<UserSes
if (id_token) {
const parsedIdToken = parseJwtToken(id_token)
if (parsedIdToken.nonce !== session.data.nonce) {
oidcErrorHandler(event, 'Nonce mismatch', onError)
oidcErrorHandler(event, 'Nonce mismatch')
}
}

Expand All @@ -118,14 +112,14 @@ export function callbackEventHandler({ onSuccess, onError }: OAuthConfig<UserSes
logger.error(`[${provider}] ${error}`, error_description && `: ${error_description}`)
}
if (!code) {
oidcErrorHandler(event, 'Callback failed, missing code', onError)
oidcErrorHandler(event, 'Callback failed, missing code')
}
oidcErrorHandler(event, 'Callback failed', onError)
oidcErrorHandler(event, 'Callback failed')
}

// Check for valid state
if (config.state && (state !== session.data.state)) {
oidcErrorHandler(event, 'State mismatch', onError)
oidcErrorHandler(event, 'State mismatch')
}

// Construct request header object
Expand Down Expand Up @@ -174,7 +168,7 @@ export function callbackEventHandler({ onSuccess, onError }: OAuthConfig<UserSes
200,
)
}
return oidcErrorHandler(event, 'Token request failed', onError)
return oidcErrorHandler(event, 'Token request failed')
}

// Initialize tokens object
Expand Down
7 changes: 2 additions & 5 deletions src/runtime/server/utils/oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,9 @@ export function convertObjectToSnakeCase(object: Record<string, any>) {
}, {} as Record<string, any>)
}

export function oidcErrorHandler(event: H3Event, errorText: string, onError?: ((event: H3Event, error: H3Error) => void | Promise<void>), errorCode: number = 500) {
const h3Error = createError({
export function oidcErrorHandler(event: H3Event, errorText: string, errorCode: number = 500) {
throw createError({
statusCode: errorCode,
message: errorText,
})
if (!onError)
throw h3Error
return onError(event, h3Error)
}
13 changes: 8 additions & 5 deletions src/runtime/server/utils/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { AuthSessionConfig, UserSession } from '../../types/session'
import type { OidcProviderConfig, PersistentSession, ProviderKeys } from '../../types/oidc'
import { decryptToken, encryptToken, parseJwtToken } from './security'
import { configMerger, refreshAccessToken, useOidcLogger } from './oidc'
// @ts-expect-error - Missing Nitro type exports in Nuxt
import { useRuntimeConfig, useStorage } from '#imports'

const sessionName = 'nuxt-oidc-auth'
Expand All @@ -29,10 +30,6 @@ export interface SessionHooks {

export const sessionHooks = createHooks<SessionHooks>()

export async function getUserSession(event: H3Event) {
return (await _useSession(event)).data
}

/**
* Set a user session
* @param event
Expand Down Expand Up @@ -95,9 +92,14 @@ export async function refreshUserSession(event: H3Event) {
return true
}

// Deprecated, please use getUserSession
export async function requireUserSession(event: H3Event) {
return await getUserSession(event)
}

export async function getUserSession(event: H3Event) {
const logger = useOidcLogger()
const userSession = await getUserSession(event)
const userSession = (await _useSession(event)).data

if (Object.keys(userSession).length === 0) {
throw createError({
Expand Down Expand Up @@ -131,6 +133,7 @@ export async function requireUserSession(event: H3Event) {
// Automatic token refresh
if (sessionConfig.automaticRefresh) {
await refreshUserSession(event)
logger.info('Successfully refreshed token')
return userSession
}
await clearUserSession(event)
Expand Down
3 changes: 1 addition & 2 deletions src/runtime/types/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import type { H3Error, H3Event } from 'h3'
import type { H3Event } from 'h3'

export interface OAuthConfig<UserSession> {
onSuccess: (
event: H3Event,
result: { user: UserSession | null, callbackRedirectUrl?: string }
) => Promise<void> | void
onError?: (event: H3Event, error: H3Error) => Promise<void> | void
}

0 comments on commit 68d98ff

Please sign in to comment.