diff --git a/backend/src/auth/oidc.ts b/backend/src/auth/oidc.ts index 6e7508e..0ef0a3f 100644 --- a/backend/src/auth/oidc.ts +++ b/backend/src/auth/oidc.ts @@ -170,10 +170,27 @@ export async function verifyToken(tokenSet: TokenSet): Promise { } } +// Cache userinfo responses to avoid hitting the OIDC provider on every request. +// Entries expire after 5 minutes. The cache is keyed by the raw access token. +const userinfoCache = new Map(); +const USERINFO_CACHE_TTL_MS = 5 * 60 * 1000; + export async function verifyBearerToken(accessToken: string): Promise { + const cached = userinfoCache.get(accessToken); + if (cached && Date.now() < cached.expiresAt) { + return cached.user; + } + const client = getOIDCClient(); - const userInfo = await client.userinfo(accessToken); + let userInfo: Awaited>; + try { + userInfo = await client.userinfo(accessToken); + } catch (err) { + // Remove any stale cache entry for this token + userinfoCache.delete(accessToken); + throw err; + } const id = String(userInfo.sub); const username = String(userInfo.preferred_username || userInfo.name || id); @@ -184,5 +201,7 @@ export async function verifyBearerToken(accessToken: string): Promise String { "/api/clients/\(id)" } + static let clients = "/clients" + static func client(id: String) -> String { "/clients/\(id)" } // Projects - static let projects = "/api/projects" - static func project(id: String) -> String { "/api/projects/\(id)" } + static let projects = "/projects" + static func project(id: String) -> String { "/projects/\(id)" } // Time Entries - static let timeEntries = "/api/time-entries" - static let timeEntriesStatistics = "/api/time-entries/statistics" - static func timeEntry(id: String) -> String { "/api/time-entries/\(id)" } + static let timeEntries = "/time-entries" + static let timeEntriesStatistics = "/time-entries/statistics" + static func timeEntry(id: String) -> String { "/time-entries/\(id)" } // Timer - static let timer = "/api/timer" - static let timerStart = "/api/timer/start" - static let timerStop = "/api/timer/stop" + static let timer = "/timer" + static let timerStart = "/timer/start" + static let timerStop = "/timer/stop" } struct APIEndpoints {