react-session.manager.sk 2.2.3 → 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.
Files changed (2) hide show
  1. package/README.md +176 -21
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,32 +1,187 @@
1
1
  # react-session.manager.sk
2
2
 
3
- This is used in conjunction with a custom flask app in order to manage user sessions.
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
- ## Usage
44
+ ---
12
45
 
13
- ```
14
- <SessionManagerProvider
15
- userLoader={who} // function to get user data
16
- refreshToken={refresh} // function to refresh token
17
- AuthenticatedAxiosObject={axiosAuth} // axios object with token
18
- refreshTimer={config.server.tokenRefreshTimer} // time to refresh token
19
- dataRefresh={config.server.dataRefreshTimer} // time to refresh data
20
- appVersion={config.appVersion} // app version
21
- toastOptions={{
22
- icon: true,
23
- toastClassName: config.theme.Notification.ThemeNotifications
24
- ? config.theme.Notification.MaterialNotifications
25
- ? "custToast materialToast"
26
- : "custToast"
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
- <App />
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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-session.manager.sk",
3
- "version": "2.2.3",
3
+ "version": "2.2.4",
4
4
  "description": "A react component used to manage token sessions with flask backend",
5
5
  "main": "./dist/index.js",
6
6
  "files": [