Skip to content

enh(#797): Determine if baseUrl is external and properly handle internal requests #856

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

Closed
wants to merge 13 commits into from
Closed
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
2 changes: 1 addition & 1 deletion docs/guide/local/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The entire configuration for the `local` provider is contained inside the `nuxt.
export default defineNuxtConfig({
modules: ['@sidebase/nuxt-auth'],
auth: {
baseURL: '/api/auth',
baseURL: '/api/auth', // or an external url: (e.g. https://auth.example.com/api/auth)
provider: {
type: 'local'
}
Expand Down
4 changes: 1 addition & 3 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ export default defineNuxtModule<ModuleOptions>({
const logger = useLogger(PACKAGE_NAME)

// 0. Assemble all options
const { origin, pathname = '/api/auth' } = getOriginAndPathnameFromURL(
userOptions.baseURL ?? ''
)
const { origin, pathname = '/api/auth' } = getOriginAndPathnameFromURL(userOptions.baseURL ?? '')

const selectedProvider = userOptions.provider?.type ?? 'authjs'

Expand Down
13 changes: 11 additions & 2 deletions src/runtime/composables/commonAuthState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,34 @@ export function makeCommonAuthState<SessionData>() {

// Determine base url of app
let baseURL
const determinedOrigin = getURL(useRequestEvent()?.node.req, false)
const { origin, pathname, fullBaseUrl } = useRuntimeConfig().public.auth.computed
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
const determinedOrigin = getURL(useRequestEvent()?.node.req, false)
baseURL = joinURL(determinedOrigin, pathname)
}

// Determine if the API is internal. This is the case if:
// - no `ORIGIN` was provided
// - the provided `ORIGIN` matches the `determinedOrigin` of the app
let isBaseURLInternal = false
if (!origin || origin === determinedOrigin) {
isBaseURLInternal = true
}

return {
data,
loading,
lastRefreshedAt,
status,
_internal: {
baseURL,
pathname
basePath: pathname,
isBaseURLInternal
}
}
}
3 changes: 2 additions & 1 deletion src/runtime/composables/local/useAuthState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export interface UseAuthStateReturn extends CommonUseAuthStateReturn<SessionData
clearToken: () => void
_internal: {
baseURL: string
pathname: string
basePath: string
isBaseURLInternal: boolean
rawTokenCookie: CookieRef<string | null>
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/runtime/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,15 +516,22 @@ export interface CommonUseAuthReturn<SignIn, SignOut, GetSession, SessionData> {
getSession: GetSession
refresh: () => Promise<unknown>
}

/**
* Common values required for all providers
*
* @remark basePath: The `basePath` for the API without an `origin`
* @remark baseURL: The `basePath` combined with an `origin` (provided via config or determined)
* @remark isBaseURLInternal: Is the origin provided in `baseURL` the same as that of the Nuxt app?
*/
export interface CommonUseAuthStateReturn<SessionData> {
data: WrappedSessionData<SessionData>
loading: Ref<boolean>
lastRefreshedAt: Ref<SessionLastRefreshedAt>
status: ComputedRef<SessionStatus>
_internal: {
baseURL: string
pathname: string
basePath: string
isBaseURLInternal: boolean
}
}

Expand Down
14 changes: 5 additions & 9 deletions src/runtime/utils/url.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import { joinURL } from 'ufo'
import { withBase } from 'ufo'
import getURL from 'requrl'
import { sanitizeStatusCode } from 'h3'
import type { ModuleOptionsNormalized } from '../types'
import { abortNavigation, useAuthState, useNuxtApp, useRequestEvent } from '#imports'

export const getRequestURL = (includePath = true) => getURL(useRequestEvent()?.node.req, includePath)
export function joinPathToApiURL(path: string) {
const authStateInternal = useAuthState()._internal
const { baseURL, basePath, isBaseURLInternal } = useAuthState()._internal

// For internal calls, use a different base
// https://github.com/sidebase/nuxt-auth/issues/742
const base = path.startsWith('/')
? authStateInternal.pathname
: authStateInternal.baseURL

return joinURL(base, path)
// For internal calls, do not include the `ORIGIN`
const base = isBaseURLInternal ? basePath : baseURL
return withBase(path, base)
}

/**
Expand Down
Loading