import axios from 'axios'; import { dev } from '$app/environment'; import { goto } from '$app/navigation'; import { get } from 'svelte/store'; import { persistentSettings, clearLoginState } from '$lib/persistent_store'; if (dev) { axios.defaults.baseURL = "http://localhost:8000/api/v1" } else { axios.defaults.baseURL = "/api/v1" } // Get access token from local storage axios.defaults.headers.common['Authorization'] = "Bearer " + get(persistentSettings).accessToken; function createTokenRefreshInterceptor() { const interceptor = axios.interceptors.response.use( (response) => response, (error) => { // Reject promise if usual error if (error.response.status !== 401) { return Promise.reject(error); } /* * When response code is 401, try to refresh the token. * Eject the interceptor so it doesn't loop in case * token refresh causes the 401 response. * * Must be re-attached later on or the token refresh will only happen once */ axios.interceptors.response.eject(interceptor); return axios .post("/auth/refresh", { refresh_token: get(persistentSettings).refreshToken, }) .then((response) => { // Save new tokens persistentSettings.update(settings => { settings.accessToken = response.data.access_token settings.refreshToken = response.data.refresh_token; return settings; }) // Update access token const authHeader = "Bearer " + response.data.access_token; axios.defaults.headers.common['Authorization'] = authHeader; error.response.config.headers["Authorization"] = authHeader; // Retry initial request with new token return axios(error.response.config); }) .catch((retryError) => { // Retry failed, clean up and reject the promise clearLoginState(); axios.defaults.headers.common['Authorization'] = ""; goto('/login?reauth') return Promise.reject(retryError); }) .finally(createTokenRefreshInterceptor); // Re-attach interceptor for future requests } ); } createTokenRefreshInterceptor(); export const login = async function(email: string, password: string) { await axios .post('/auth/login', { email, password, }) .then((response) => { persistentSettings.update(settings => { settings.loggedIn = true settings.accessToken = response.data.access_token settings.refreshToken = response.data.refresh_token return settings; }) axios.defaults.headers.common['Authorization'] = 'Bearer ' + response.data.access_token axios.get('/me').then((response) => { persistentSettings.update(settings => { settings.email = response.data.email settings.friendlyName = response.data.friendly_name settings.role = response.data.role return settings; }) }) goto('/') return Promise.resolve(); }) .catch((error) => { return Promise.reject(error); }) } export const logout = function() { axios .post('/auth/logout') .then(() => { clearLoginState(); axios.defaults.headers.common['Authorization'] = ""; goto('/login?logout') }); } export default axios;