auth fixes
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { Config, ConfigCreate, Project, ProjectCreate, ProjectUpdate, Repository, RepositoryConnection, RepositoryConnectionCreate, RepositoryCreate, Secret, SecretCreate, ToolDefinition, ToolInstance, User } from '../types/api.ts'
|
||||
import { getToken, clearToken } from '../auth/oidc'
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
|
||||
|
||||
@@ -13,8 +14,49 @@ export class ApiError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
function getAuthToken(): string | null {
|
||||
return localStorage.getItem('access_token')
|
||||
let isRefreshing = false
|
||||
let refreshPromise: Promise<string | null> | null = null
|
||||
|
||||
async function refreshToken(): Promise<string | null> {
|
||||
if (isRefreshing && refreshPromise) {
|
||||
return refreshPromise
|
||||
}
|
||||
|
||||
isRefreshing = true
|
||||
refreshPromise = (async () => {
|
||||
try {
|
||||
const token = getToken()
|
||||
if (!token) return null
|
||||
|
||||
const response = await fetch(`${API_URL}/api/v1/auth/refresh`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
clearToken()
|
||||
return null
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
if (data.access_token) {
|
||||
localStorage.setItem('access_token', data.access_token)
|
||||
return data.access_token
|
||||
}
|
||||
return null
|
||||
} catch {
|
||||
clearToken()
|
||||
return null
|
||||
} finally {
|
||||
isRefreshing = false
|
||||
refreshPromise = null
|
||||
}
|
||||
})()
|
||||
|
||||
return refreshPromise
|
||||
}
|
||||
|
||||
async function fetchWithAuth(
|
||||
@@ -22,7 +64,7 @@ async function fetchWithAuth(
|
||||
options: RequestInit = {}
|
||||
): Promise<Response> {
|
||||
const url = `${API_URL}/api/v1${endpoint}`
|
||||
const token = getAuthToken()
|
||||
const token = getToken()
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -46,6 +88,22 @@ async function fetchWithAuth(
|
||||
console.log(`[API] ${response.status} ${response.statusText}`)
|
||||
}
|
||||
|
||||
if (response.status === 401 && token) {
|
||||
const newToken = await refreshToken()
|
||||
if (newToken) {
|
||||
headers['Authorization'] = `Bearer ${newToken}`
|
||||
const retryResponse = await fetch(url, {
|
||||
...options,
|
||||
headers,
|
||||
})
|
||||
if (!retryResponse.ok) {
|
||||
const data = await retryResponse.json().catch(() => undefined)
|
||||
throw new ApiError(retryResponse.status, retryResponse.statusText, data)
|
||||
}
|
||||
return retryResponse
|
||||
}
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json().catch(() => undefined)
|
||||
throw new ApiError(response.status, response.statusText, data)
|
||||
|
||||
Reference in New Issue
Block a user