42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
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)
|
||
}
|