secure-web-token 1.2.1 → 1.2.3
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 +152 -70
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,102 +2,99 @@
|
|
|
2
2
|
|
|
3
3
|
## 1. About the Package
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Secure Web Token (SWT) is a **next-generation authentication token system** designed for security-critical applications. Unlike traditional JWTs, SWT operates on a **Device Registration and Server-Side Session Model**, ensuring that tokens are intrinsically tied to specific devices and sessions.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Key highlights:
|
|
8
|
+
|
|
9
|
+
- **AES-256-GCM encryption**: Ensures payloads are fully encrypted, not just Base64 encoded.
|
|
10
|
+
- **Device fingerprint binding**: Tokens are locked to a device (or session) to prevent unauthorized reuse.
|
|
11
|
+
- **Server-side session store**: Device IDs and sessions are managed securely on the backend, never exposed to the browser.
|
|
12
|
+
- **Simple developer experience**: Easily integrate into Node.js applications with `sign` and `verify` functions.
|
|
13
|
+
|
|
14
|
+
SWT is ideal for **mission-critical applications** where security, controlled access, and device binding are required.
|
|
8
15
|
|
|
9
16
|
---
|
|
10
17
|
|
|
11
18
|
## 2. What Problem Does It Solve?
|
|
12
19
|
|
|
13
|
-
Traditional
|
|
20
|
+
Traditional JWTs have several limitations:
|
|
14
21
|
|
|
15
|
-
- JWT payloads are
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
22
|
+
- JWT payloads are only Base64 encoded, not encrypted. Anyone can decode them.
|
|
23
|
+
- If a token leaks, it can be reused from any device.
|
|
24
|
+
- No built-in mechanism to restrict tokens to specific devices.
|
|
25
|
+
- Cannot safely enforce single-device login without additional server logic.
|
|
19
26
|
|
|
20
|
-
**
|
|
27
|
+
**SWT addresses these issues by:**
|
|
21
28
|
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
29
|
+
- Fully encrypting token payloads using AES-256-GCM.
|
|
30
|
+
- Binding tokens to **device fingerprints** managed on the backend.
|
|
31
|
+
- Preventing token reuse from unauthorized devices.
|
|
32
|
+
- Supporting auto-generated device IDs for added security.
|
|
33
|
+
- Managing sessions server-side, so sensitive identifiers never reach the browser.
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
Use cases:
|
|
36
|
+
|
|
37
|
+
- Course platforms with anti-piracy requirements
|
|
30
38
|
- SaaS dashboards
|
|
31
|
-
- Admin panels
|
|
32
|
-
-
|
|
39
|
+
- Admin panels with restricted access
|
|
40
|
+
- Any system requiring **device-bound authentication**
|
|
33
41
|
|
|
34
42
|
---
|
|
35
43
|
|
|
36
44
|
## 3. Available Functions
|
|
37
45
|
|
|
38
46
|
### `sign()`
|
|
39
|
-
Creates an encrypted and signed token.
|
|
40
|
-
|
|
41
|
-
**Features:**
|
|
42
|
-
- Encrypts payload
|
|
43
|
-
- Adds expiry (`iat`, `exp`)
|
|
44
|
-
- Supports device fingerprint binding
|
|
45
|
-
- Can auto-generate a device ID
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
### `verify()`
|
|
50
|
-
Verifies and decrypts a token.
|
|
51
47
|
|
|
52
|
-
**
|
|
53
|
-
- Token format
|
|
54
|
-
- Signature integrity
|
|
55
|
-
- Token expiry
|
|
56
|
-
- Device fingerprint validation
|
|
57
|
-
|
|
58
|
-
---
|
|
48
|
+
Creates a **secure, encrypted token**.
|
|
59
49
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
### Installation
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
npm install secure-web-token
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
### Import
|
|
71
|
-
|
|
72
|
-
```js
|
|
73
|
-
const { sign, verify } = require("secure-web-token");
|
|
74
|
-
```
|
|
50
|
+
**Features:**
|
|
75
51
|
|
|
76
|
-
|
|
52
|
+
- Encrypts the payload completely
|
|
53
|
+
- Adds `iat` (issued at) and `exp` (expiry) timestamps
|
|
54
|
+
- Supports **device fingerprint binding**
|
|
55
|
+
- Can auto-generate a device ID
|
|
56
|
+
- Optional server-side session management
|
|
77
57
|
|
|
78
|
-
|
|
58
|
+
```ts
|
|
59
|
+
import { sign } from "secure-web-token";
|
|
79
60
|
|
|
80
|
-
```js
|
|
81
61
|
const secret = "my-super-secret";
|
|
82
62
|
|
|
83
|
-
|
|
63
|
+
// Auto device registration + server session
|
|
64
|
+
const { token, sessionId } = sign(
|
|
84
65
|
{ userId: 1, role: "admin" },
|
|
85
66
|
secret,
|
|
86
|
-
{ fingerprint: true }
|
|
67
|
+
{ fingerprint: true, store: "memory", expiresIn: 3600 }
|
|
87
68
|
);
|
|
88
69
|
|
|
89
70
|
console.log("TOKEN:", token);
|
|
90
|
-
console.log("
|
|
71
|
+
console.log("SESSION ID (internal, not exposed to browser):", sessionId);
|
|
91
72
|
```
|
|
92
73
|
|
|
93
74
|
---
|
|
94
75
|
|
|
95
|
-
###
|
|
76
|
+
### `verify()`
|
|
77
|
+
|
|
78
|
+
Verifies and decrypts a token.
|
|
79
|
+
|
|
80
|
+
**Checks performed:**
|
|
81
|
+
|
|
82
|
+
- Token format integrity
|
|
83
|
+
- Signature correctness
|
|
84
|
+
- Expiry check
|
|
85
|
+
- Device fingerprint / session validation
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { verify, getStore } from "secure-web-token";
|
|
89
|
+
|
|
90
|
+
// Get the store instance (MemoryStore / Redis)
|
|
91
|
+
const store = getStore("memory");
|
|
96
92
|
|
|
97
|
-
```js
|
|
98
93
|
try {
|
|
99
94
|
const payload = verify(token, secret, {
|
|
100
|
-
|
|
95
|
+
sessionId, // Server-side session ID
|
|
96
|
+
fingerprint: "abc", // Device fingerprint stored internally
|
|
97
|
+
store: "memory" // Must match the store used during sign()
|
|
101
98
|
});
|
|
102
99
|
|
|
103
100
|
console.log("USER DATA:", payload.data);
|
|
@@ -108,22 +105,107 @@ try {
|
|
|
108
105
|
|
|
109
106
|
---
|
|
110
107
|
|
|
111
|
-
##
|
|
108
|
+
## 4. Server-Side Session Model (Recommended)
|
|
109
|
+
|
|
110
|
+
> In SWT v2+, **device verification is entirely server-side**.\
|
|
111
|
+
> This prevents attackers from copying tokens and device IDs from one browser to another.
|
|
112
|
+
|
|
113
|
+
**Workflow:**
|
|
114
|
+
|
|
115
|
+
1. **User logs in** → `sign()` generates token + server session
|
|
116
|
+
2. **Server stores session** internally (deviceId, fingerprint)
|
|
117
|
+
3. **Browser receives token + HttpOnly cookie** → cannot read device ID
|
|
118
|
+
4. **verify()**** checks session + fingerprint internally** → ensures single-device access
|
|
119
|
+
5. **Session revocation** automatically prevents token reuse
|
|
120
|
+
|
|
121
|
+
**Example Express backend:**
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import express from "express";
|
|
125
|
+
import cookieParser from "cookie-parser";
|
|
126
|
+
import cors from "cors";
|
|
127
|
+
import { sign, verify, getStore } from "secure-web-token";
|
|
128
|
+
|
|
129
|
+
const app = express();
|
|
130
|
+
app.use(cors({ origin: true, credentials: true }));
|
|
131
|
+
app.use(cookieParser());
|
|
132
|
+
app.use(express.json());
|
|
133
|
+
|
|
134
|
+
const SECRET = "super-secret-key";
|
|
135
|
+
const store = getStore("memory");
|
|
136
|
+
|
|
137
|
+
// LOGIN
|
|
138
|
+
app.post("/login", (req, res) => {
|
|
139
|
+
const user = { userId: 1, name: "John" };
|
|
140
|
+
const { token, sessionId } = sign(user, SECRET, { fingerprint: true, store: "memory", expiresIn: 3600 });
|
|
141
|
+
|
|
142
|
+
res.cookie("swt_session", sessionId, { httpOnly: true, sameSite: "strict", secure: false });
|
|
143
|
+
res.json({ token });
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// PROFILE
|
|
147
|
+
app.get("/profile", (req, res) => {
|
|
148
|
+
try {
|
|
149
|
+
const sessionId = req.cookies.swt_session;
|
|
150
|
+
const session = store.getSession(sessionId);
|
|
151
|
+
if (!session) throw new Error("Unauthorized or session expired");
|
|
152
|
+
|
|
153
|
+
const token = req.headers.authorization?.split(" ")[1];
|
|
154
|
+
const payload = verify(token, SECRET, { sessionId, fingerprint: session.fingerprint, store: "memory" });
|
|
155
|
+
res.json({ user: payload.data });
|
|
156
|
+
} catch (err) {
|
|
157
|
+
res.status(401).json({ error: err.message });
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
112
163
|
|
|
113
|
-
|
|
164
|
+
## 5. Payload Structure (Internal)
|
|
165
|
+
|
|
166
|
+
```json
|
|
114
167
|
{
|
|
115
|
-
data: {
|
|
116
|
-
userId: 1,
|
|
117
|
-
role: "admin"
|
|
168
|
+
"data": {
|
|
169
|
+
"userId": 1,
|
|
170
|
+
"role": "admin"
|
|
118
171
|
},
|
|
119
|
-
iat: 1768368114,
|
|
120
|
-
exp: 1768369014,
|
|
121
|
-
fp:
|
|
172
|
+
"iat": 1768368114,
|
|
173
|
+
"exp": 1768369014,
|
|
174
|
+
"fp": "device-fingerprint" // stored server-side
|
|
122
175
|
}
|
|
123
176
|
```
|
|
124
177
|
|
|
178
|
+
> Note: The `fp` (fingerprint) and session ID are **not exposed to the browser**, making token copying attacks impossible.
|
|
179
|
+
|
|
125
180
|
---
|
|
126
181
|
|
|
127
|
-
##
|
|
182
|
+
## 6. Installation
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
npm install secure-web-token
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 7. Importing
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
// ESM
|
|
194
|
+
import { sign, verify, getStore } from "secure-web-token";
|
|
195
|
+
|
|
196
|
+
// CommonJS
|
|
197
|
+
const { sign, verify, getStore } = require("secure-web-token");
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 8. Summary of Features
|
|
203
|
+
|
|
204
|
+
- 🔐 AES-256-GCM encryption
|
|
205
|
+
- 🔒 Server-side session + device binding
|
|
206
|
+
- ⏱ Expiry (`iat` + `exp`)
|
|
207
|
+
- 🛡 Prevents token reuse on unauthorized devices
|
|
208
|
+
- ⚡ Easy integration with Node.js / Express
|
|
209
|
+
- ✅ Auto-generated device IDs
|
|
210
|
+
- ✅ Fully optional server-side memory store
|
|
128
211
|
|
|
129
|
-
MIT License
|