mirror of
https://github.com/supabase/supabase.git
synced 2026-10-15 14:19:11 +03:00
fix(common): prevent errors when accessing local storage in certain browser setups Got many reports of errors from accessing localStorage on Safari, probably due to certain user security settings that cause the browser to throw an error on storage access.
127 lines
3.7 KiB
TypeScript
127 lines
3.7 KiB
TypeScript
import { AuthClient, navigatorLock, User } from '@supabase/auth-js'
|
|
|
|
export const STORAGE_KEY = process.env.NEXT_PUBLIC_STORAGE_KEY || 'supabase.dashboard.auth.token'
|
|
export const AUTH_DEBUG_KEY =
|
|
process.env.NEXT_PUBLIC_AUTH_DEBUG_KEY || 'supabase.dashboard.auth.debug'
|
|
export const AUTH_DEBUG_PERSISTED_KEY =
|
|
process.env.NEXT_PUBLIC_AUTH_DEBUG_PERSISTED_KEY || 'supabase.dashboard.auth.debug.persist'
|
|
export const AUTH_NAVIGATOR_LOCK_DISABLED_KEY =
|
|
process.env.NEXT_PUBLIC_AUTH_NAVIGATOR_LOCK_KEY ||
|
|
'supabase.dashboard.auth.navigatorLock.disabled'
|
|
|
|
/**
|
|
* Catches errors thrown when accessing localStorage. Safari with certain
|
|
* security settings throws when localStorage is accessed.
|
|
*/
|
|
function safeGetLocalStorage(key: string) {
|
|
try {
|
|
return globalThis?.localStorage?.getItem(key)
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const debug =
|
|
process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' && safeGetLocalStorage(AUTH_DEBUG_KEY) === 'true'
|
|
|
|
const persistedDebug =
|
|
process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' &&
|
|
safeGetLocalStorage(AUTH_DEBUG_PERSISTED_KEY) === 'true'
|
|
|
|
const shouldEnableNavigatorLock =
|
|
process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' &&
|
|
!(safeGetLocalStorage(AUTH_NAVIGATOR_LOCK_DISABLED_KEY) === 'true')
|
|
|
|
const shouldDetectSessionInUrl = process.env.NEXT_PUBLIC_AUTH_DETECT_SESSION_IN_URL
|
|
? process.env.NEXT_PUBLIC_AUTH_DETECT_SESSION_IN_URL === 'true'
|
|
: true
|
|
|
|
const navigatorLockEnabled = !!(shouldEnableNavigatorLock && globalThis?.navigator?.locks)
|
|
|
|
if (shouldEnableNavigatorLock && !globalThis?.navigator?.locks) {
|
|
console.warn('This browser does not support the Navigator Locks API. Please update it.')
|
|
}
|
|
|
|
const tabId = Math.random().toString(16).substring(2)
|
|
|
|
let dbHandle = new Promise<IDBDatabase | null>((accept, _) => {
|
|
if (!persistedDebug) {
|
|
accept(null)
|
|
return
|
|
}
|
|
|
|
const request = indexedDB.open('auth-debug-log', 1)
|
|
|
|
request.onupgradeneeded = (event: any) => {
|
|
const db = event?.target?.result
|
|
|
|
if (!db) {
|
|
return
|
|
}
|
|
|
|
db.createObjectStore('events', { autoIncrement: true })
|
|
}
|
|
|
|
request.onsuccess = (event: any) => {
|
|
console.log('Opened persisted auth debug log IndexedDB database', tabId)
|
|
accept(event.target.result)
|
|
}
|
|
|
|
request.onerror = (event: any) => {
|
|
console.error('Failed to open persisted auth debug log IndexedDB database', event)
|
|
accept(null)
|
|
}
|
|
})
|
|
|
|
const logIndexedDB = (message: string, ...args: any[]) => {
|
|
console.log(message, ...args)
|
|
|
|
const copyArgs = structuredClone(args)
|
|
|
|
copyArgs.forEach((value) => {
|
|
if (typeof value === 'object' && value !== null) {
|
|
delete value.user
|
|
delete value.access_token
|
|
delete value.token_type
|
|
delete value.provider_token
|
|
}
|
|
})
|
|
;(async () => {
|
|
try {
|
|
const db = await dbHandle
|
|
|
|
if (!db) {
|
|
return
|
|
}
|
|
|
|
const tx = db.transaction(['events'], 'readwrite')
|
|
tx.onerror = (event: any) => {
|
|
console.error('Failed to write to persisted auth debug log IndexedDB database', event)
|
|
dbHandle = Promise.resolve(null)
|
|
}
|
|
|
|
const events = tx.objectStore('events')
|
|
|
|
events.add({
|
|
m: message.replace(/^GoTrueClient@/i, ''),
|
|
a: copyArgs,
|
|
l: window.location.pathname,
|
|
t: tabId,
|
|
})
|
|
} catch (e: any) {
|
|
console.error('Failed to log to persisted auth debug log IndexedDB database', e)
|
|
dbHandle = Promise.resolve(null)
|
|
}
|
|
})()
|
|
}
|
|
|
|
export const gotrueClient = new AuthClient({
|
|
url: process.env.NEXT_PUBLIC_GOTRUE_URL,
|
|
storageKey: STORAGE_KEY,
|
|
detectSessionInUrl: shouldDetectSessionInUrl,
|
|
debug: debug ? (persistedDebug ? logIndexedDB : true) : false,
|
|
lock: navigatorLockEnabled ? navigatorLock : undefined,
|
|
})
|
|
|
|
export type { User }
|