fix(auth): stabilize header session state and retry team token errors
This commit is contained in:
@@ -7,7 +7,8 @@
|
|||||||
export const useAuth = () => {
|
export const useAuth = () => {
|
||||||
const { getToken, initTokens, idToken } = useLogtoTokens()
|
const { getToken, initTokens, idToken } = useLogtoTokens()
|
||||||
const me = useState<{ id?: string | null } | null>('me', () => null)
|
const me = useState<{ id?: string | null } | null>('me', () => null)
|
||||||
const isAuthenticated = computed(() => !!me.value?.id)
|
const logtoUser = useState<Record<string, unknown> | null>('logto-user', () => null)
|
||||||
|
const isAuthenticated = computed(() => !!(me.value?.id || logtoUser.value))
|
||||||
const loggedIn = isAuthenticated
|
const loggedIn = isAuthenticated
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const CLIENT_MAP: Record<string, string> = {
|
|||||||
export const useGraphQL = () => {
|
export const useGraphQL = () => {
|
||||||
const auth = useAuth()
|
const auth = useAuth()
|
||||||
const { activeLogtoOrgId } = useActiveTeam()
|
const { activeLogtoOrgId } = useActiveTeam()
|
||||||
|
const { refreshTokens } = useLogtoTokens()
|
||||||
|
|
||||||
const getClientId = (endpoint: Endpoint, api: Api): string => {
|
const getClientId = (endpoint: Endpoint, api: Api): string => {
|
||||||
return CLIENT_MAP[`${endpoint}:${api}`] || 'default'
|
return CLIENT_MAP[`${endpoint}:${api}`] || 'default'
|
||||||
@@ -77,8 +78,8 @@ export const useGraphQL = () => {
|
|||||||
): Promise<TResult> => {
|
): Promise<TResult> => {
|
||||||
const clientId = getClientId(endpoint, api)
|
const clientId = getClientId(endpoint, api)
|
||||||
const { client } = useApolloClient(clientId)
|
const { client } = useApolloClient(clientId)
|
||||||
|
const executeOnce = async () => {
|
||||||
const context = await getAuthContext(endpoint, api)
|
const context = await getAuthContext(endpoint, api)
|
||||||
|
|
||||||
const result = await client.query({
|
const result = await client.query({
|
||||||
query: document,
|
query: document,
|
||||||
variables,
|
variables,
|
||||||
@@ -93,6 +94,23 @@ export const useGraphQL = () => {
|
|||||||
return result.data as TResult
|
return result.data as TResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await executeOnce()
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error)
|
||||||
|
const isAuthContextFailure = message.includes('Invalid Compact JWS')
|
||||||
|
|| message.includes('Context creation failed')
|
||||||
|
|| message.includes('Received status code 500')
|
||||||
|
|
||||||
|
if (endpoint === 'team' && isAuthContextFailure) {
|
||||||
|
await refreshTokens()
|
||||||
|
return await executeOnce()
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const mutate = async <TResult, TVariables extends Record<string, unknown>>(
|
const mutate = async <TResult, TVariables extends Record<string, unknown>>(
|
||||||
document: TypedDocumentNode<TResult, TVariables>,
|
document: TypedDocumentNode<TResult, TVariables>,
|
||||||
variables: TVariables,
|
variables: TVariables,
|
||||||
@@ -101,8 +119,8 @@ export const useGraphQL = () => {
|
|||||||
): Promise<TResult> => {
|
): Promise<TResult> => {
|
||||||
const clientId = getClientId(endpoint, api)
|
const clientId = getClientId(endpoint, api)
|
||||||
const { client } = useApolloClient(clientId)
|
const { client } = useApolloClient(clientId)
|
||||||
|
const mutateOnce = async () => {
|
||||||
const context = await getAuthContext(endpoint, api)
|
const context = await getAuthContext(endpoint, api)
|
||||||
|
|
||||||
const result = await client.mutate({
|
const result = await client.mutate({
|
||||||
mutation: document,
|
mutation: document,
|
||||||
variables,
|
variables,
|
||||||
@@ -116,5 +134,22 @@ export const useGraphQL = () => {
|
|||||||
return result.data as TResult
|
return result.data as TResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await mutateOnce()
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error)
|
||||||
|
const isAuthContextFailure = message.includes('Invalid Compact JWS')
|
||||||
|
|| message.includes('Context creation failed')
|
||||||
|
|| message.includes('Received status code 500')
|
||||||
|
|
||||||
|
if (endpoint === 'team' && isAuthContextFailure) {
|
||||||
|
await refreshTokens()
|
||||||
|
return await mutateOnce()
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { execute, mutate }
|
return { execute, mutate }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,28 @@ export default defineNuxtPlugin(() => {
|
|||||||
const originalConsoleError = console.error
|
const originalConsoleError = console.error
|
||||||
|
|
||||||
console.error = (...args: unknown[]) => {
|
console.error = (...args: unknown[]) => {
|
||||||
const hasApolloDevtoolsWarning = args.some((arg) => {
|
const serializedArgs = args
|
||||||
if (typeof arg !== 'string') return false
|
.map((arg) => {
|
||||||
|
if (typeof arg === 'string') return arg
|
||||||
return (
|
if (arg instanceof Error) return `${arg.message}\n${arg.stack || ''}`
|
||||||
arg.includes('connectToDevTools') &&
|
try {
|
||||||
arg.includes('devtools.enabled')
|
return JSON.stringify(arg)
|
||||||
)
|
} catch {
|
||||||
|
return String(arg)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
.join(' ')
|
||||||
|
|
||||||
|
const hasApolloDevtoolsWarning = (
|
||||||
|
(
|
||||||
|
serializedArgs.includes('connectToDevTools')
|
||||||
|
&& serializedArgs.includes('devtools.enabled')
|
||||||
|
)
|
||||||
|
|| (
|
||||||
|
serializedArgs.includes('go.apollo.dev/c/err')
|
||||||
|
&& serializedArgs.includes('"message":104')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if (hasApolloDevtoolsWarning) {
|
if (hasApolloDevtoolsWarning) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
let token: string | null = null
|
let token: string | null = null
|
||||||
try {
|
try {
|
||||||
token = await client.getAccessToken('https://teams.optovia.ru', organizationId)
|
token = await client.getIdToken()
|
||||||
} catch {
|
} catch {
|
||||||
try {
|
try {
|
||||||
token = await client.getIdToken()
|
token = await client.getAccessToken('https://teams.optovia.ru', organizationId)
|
||||||
} catch {
|
} catch {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user