Skip to content
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

nuxt baseURL support #76

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/runtime/composables/oidcAuth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ComputedRef, Ref } from '#imports'
import type { ProviderKeys, UserSession } from '../types'
import { computed, navigateTo, useRequestFetch, useState } from '#imports'
import { parsePath } from '../server/utils/path'

const useSessionState = () => useState<UserSession>('nuxt-oidc-auth-session', undefined)

Expand All @@ -13,7 +14,7 @@ export function useOidcAuth() {
const currentProvider: ComputedRef<ProviderKeys | undefined | 'dev'> = computed(() => sessionState.value?.provider || undefined)

async function fetch() {
useSessionState().value = (await useRequestFetch()('/api/_auth/session', {
useSessionState().value = (await useRequestFetch()(parsePath('/api/_auth/session'), {
headers: {
Accept: 'text/json',
},
Expand All @@ -26,7 +27,7 @@ export function useOidcAuth() {
* @returns {Promise<void>}
*/
async function refresh(): Promise<void> {
useSessionState().value = (await useRequestFetch()('/api/_auth/refresh', {
useSessionState().value = (await useRequestFetch()(parsePath('/api/_auth/refresh'), {
headers: {
Accept: 'text/json',
},
Expand All @@ -43,7 +44,7 @@ export function useOidcAuth() {
*/
async function login(provider?: ProviderKeys | 'dev', params?: Record<string, string>): Promise<void> {
const queryParams = params ? `?${new URLSearchParams(params).toString()}` : ''
await navigateTo(`/auth${provider ? `/${provider}` : ''}/login${queryParams}`, { external: true, redirectCode: 302 })
await navigateTo(parsePath(`/auth${provider ? `/${provider}` : ''}/login${queryParams}`), { external: true, redirectCode: 302 })
}

/**
Expand All @@ -54,14 +55,14 @@ export function useOidcAuth() {
* @returns {Promise<void>}
*/
async function logout(provider?: ProviderKeys | 'dev', logoutRedirectUri?: string): Promise<void> {
await navigateTo(`/auth${provider ? `/${provider}` : currentProvider.value ? `/${currentProvider.value}` : ''}/logout${logoutRedirectUri ? `?logout_redirect_uri=${logoutRedirectUri}` : ''}`, { external: true, redirectCode: 302 })
await navigateTo(parsePath(`/auth${provider ? `/${provider}` : currentProvider.value ? `/${currentProvider.value}` : ''}/logout${logoutRedirectUri ? `?logout_redirect_uri=${logoutRedirectUri}` : ''}`), { external: true, redirectCode: 302 })
}

/**
* Clears the current user session. Mainly for debugging, in production, always use the `logout` function, which completely cleans the state.
*/
async function clear() {
await useRequestFetch()('/api/_auth/session', {
await useRequestFetch()(parsePath('/api/_auth/session'), {
method: 'DELETE',
headers: {
Accept: 'text/json',
Expand Down
5 changes: 3 additions & 2 deletions src/runtime/server/handler/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getUserSessionId, setUserSession, useAuthSession } from '../utils/sessi
// @ts-expect-error - Missing Nitro type exports in Nuxt
import { useRuntimeConfig, useStorage } from '#imports'
import { textToBase64 } from 'undio'
import { parsePath } from '../utils/path'

function callbackEventHandler({ onSuccess }: OAuthConfig<UserSession>) {
const logger = useOidcLogger()
Expand All @@ -33,7 +34,7 @@ function callbackEventHandler({ onSuccess }: OAuthConfig<UserSession>) {
// Check for admin consent callback
if (admin_consent) {
const url = getRequestURL(event)
sendRedirect(event, `${url.origin}/auth/${provider}/login`, 200)
sendRedirect(event, url.origin + parsePath(`/auth/${provider}/login`), 200)
}

// Verify id_token, if available (hybrid flow)
Expand Down Expand Up @@ -210,6 +211,6 @@ function callbackEventHandler({ onSuccess }: OAuthConfig<UserSession>) {
export default callbackEventHandler({
async onSuccess(event, { user, callbackRedirectUrl }) {
await setUserSession(event, user as UserSession)
return sendRedirect(event, callbackRedirectUrl || '/' as string)
return sendRedirect(event, parsePath(callbackRedirectUrl ?? '/'))
},
})
9 changes: 9 additions & 0 deletions src/runtime/server/utils/path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useRuntimeConfig } from '#imports'

/**
* Adds Nuxt baseURL to the passed path if set
*/
export function parsePath(path: string) {
const nuxtBaseUrl: string = useRuntimeConfig().app.baseURL ?? '/'
return `${nuxtBaseUrl}${path.startsWith('/') ? path.slice(1) : path}`
}
3 changes: 2 additions & 1 deletion src/runtime/server/utils/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { configMerger, refreshAccessToken, useOidcLogger } from './oidc'
import { decryptToken, encryptToken } from './security'
// @ts-expect-error - Missing Nitro type exports in Nuxt
import { useRuntimeConfig, useStorage } from '#imports'
import { parsePath } from './path'

const sessionName = 'nuxt-oidc-auth'
let sessionConfig: Pick<SessionConfig, 'name' | 'password'> & AuthSessionConfig
Expand Down Expand Up @@ -87,7 +88,7 @@ export async function refreshUserSession(event: H3Event) {
}
catch (error) {
logger.error(error)
return sendRedirect(event, `/auth/${provider}/logout`)
return sendRedirect(event, parsePath(`/auth/${provider}/logout`))
}

const { user, tokens, expiresIn, parsedAccessToken } = tokenRefreshResponse
Expand Down