- {key.label}
+ {sanitizeText(key.label)}
diff --git a/src/services/api.ts b/src/services/api.ts
index 8993a30..1d0937a 100644
--- a/src/services/api.ts
+++ b/src/services/api.ts
@@ -8,10 +8,25 @@ export const api = axios.create({
},
})
+const TOKEN_STORAGE_KEY = 'stepfi-user'
+
+function getStoredTokens(): { accessToken?: string; refreshToken?: string } {
+ try {
+ const raw = localStorage.getItem(TOKEN_STORAGE_KEY)
+ if (!raw) return {}
+ const parsed = JSON.parse(raw)
+ const state = parsed?.state
+ if (!state) return {}
+ return { accessToken: state.accessToken, refreshToken: state.refreshToken }
+ } catch {
+ return {}
+ }
+}
+
api.interceptors.request.use((config) => {
- const token = localStorage.getItem('accessToken')
- if (token) {
- config.headers.Authorization = `Bearer ${token}`
+ const { accessToken } = getStoredTokens()
+ if (accessToken) {
+ config.headers.Authorization = `Bearer ${accessToken}`
}
return config
})
@@ -20,8 +35,7 @@ api.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
- localStorage.removeItem('accessToken')
- localStorage.removeItem('refreshToken')
+ localStorage.removeItem(TOKEN_STORAGE_KEY)
window.location.href = '/'
}
return Promise.reject(error)
diff --git a/src/stores/user.store.ts b/src/stores/user.store.ts
index 85fabc9..14f1f9c 100644
--- a/src/stores/user.store.ts
+++ b/src/stores/user.store.ts
@@ -16,13 +16,9 @@ export const useUserStore = create()(
refreshToken: '',
isAuthenticated: false,
setTokens: (accessToken, refreshToken) => {
- localStorage.setItem('accessToken', accessToken)
- localStorage.setItem('refreshToken', refreshToken)
set({ accessToken, refreshToken, isAuthenticated: true })
},
clearTokens: () => {
- localStorage.removeItem('accessToken')
- localStorage.removeItem('refreshToken')
set({
accessToken: '',
refreshToken: '',
diff --git a/vercel.json b/vercel.json
index 170b3f6..af092bd 100644
--- a/vercel.json
+++ b/vercel.json
@@ -2,5 +2,45 @@
"framework": "vite",
"buildCommand": "npm run build",
"outputDirectory": "dist",
- "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
+ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }],
+ "headers": [
+ {
+ "source": "/(.*)",
+ "headers": [
+ {
+ "key": "Content-Security-Policy",
+ "value": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://stepfi-api.onrender.com; font-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'"
+ },
+ {
+ "key": "X-Frame-Options",
+ "value": "DENY"
+ },
+ {
+ "key": "X-Content-Type-Options",
+ "value": "nosniff"
+ },
+ {
+ "key": "Referrer-Policy",
+ "value": "strict-origin-when-cross-origin"
+ },
+ {
+ "key": "Permissions-Policy",
+ "value": "camera=(), microphone=(), geolocation=()"
+ },
+ {
+ "key": "Strict-Transport-Security",
+ "value": "max-age=31536000; includeSubDomains; preload"
+ }
+ ]
+ },
+ {
+ "source": "/assets/(.*)",
+ "headers": [
+ {
+ "key": "Cache-Control",
+ "value": "public, max-age=31536000, immutable"
+ }
+ ]
+ }
+ ]
}