Skip to content

Commit

Permalink
enh(#935): allow external login page (#936)
Browse files Browse the repository at this point in the history
* allow external link as login page

* allow external login page

* fix typecheck

* chore: adjust the external handling

---------

Co-authored-by: Thomas <[email protected]>
Co-authored-by: Zoey <[email protected]>
Co-authored-by: Marsel Shaikhin <[email protected]>
  • Loading branch information
4 people authored Dec 12, 2024
1 parent 37b0c65 commit b1e4aba
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 8 deletions.
18 changes: 13 additions & 5 deletions src/runtime/middleware/sidebase-auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { determineCallbackUrl } from '../utils/url'
import { determineCallbackUrl, isExternalUrl } from '../utils/url'
import { isProduction } from '../helpers'
import { ERROR_PREFIX } from '../utils/logger'
import { defineNuxtRouteMiddleware, navigateTo, useAuth, useRuntimeConfig } from '#imports'

type MiddlewareMeta = boolean | {
Expand Down Expand Up @@ -98,23 +99,30 @@ export default defineNuxtRouteMiddleware((to) => {
return navigateTo(options.navigateUnauthenticatedTo)
}

const loginPage = authConfig.provider.pages.login
if (typeof loginPage !== 'string') {
console.warn(`${ERROR_PREFIX} provider.pages.login is misconfigured`)
return
}

// Default callback URL was provided
const external = isExternalUrl(loginPage)
if (typeof globalAppMiddleware === 'object' && globalAppMiddleware.addDefaultCallbackUrl) {
let redirectUrl: string = to.fullPath
if (typeof globalAppMiddleware.addDefaultCallbackUrl === 'string') {
redirectUrl = globalAppMiddleware.addDefaultCallbackUrl
}

return navigateTo({
path: authConfig.provider.pages.login,
path: loginPage,
query: {
redirect: redirectUrl
}
})
}, { external })
}

// Fall back to login page
return navigateTo(authConfig.provider.pages.login)
return navigateTo(loginPage, { external })
})

interface MiddlewareOptionsNormalized {
Expand Down Expand Up @@ -146,7 +154,7 @@ function normalizeUserOptions(userOptions: MiddlewareMeta | undefined): Middlewa
if (userOptions.unauthenticatedOnly === undefined) {
if (!isProduction) {
console.warn(
'[@sidebase/nuxt-auth] `unauthenticatedOnly` was not provided to `definePageMeta` - defaulting to Guest Mode enabled. '
`${ERROR_PREFIX} \`unauthenticatedOnly\` was not provided to \`definePageMeta\` - defaulting to Guest Mode enabled. `
+ 'Read more at https://auth.sidebase.io/guide/application-side/protecting-pages#middleware-options'
)
}
Expand Down
3 changes: 1 addition & 2 deletions src/runtime/utils/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { resolveApiUrlPath } from './url'
import { ERROR_PREFIX } from './logger'
import { callWithNuxt, useRuntimeConfig } from '#app'
import type { useNuxtApp } from '#imports'

const ERROR_PREFIX = '[@sidebase/nuxt-auth]'

export async function _fetch<T>(nuxt: ReturnType<typeof useNuxtApp>, path: string, fetchOptions?: Parameters<typeof $fetch>[1]): Promise<T> {
const runtimeConfig = await callWithNuxt(nuxt, useRuntimeConfig)
const joinedPath = resolveApiUrlPath(path, runtimeConfig)
Expand Down
1 change: 1 addition & 0 deletions src/runtime/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const ERROR_PREFIX = '[@sidebase/nuxt-auth]'
11 changes: 10 additions & 1 deletion src/runtime/utils/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function resolveApiUrlPath(
runtimeConfig: RuntimeConfig
): string {
// Fully-specified endpoint path - do not join with `baseURL`
if (endpointPath.startsWith('http://') || endpointPath.startsWith('https://')) {
if (isExternalUrl(endpointPath)) {
return endpointPath
}

Expand Down Expand Up @@ -95,3 +95,12 @@ export function determineCallbackUrl<T extends string | Promise<string>>(
return getOriginalTargetPath()
}
}

/**
* Naively checks if a URL is external or not by comparing against its protocol.
*
* URL being valid is not a concern for this function as it is used with developer-controlled inputs.
*/
export function isExternalUrl(url: string): boolean {
return url.startsWith('http://') || url.startsWith('https://')
}

0 comments on commit b1e4aba

Please sign in to comment.