[FA-misc] Fixes refresh token usage hopefully
All checks were successful
CI / build-backend (pull_request) Successful in 1m34s
CI / build-frontend (pull_request) Successful in 39s

This commit is contained in:
gamer147
2025-12-09 19:23:11 -05:00
parent e70c39ea75
commit d109db2155
5 changed files with 55 additions and 12 deletions

View File

@@ -117,3 +117,14 @@ export async function logout() {
user.set(null);
}
}
export async function refreshToken(): Promise<User | null> {
if (!userManager) return null;
try {
const newUser = await userManager.signinSilent();
return newUser;
} catch (e) {
console.error('Token refresh failed:', e);
return null;
}
}

View File

@@ -4,7 +4,7 @@ const authority = import.meta.env.PUBLIC_OIDC_AUTHORITY;
const clientId = import.meta.env.PUBLIC_OIDC_CLIENT_ID;
const redirectUri = import.meta.env.PUBLIC_OIDC_REDIRECT_URI;
const postLogoutRedirectUri = import.meta.env.PUBLIC_OIDC_POST_LOGOUT_REDIRECT_URI ?? redirectUri;
const scope = import.meta.env.PUBLIC_OIDC_SCOPE ?? 'openid profile email';
const scope = import.meta.env.PUBLIC_OIDC_SCOPE ?? 'openid profile email offline_access';
export const isOidcConfigured =
Boolean(authority) && Boolean(clientId) && Boolean(redirectUri);
@@ -20,7 +20,7 @@ function buildSettings(): UserManagerSettings | null {
response_type: 'code',
scope,
loadUserInfo: true,
automaticSilentRenew: true,
automaticSilentRenew: false, // We handle refresh reactively via authExchange
userStore:
typeof window !== 'undefined'
? new WebStorageStateStore({ store: window.localStorage })

View File

@@ -1,19 +1,36 @@
import { Client, cacheExchange, fetchExchange } from '@urql/core';
import { authExchange } from '@urql/exchange-auth';
import { get } from 'svelte/store';
import { user } from '../auth/authStore';
import { user, refreshToken } from '../auth/authStore';
export function createClient() {
return new Client({
url: import.meta.env.PUBLIC_GRAPHQL_URI,
exchanges: [cacheExchange, fetchExchange],
fetchOptions: () => {
const currentUser = get(user);
return {
headers: currentUser?.access_token
? { Authorization: `Bearer ${currentUser.access_token}` }
: {},
};
},
exchanges: [
cacheExchange,
authExchange(async (utils) => ({
addAuthToOperation(operation) {
const currentUser = get(user);
if (!currentUser?.access_token) return operation;
return utils.appendHeaders(operation, {
Authorization: `Bearer ${currentUser.access_token}`,
});
},
didAuthError(error) {
return error.graphQLErrors?.some(
(e) => e.extensions?.code === 'AUTH_NOT_AUTHENTICATED'
);
},
async refreshAuth() {
const newUser = await refreshToken();
if (!newUser) {
// Refresh failed, redirect to login
window.location.href = '/';
}
},
})),
fetchExchange,
],
});
}