react-session.manager.sk 2.2.2 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,32 +1,187 @@
|
|
|
1
1
|
# react-session.manager.sk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A React context provider for managing token-based user sessions in applications backed by a Flask API. It handles JWT token storage and refresh, device fingerprinting, app version enforcement, cross-tab session synchronisation, and user-facing toast notifications — all from a single wrapper component.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Features](#features)
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Props](#props)
|
|
13
|
+
- [Context API](#context-api)
|
|
14
|
+
- [How It Works](#how-it-works)
|
|
15
|
+
- [Token Management](#token-management)
|
|
16
|
+
- [Device Fingerprinting](#device-fingerprinting)
|
|
17
|
+
- [Version Protection](#version-protection)
|
|
18
|
+
- [Axios Interceptors](#axios-interceptors)
|
|
19
|
+
- [Toast Notifications](#toast-notifications)
|
|
20
|
+
- [Dependencies](#dependencies)
|
|
21
|
+
- [License](#license)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Automatic token refresh** on a configurable interval
|
|
28
|
+
- **Persistent sessions** via `localStorage` (remember me) or `sessionStorage`
|
|
29
|
+
- **Cross-tab synchronisation** — a login in one tab is picked up by all open tabs
|
|
30
|
+
- **Device fingerprinting** — generates a stable `deviceUID` and attaches it to every request header
|
|
31
|
+
- **App version enforcement** — detects when the server requires a newer client version and prompts the user to update
|
|
32
|
+
- **Axios interceptor** — centrally handles `455` (session expired) and `426` (upgrade required) status codes
|
|
33
|
+
- **Toast notifications** via [react-toastify](https://fkhadra.github.io/react-toastify/) for session, connection, and version events
|
|
34
|
+
- **Role-based access** helper via the `hasRole` context function
|
|
35
|
+
|
|
36
|
+
---
|
|
4
37
|
|
|
5
38
|
## Installation
|
|
6
39
|
|
|
7
|
-
```
|
|
40
|
+
```bash
|
|
8
41
|
npm install react-session.manager.sk
|
|
9
42
|
```
|
|
10
43
|
|
|
11
|
-
|
|
44
|
+
---
|
|
12
45
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
Wrap your application with `SessionManagerProvider` and pass the required props:
|
|
49
|
+
|
|
50
|
+
```jsx
|
|
51
|
+
import SessionManagerProvider from "react-session.manager.sk";
|
|
52
|
+
import axiosAuth from "./axiosAuth"; // your pre-configured axios instance
|
|
53
|
+
import { whoAmI, refreshToken } from "./api";
|
|
54
|
+
|
|
55
|
+
function Root() {
|
|
56
|
+
return (
|
|
57
|
+
<SessionManagerProvider
|
|
58
|
+
userLoader={whoAmI}
|
|
59
|
+
refreshToken={refreshToken}
|
|
60
|
+
AuthenticatedAxiosObject={axiosAuth}
|
|
61
|
+
refreshTimer={15}
|
|
62
|
+
dataRefresh={30}
|
|
63
|
+
appVersion="1.0.0"
|
|
64
|
+
toastOptions={{ position: "top-right" }}
|
|
29
65
|
>
|
|
30
|
-
|
|
31
|
-
</SessionManagerProvider>
|
|
66
|
+
<App />
|
|
67
|
+
</SessionManagerProvider>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
32
70
|
```
|
|
71
|
+
|
|
72
|
+
Consume the session context anywhere inside your app:
|
|
73
|
+
|
|
74
|
+
```jsx
|
|
75
|
+
import { useContext } from "react";
|
|
76
|
+
import { SessionManager } from "react-session.manager.sk";
|
|
77
|
+
|
|
78
|
+
function Profile() {
|
|
79
|
+
const { isLoggedIn, userInfo, isAdmin, hasRole, setLoggedin } =
|
|
80
|
+
useContext(SessionManager);
|
|
81
|
+
|
|
82
|
+
if (!isLoggedIn) return <p>Please log in.</p>;
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div>
|
|
86
|
+
<p>Welcome, {userInfo?.name}</p>
|
|
87
|
+
{isAdmin && <p>You are an administrator.</p>}
|
|
88
|
+
{hasRole(["editor"]) && <p>You have editor access.</p>}
|
|
89
|
+
<button onClick={() => setLoggedin(false)}>Log out</button>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Props
|
|
98
|
+
|
|
99
|
+
| Prop | Type | Required | Description |
|
|
100
|
+
|---|---|---|---|
|
|
101
|
+
| `AuthenticatedAxiosObject` | `AxiosInstance` | ✅ | An axios instance. The provider attaches `Authorization`, `deviceUID`, and `appVersion` headers to it automatically. |
|
|
102
|
+
| `userLoader` | `() => Promise` | ✅ | Async function that fetches the current user. Must resolve to `{ data: { logged_in, is_admin, Info } }`. |
|
|
103
|
+
| `refreshToken` | `() => Promise` | ✅ | Async function that refreshes the JWT. Must resolve to `{ access_token, refreshed? }`. |
|
|
104
|
+
| `refreshTimer` | `number` | | Minutes between automatic token refresh attempts. Defaults to `60`. |
|
|
105
|
+
| `dataRefresh` | `number` | | Minutes between automatic user-data refresh calls. Defaults to `60`. |
|
|
106
|
+
| `appVersion` | `string` | | Semver string of the current client build (e.g. `"1.2.3"`). Used for version comparison against server requirements. |
|
|
107
|
+
| `toastOptions` | `object` | | Any valid [react-toastify `ToastContainer` props](https://fkhadra.github.io/react-toastify/api/toast-container) to customise notification behaviour. |
|
|
108
|
+
| `children` | `ReactNode` | ✅ | Your application tree. |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Context API
|
|
113
|
+
|
|
114
|
+
Import the `SessionManager` context object and read it with `useContext`:
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
import { SessionManager } from "react-session.manager.sk";
|
|
118
|
+
const session = useContext(SessionManager);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| Property | Type | Description |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `isLoggedIn` | `boolean` | Whether the current user is authenticated. |
|
|
124
|
+
| `loadingUser` | `boolean` | `true` while the initial `userLoader` call is in flight. |
|
|
125
|
+
| `userInfo` | `object` | The `Info` object returned by `userLoader`. Shape is determined by your API. |
|
|
126
|
+
| `isAdmin` | `boolean` | Mirrors `is_admin` from the `userLoader` response. |
|
|
127
|
+
| `header` | `string` | The current `Authorization` header value (e.g. `"Bearer <token>"`). |
|
|
128
|
+
| `deviceUID` | `string` | The stable device fingerprint stored in `localStorage`. |
|
|
129
|
+
| `refreshData` | `boolean` | Flag that is set to `true` when a periodic data refresh is due. |
|
|
130
|
+
| `setHeader` | `(token: string) => void` | Manually set the `Authorization` header (e.g. after a successful login). |
|
|
131
|
+
| `setLoggedin` | `(status: boolean) => void` | Manually update the logged-in state (e.g. after logout). |
|
|
132
|
+
| `setRefreshData` | `(status: boolean) => void` | Manually trigger or clear a data refresh cycle. |
|
|
133
|
+
| `hasRole` | `(roles: string[]) => boolean` | Returns `true` if `userInfo.roles` contains any of the provided role strings. |
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## How It Works
|
|
138
|
+
|
|
139
|
+
### Token Management
|
|
140
|
+
|
|
141
|
+
On mount the provider checks `localStorage` and `sessionStorage` for a stored `Authorization` token. If found it immediately calls `refreshToken` to validate/rotate it, then re-stores the result. A `setInterval` continues to call `refreshToken` every `refreshTimer` minutes while the user is logged in.
|
|
142
|
+
|
|
143
|
+
Storing a token in `localStorage` means the session persists across browser restarts ("remember me"). `sessionStorage` tokens expire when the tab is closed.
|
|
144
|
+
|
|
145
|
+
### Device Fingerprinting
|
|
146
|
+
|
|
147
|
+
On first load the provider uses [ClientJS](https://clientjs.org/) to generate a browser fingerprint. This value is persisted to `localStorage` as `deviceUID` and is automatically added to every outgoing request as a custom `deviceUID` header. Subsequent loads reuse the cached value.
|
|
148
|
+
|
|
149
|
+
### Version Protection
|
|
150
|
+
|
|
151
|
+
Every request includes the current `appVersion` header. If the server responds with HTTP `426 Upgrade Required` the provider:
|
|
152
|
+
|
|
153
|
+
1. Stores the minimum required version in `sessionStorage`.
|
|
154
|
+
2. Reloads the page up to twice to pick up the latest build from the cache.
|
|
155
|
+
3. If reloading does not satisfy the version requirement, shows a warning toast asking the user to wait and reload manually.
|
|
156
|
+
|
|
157
|
+
After a successful reload, if the new client version satisfies the server's requirement a success toast is shown confirming the update.
|
|
158
|
+
|
|
159
|
+
### Axios Interceptors
|
|
160
|
+
|
|
161
|
+
The provider registers a response interceptor on `AuthenticatedAxiosObject`:
|
|
162
|
+
|
|
163
|
+
| Status | Behaviour |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `455` | Session is no longer valid. Clears the auth state and shows an info toast prompting the user to log in again. |
|
|
166
|
+
| `426` | App version is too old — triggers the version protection flow described above. |
|
|
167
|
+
| No response / timeout | Shows an error toast indicating the server is unreachable or the request timed out. |
|
|
168
|
+
| `ERR_CANCELED` | Silently ignored (e.g. aborted requests). |
|
|
169
|
+
|
|
170
|
+
### Toast Notifications
|
|
171
|
+
|
|
172
|
+
All notifications are rendered via a `<ToastContainer>` mounted inside the provider. You can customise its behaviour with the `toastOptions` prop (accepts any props that `<ToastContainer>` accepts). Custom CSS classes can be passed through `toastClassName`.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Dependencies
|
|
177
|
+
|
|
178
|
+
| Package | Role |
|
|
179
|
+
|---|---|
|
|
180
|
+
| [react-toastify](https://www.npmjs.com/package/react-toastify) | In-app toast notifications |
|
|
181
|
+
| [clientjs](https://www.npmjs.com/package/clientjs) | Browser fingerprinting for `deviceUID` |
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
ISC © [Skulldorom](https://github.com/Skulldorom)
|