secure-web-token 1.2.2 โ 1.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 +206 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,42 +1,228 @@
|
|
|
1
1
|
# ๐ Secure Web Token (SWT)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
SWT is a secure token system that encrypts payloads and binds them to devices. Unlike JWT, it prevents token reuse on other devices.
|
|
3
|
+
A **secure, device-bound authentication token system** for Node.js applications.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
- JWT can be decoded easily.
|
|
8
|
-
- Tokens can be used on any device if leaked.
|
|
9
|
-
- SWT encrypts payloads and binds tokens to device fingerprints.
|
|
5
|
+
---
|
|
10
6
|
|
|
11
|
-
##
|
|
7
|
+
## 1. About the Package
|
|
8
|
+
|
|
9
|
+
**Secure Web Token (SWT)** is a next-generation alternative to JWT, built for **security-critical applications** where token leakage, device hijacking, or session reuse must be prevented.
|
|
10
|
+
|
|
11
|
+
Unlike JWTs (which are only Base64 encoded), SWT uses **full encryption + server-side session binding**, making stolen tokens useless on other devices.
|
|
12
|
+
|
|
13
|
+
### Key Highlights โจ
|
|
14
|
+
|
|
15
|
+
- ๐ **AES-256-GCM encrypted payloads**
|
|
16
|
+
- ๐งท **Device-bound tokens (single-device login)**
|
|
17
|
+
- ๐ **Server-side session management**
|
|
18
|
+
- ๐ช **HttpOnly session cookies**
|
|
19
|
+
- โฑ **Expiry support (`iat`, `exp`)**
|
|
20
|
+
- โก Simple API: `sign()` and `verify()`
|
|
21
|
+
- ๐ง Memory store (Redis-ready design)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 2. What Problem Does It Solve?
|
|
26
|
+
|
|
27
|
+
### Problems with JWT โ
|
|
28
|
+
|
|
29
|
+
- Payloads are readable (Base64 โ encryption)
|
|
30
|
+
- Tokens can be reused on any device
|
|
31
|
+
- No native device binding
|
|
32
|
+
- Logout does not truly invalidate tokens
|
|
33
|
+
|
|
34
|
+
### How SWT Solves This โ
|
|
35
|
+
|
|
36
|
+
- Encrypts payload using **AES-256-GCM**
|
|
37
|
+
- Binds tokens to **server-managed device sessions**
|
|
38
|
+
- Prevents token reuse across devices
|
|
39
|
+
- Supports true logout via session revocation
|
|
40
|
+
- Sensitive identifiers never reach the browser
|
|
41
|
+
|
|
42
|
+
**Best suited for:**
|
|
43
|
+
- Admin panels
|
|
44
|
+
- SaaS dashboards
|
|
45
|
+
- Course platforms
|
|
46
|
+
- Internal tools
|
|
47
|
+
- High-security APIs
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 3. Available Functions
|
|
52
|
+
|
|
53
|
+
### `sign()`
|
|
54
|
+
|
|
55
|
+
Creates a **secure, encrypted token** and optionally registers a **server-side device session**.
|
|
56
|
+
|
|
57
|
+
### `verify()`
|
|
58
|
+
|
|
59
|
+
Validates and decrypts the token, ensuring the request comes from the **correct device and active session**.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 4. Boiler Code (Core Usage)
|
|
64
|
+
|
|
65
|
+
### `sign()` function
|
|
12
66
|
|
|
13
|
-
### sign()
|
|
14
|
-
Creates a secure token.
|
|
15
67
|
```ts
|
|
16
68
|
import { sign } from "secure-web-token";
|
|
17
|
-
|
|
18
|
-
|
|
69
|
+
|
|
70
|
+
const SECRET = "super-secret-key";
|
|
71
|
+
|
|
72
|
+
const { token, sessionId } = sign(
|
|
73
|
+
{ userId: 1, role: "admin" },
|
|
74
|
+
SECRET,
|
|
75
|
+
{
|
|
76
|
+
fingerprint: true,
|
|
77
|
+
store: "memory",
|
|
78
|
+
expiresIn: 3600,
|
|
79
|
+
}
|
|
80
|
+
);
|
|
19
81
|
```
|
|
20
82
|
|
|
21
|
-
|
|
22
|
-
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### `verify()` function
|
|
86
|
+
|
|
23
87
|
```ts
|
|
24
|
-
import { verify } from "secure-web-token";
|
|
25
|
-
|
|
26
|
-
|
|
88
|
+
import { verify, getStore } from "secure-web-token";
|
|
89
|
+
|
|
90
|
+
const store = getStore("memory");
|
|
91
|
+
const session = store.getSession(sessionId);
|
|
92
|
+
|
|
93
|
+
const payload = verify(token, SECRET, {
|
|
94
|
+
sessionId,
|
|
95
|
+
fingerprint: session.fingerprint,
|
|
96
|
+
store: "memory",
|
|
97
|
+
});
|
|
27
98
|
```
|
|
28
99
|
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 5. Demo App
|
|
103
|
+
|
|
104
|
+
### Backend (Express.js + Node.js)
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
const express = require("express");
|
|
108
|
+
const cookieParser = require("cookie-parser");
|
|
109
|
+
const cors = require("cors");
|
|
110
|
+
const { sign, verify, getStore } = require("secure-web-token");
|
|
111
|
+
|
|
112
|
+
const app = express();
|
|
113
|
+
app.use(cors({ origin: true, credentials: true }));
|
|
114
|
+
app.use(cookieParser());
|
|
115
|
+
|
|
116
|
+
const SECRET = "super-secret-key";
|
|
117
|
+
const store = getStore("memory");
|
|
118
|
+
|
|
119
|
+
app.post("/login", (req, res) => {
|
|
120
|
+
const user = { userId: 1, name: "Mintu" };
|
|
121
|
+
|
|
122
|
+
const { token, sessionId } = sign(user, SECRET, {
|
|
123
|
+
fingerprint: true,
|
|
124
|
+
store: "memory",
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
res.cookie("swt_session", sessionId, { httpOnly: true });
|
|
128
|
+
res.json({ token });
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
app.get("/profile", (req, res) => {
|
|
132
|
+
try {
|
|
133
|
+
const sessionId = req.cookies.swt_session;
|
|
134
|
+
const session = store.getSession(sessionId);
|
|
135
|
+
const token = req.headers.authorization?.split(" ")[1];
|
|
136
|
+
|
|
137
|
+
const payload = verify(token, SECRET, {
|
|
138
|
+
sessionId,
|
|
139
|
+
fingerprint: session.fingerprint,
|
|
140
|
+
store: "memory",
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
res.json({ user: payload.data });
|
|
144
|
+
} catch {
|
|
145
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
app.listen(4000);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### Frontend (React.js)
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
function App() {
|
|
158
|
+
const login = async () => {
|
|
159
|
+
const res = await fetch("http://localhost:4000/login", {
|
|
160
|
+
method: "POST",
|
|
161
|
+
credentials: "include",
|
|
162
|
+
});
|
|
163
|
+
const data = await res.json();
|
|
164
|
+
localStorage.setItem("token", data.token);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const profile = async () => {
|
|
168
|
+
const token = localStorage.getItem("token");
|
|
169
|
+
const res = await fetch("http://localhost:4000/profile", {
|
|
170
|
+
credentials: "include",
|
|
171
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
172
|
+
});
|
|
173
|
+
console.log(await res.json());
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<>
|
|
178
|
+
<button onClick={login}>Login</button>
|
|
179
|
+
<button onClick={profile}>View Profile</button>
|
|
180
|
+
</>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export default App;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 6. Payload Structure
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"data": {
|
|
194
|
+
"userId": 1,
|
|
195
|
+
"role": "admin"
|
|
196
|
+
},
|
|
197
|
+
"iat": 1768368114,
|
|
198
|
+
"exp": 1768369014,
|
|
199
|
+
"fp": "device-id"
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
29
205
|
## Installation
|
|
206
|
+
|
|
30
207
|
```bash
|
|
31
208
|
npm install secure-web-token
|
|
32
209
|
```
|
|
33
210
|
|
|
211
|
+
---
|
|
212
|
+
|
|
34
213
|
## Importing
|
|
214
|
+
|
|
35
215
|
```ts
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
216
|
+
// ESM
|
|
217
|
+
import { sign, verify, getStore } from "secure-web-token";
|
|
218
|
+
|
|
219
|
+
// CommonJS
|
|
220
|
+
const { sign, verify, getStore } = require("secure-web-token");
|
|
39
221
|
```
|
|
40
222
|
|
|
41
|
-
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Final Note
|
|
42
226
|
|
|
227
|
+
If you need **encrypted tokens**, **single-device login**, and **true logout**,
|
|
228
|
+
**Secure Web Token (SWT)** is built for you.
|