first commit
This commit is contained in:
41
frontend/src/auth/authStore.ts
Normal file
41
frontend/src/auth/authStore.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { useSyncExternalStore } from 'react'
|
||||
|
||||
/**
|
||||
* Модуль-стор access-токена JWT.
|
||||
*
|
||||
* Токен хранится ТОЛЬКО в памяти процесса (в переменной модуля), никогда —
|
||||
* в localStorage/sessionStorage: это защищает его от чтения через XSS.
|
||||
* Refresh-токен — httpOnly cookie, им управляет браузер, здесь он не виден
|
||||
* и не хранится.
|
||||
*
|
||||
* При перезагрузке страницы access-токен теряется — сессия восстанавливается
|
||||
* через silent-refresh в AuthProvider при старте приложения.
|
||||
*/
|
||||
|
||||
type Listener = () => void
|
||||
|
||||
let accessToken: string | null = null
|
||||
const listeners = new Set<Listener>()
|
||||
|
||||
function emitChange(): void {
|
||||
for (const listener of listeners) listener()
|
||||
}
|
||||
|
||||
export const authStore = {
|
||||
getAccessToken(): string | null {
|
||||
return accessToken
|
||||
},
|
||||
setAccessToken(token: string | null): void {
|
||||
accessToken = token
|
||||
emitChange()
|
||||
},
|
||||
subscribe(listener: Listener): () => void {
|
||||
listeners.add(listener)
|
||||
return () => listeners.delete(listener)
|
||||
},
|
||||
}
|
||||
|
||||
/** Реактивный доступ к текущему access-токену (для компонентов, которым это нужно). */
|
||||
export function useAccessToken(): string | null {
|
||||
return useSyncExternalStore(authStore.subscribe, authStore.getAccessToken)
|
||||
}
|
||||
Reference in New Issue
Block a user