win-portal-auth-sdk 1.2.1 → 1.3.0
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 +28 -9
- package/dist/client/api/auth.api.d.ts +25 -1
- package/dist/client/api/auth.api.d.ts.map +1 -1
- package/dist/client/api/auth.api.js +30 -1
- package/dist/client/api/files.api.d.ts +0 -1
- package/dist/client/api/files.api.d.ts.map +1 -1
- package/dist/client/api/index.d.ts +2 -0
- package/dist/client/api/index.d.ts.map +1 -1
- package/dist/client/api/index.js +3 -1
- package/dist/client/api/license.api.d.ts +74 -0
- package/dist/client/api/license.api.d.ts.map +1 -0
- package/dist/client/api/license.api.js +50 -0
- package/dist/client/api/system-config.api.d.ts +11 -1
- package/dist/client/api/system-config.api.d.ts.map +1 -1
- package/dist/client/api/system-config.api.js +21 -0
- package/dist/client/auth-client.d.ts +183 -1
- package/dist/client/auth-client.d.ts.map +1 -1
- package/dist/client/auth-client.js +453 -4
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/types/auth.types.d.ts +9 -0
- package/dist/types/auth.types.d.ts.map +1 -1
- package/dist/types/system-config.types.d.ts +37 -0
- package/dist/types/system-config.types.d.ts.map +1 -1
- package/dist/utils/token-utils.d.ts +60 -0
- package/dist/utils/token-utils.d.ts.map +1 -0
- package/dist/utils/token-utils.js +116 -0
- package/package.json +1 -2
- package/TYPE_SAFETY.md +0 -97
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Utilities
|
|
3
|
+
*
|
|
4
|
+
* @description Utilities สำหรับจัดการ JWT tokens
|
|
5
|
+
* - Decode JWT payload
|
|
6
|
+
* - ตรวจสอบ token expiration
|
|
7
|
+
* - คำนวณเวลาที่เหลือก่อนหมดอายุ
|
|
8
|
+
*/
|
|
9
|
+
interface JwtPayload {
|
|
10
|
+
exp: number;
|
|
11
|
+
iat?: number;
|
|
12
|
+
sub?: string;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Decode JWT token (base64 decode only, ไม่ verify signature)
|
|
17
|
+
*
|
|
18
|
+
* @param token - JWT token string
|
|
19
|
+
* @returns Decoded payload หรือ null ถ้า decode ไม่ได้
|
|
20
|
+
*/
|
|
21
|
+
export declare function decodeJwt(token: string): JwtPayload | null;
|
|
22
|
+
/**
|
|
23
|
+
* ตรวจสอบว่า token หมดอายุหรือยัง
|
|
24
|
+
*
|
|
25
|
+
* @param token - JWT token string
|
|
26
|
+
* @returns true ถ้า token หมดอายุแล้ว
|
|
27
|
+
*/
|
|
28
|
+
export declare function isTokenExpired(token: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* คำนวณเวลาที่เหลือก่อน token หมดอายุ (เป็นนาที)
|
|
31
|
+
*
|
|
32
|
+
* @param token - JWT token string
|
|
33
|
+
* @returns จำนวนนาทีที่เหลือ หรือ null ถ้า decode ไม่ได้
|
|
34
|
+
*/
|
|
35
|
+
export declare function getTokenExpirationMinutes(token: string): number | null;
|
|
36
|
+
/**
|
|
37
|
+
* ตรวจสอบว่า token ใกล้หมดอายุหรือไม่ (ตาม threshold)
|
|
38
|
+
*
|
|
39
|
+
* @param token - JWT token string
|
|
40
|
+
* @param thresholdMinutes - จำนวนนาทีก่อนหมดอายุที่จะถือว่า "ใกล้หมดอายุ" (default: 5)
|
|
41
|
+
* @returns true ถ้า token ใกล้หมดอายุ
|
|
42
|
+
*/
|
|
43
|
+
export declare function isTokenNearExpiration(token: string, thresholdMinutes?: number): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* ตรวจสอบว่า token ยังใช้งานได้หรือไม่ (ยังไม่หมดอายุ)
|
|
46
|
+
*
|
|
47
|
+
* @param token - JWT token string
|
|
48
|
+
* @returns true ถ้า token ยังใช้งานได้
|
|
49
|
+
*/
|
|
50
|
+
export declare function isTokenValid(token: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* แปลง duration + unit เป็นนาที
|
|
53
|
+
*
|
|
54
|
+
* @param duration - จำนวน duration
|
|
55
|
+
* @param unit - หน่วยเวลา: 'minutes', 'hours', หรือ 'days'
|
|
56
|
+
* @returns จำนวนนาที
|
|
57
|
+
*/
|
|
58
|
+
export declare function convertDurationToMinutes(duration: number, unit: 'minutes' | 'hours' | 'days'): number;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=token-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-utils.d.ts","sourceRoot":"","sources":["../../src/utils/token-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAmB1D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CASrD;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,GAAE,MAAU,GAAG,OAAO,CAO1F;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAWrG"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Token Utilities
|
|
4
|
+
*
|
|
5
|
+
* @description Utilities สำหรับจัดการ JWT tokens
|
|
6
|
+
* - Decode JWT payload
|
|
7
|
+
* - ตรวจสอบ token expiration
|
|
8
|
+
* - คำนวณเวลาที่เหลือก่อนหมดอายุ
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.convertDurationToMinutes = exports.isTokenValid = exports.isTokenNearExpiration = exports.getTokenExpirationMinutes = exports.isTokenExpired = exports.decodeJwt = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* Decode JWT token (base64 decode only, ไม่ verify signature)
|
|
14
|
+
*
|
|
15
|
+
* @param token - JWT token string
|
|
16
|
+
* @returns Decoded payload หรือ null ถ้า decode ไม่ได้
|
|
17
|
+
*/
|
|
18
|
+
function decodeJwt(token) {
|
|
19
|
+
try {
|
|
20
|
+
const parts = token.split('.');
|
|
21
|
+
if (parts.length !== 3) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
// Decode payload (second part)
|
|
25
|
+
const payload = parts[1];
|
|
26
|
+
// Support both browser and Node.js environments
|
|
27
|
+
const decoded = typeof window !== 'undefined'
|
|
28
|
+
? atob(payload.replace(/-/g, '+').replace(/_/g, '/'))
|
|
29
|
+
: Buffer.from(payload.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf-8');
|
|
30
|
+
return JSON.parse(decoded);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('[TokenUtils] Failed to decode JWT:', error);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.decodeJwt = decodeJwt;
|
|
38
|
+
/**
|
|
39
|
+
* ตรวจสอบว่า token หมดอายุหรือยัง
|
|
40
|
+
*
|
|
41
|
+
* @param token - JWT token string
|
|
42
|
+
* @returns true ถ้า token หมดอายุแล้ว
|
|
43
|
+
*/
|
|
44
|
+
function isTokenExpired(token) {
|
|
45
|
+
const payload = decodeJwt(token);
|
|
46
|
+
if (!payload || !payload.exp) {
|
|
47
|
+
return true; // ถ้า decode ไม่ได้หรือไม่มี exp ถือว่าหมดอายุ
|
|
48
|
+
}
|
|
49
|
+
const expirationTime = payload.exp * 1000; // Convert to milliseconds
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
return now >= expirationTime;
|
|
52
|
+
}
|
|
53
|
+
exports.isTokenExpired = isTokenExpired;
|
|
54
|
+
/**
|
|
55
|
+
* คำนวณเวลาที่เหลือก่อน token หมดอายุ (เป็นนาที)
|
|
56
|
+
*
|
|
57
|
+
* @param token - JWT token string
|
|
58
|
+
* @returns จำนวนนาทีที่เหลือ หรือ null ถ้า decode ไม่ได้
|
|
59
|
+
*/
|
|
60
|
+
function getTokenExpirationMinutes(token) {
|
|
61
|
+
const payload = decodeJwt(token);
|
|
62
|
+
if (!payload || !payload.exp) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const expirationTime = payload.exp * 1000; // Convert to milliseconds
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
const remainingMs = expirationTime - now;
|
|
68
|
+
const remainingMinutes = Math.floor(remainingMs / (1000 * 60));
|
|
69
|
+
return remainingMinutes;
|
|
70
|
+
}
|
|
71
|
+
exports.getTokenExpirationMinutes = getTokenExpirationMinutes;
|
|
72
|
+
/**
|
|
73
|
+
* ตรวจสอบว่า token ใกล้หมดอายุหรือไม่ (ตาม threshold)
|
|
74
|
+
*
|
|
75
|
+
* @param token - JWT token string
|
|
76
|
+
* @param thresholdMinutes - จำนวนนาทีก่อนหมดอายุที่จะถือว่า "ใกล้หมดอายุ" (default: 5)
|
|
77
|
+
* @returns true ถ้า token ใกล้หมดอายุ
|
|
78
|
+
*/
|
|
79
|
+
function isTokenNearExpiration(token, thresholdMinutes = 5) {
|
|
80
|
+
const remainingMinutes = getTokenExpirationMinutes(token);
|
|
81
|
+
if (remainingMinutes === null) {
|
|
82
|
+
return true; // ถ้า decode ไม่ได้ ถือว่าใกล้หมดอายุ
|
|
83
|
+
}
|
|
84
|
+
return remainingMinutes <= thresholdMinutes;
|
|
85
|
+
}
|
|
86
|
+
exports.isTokenNearExpiration = isTokenNearExpiration;
|
|
87
|
+
/**
|
|
88
|
+
* ตรวจสอบว่า token ยังใช้งานได้หรือไม่ (ยังไม่หมดอายุ)
|
|
89
|
+
*
|
|
90
|
+
* @param token - JWT token string
|
|
91
|
+
* @returns true ถ้า token ยังใช้งานได้
|
|
92
|
+
*/
|
|
93
|
+
function isTokenValid(token) {
|
|
94
|
+
return !isTokenExpired(token);
|
|
95
|
+
}
|
|
96
|
+
exports.isTokenValid = isTokenValid;
|
|
97
|
+
/**
|
|
98
|
+
* แปลง duration + unit เป็นนาที
|
|
99
|
+
*
|
|
100
|
+
* @param duration - จำนวน duration
|
|
101
|
+
* @param unit - หน่วยเวลา: 'minutes', 'hours', หรือ 'days'
|
|
102
|
+
* @returns จำนวนนาที
|
|
103
|
+
*/
|
|
104
|
+
function convertDurationToMinutes(duration, unit) {
|
|
105
|
+
switch (unit) {
|
|
106
|
+
case 'minutes':
|
|
107
|
+
return duration;
|
|
108
|
+
case 'hours':
|
|
109
|
+
return duration * 60;
|
|
110
|
+
case 'days':
|
|
111
|
+
return duration * 24 * 60;
|
|
112
|
+
default:
|
|
113
|
+
return duration; // fallback
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.convertDurationToMinutes = convertDurationToMinutes;
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "win-portal-auth-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Shared authentication SDK for Win Portal applications with JWT and OAuth support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"README.md",
|
|
10
|
-
"TYPE_SAFETY.md",
|
|
11
10
|
"LICENSE"
|
|
12
11
|
],
|
|
13
12
|
"repository": {
|
package/TYPE_SAFETY.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# Type Safety Guide
|
|
2
|
-
|
|
3
|
-
## Express Type Augmentation
|
|
4
|
-
|
|
5
|
-
The SDK automatically extends Express's `Request` interface to include auth properties.
|
|
6
|
-
|
|
7
|
-
### What's Included
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
declare global {
|
|
11
|
-
namespace Express {
|
|
12
|
-
interface Request {
|
|
13
|
-
user?: UserProfileResponseDto | null;
|
|
14
|
-
token?: string | null;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### Usage
|
|
21
|
-
|
|
22
|
-
After installing the SDK, TypeScript will automatically recognize `req.user` and `req.token`:
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
import express from 'express';
|
|
26
|
-
import { authMiddleware } from 'win-portal-auth-sdk';
|
|
27
|
-
|
|
28
|
-
const app = express();
|
|
29
|
-
|
|
30
|
-
app.use(
|
|
31
|
-
authMiddleware({
|
|
32
|
-
baseURL: process.env.API_URL,
|
|
33
|
-
apiKey: process.env.API_KEY,
|
|
34
|
-
}),
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
app.get('/profile', (req, res) => {
|
|
38
|
-
// ✅ TypeScript knows about req.user
|
|
39
|
-
if (req.user) {
|
|
40
|
-
// ✅ Full IntelliSense for user properties
|
|
41
|
-
res.json({
|
|
42
|
-
email: req.user.email,
|
|
43
|
-
name: req.user.displayName,
|
|
44
|
-
permissions: req.user.permissions,
|
|
45
|
-
});
|
|
46
|
-
} else {
|
|
47
|
-
res.status(401).json({ error: 'Not authenticated' });
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### States
|
|
53
|
-
|
|
54
|
-
- `undefined` - Middleware not applied to this route
|
|
55
|
-
- `null` - Middleware applied but no token provided (when `optional: true`)
|
|
56
|
-
- `UserProfileResponseDto` - Successfully authenticated
|
|
57
|
-
|
|
58
|
-
### Helper Functions
|
|
59
|
-
|
|
60
|
-
For guaranteed non-null user:
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
import { requireAuth } from 'win-portal-auth-sdk';
|
|
64
|
-
|
|
65
|
-
app.get('/protected', (req, res) => {
|
|
66
|
-
const { user } = requireAuth(req);
|
|
67
|
-
// ✅ user is guaranteed to be UserProfileResponseDto (not null)
|
|
68
|
-
res.json({ email: user.email });
|
|
69
|
-
});
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
For optional auth:
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
import { getAuth } from 'win-portal-auth-sdk';
|
|
76
|
-
|
|
77
|
-
app.get('/optional', (req, res) => {
|
|
78
|
-
const { user, token } = getAuth(req);
|
|
79
|
-
|
|
80
|
-
if (user) {
|
|
81
|
-
res.json({ authenticated: true, email: user.email });
|
|
82
|
-
} else {
|
|
83
|
-
res.json({ authenticated: false });
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Benefits
|
|
89
|
-
|
|
90
|
-
1. **IntelliSense** - Full autocomplete for `req.user` properties
|
|
91
|
-
2. **Type Safety** - Compile-time errors for typos
|
|
92
|
-
3. **Better DX** - No need to cast or assert types manually
|
|
93
|
-
4. **Standard Pattern** - Follows Express best practices
|
|
94
|
-
|
|
95
|
-
## No Express Dependency
|
|
96
|
-
|
|
97
|
-
The SDK does NOT depend on Express itself - it only augments the types when Express is present in your project. This keeps the SDK lightweight and flexible.
|