@alexdevco/passport 1.0.11 → 1.0.12

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.
@@ -16,4 +16,10 @@ export interface IJWTStrategy {
16
16
  * @returns Результат проверки токена.
17
17
  */
18
18
  verify(token: string): IVerifyResult;
19
+ /**
20
+ * Проверяет действительность refresh токена.
21
+ * @param token - Refresh токен для проверки.
22
+ * @returns Результат проверки токена.
23
+ */
24
+ verifyRefresh(token: string): IVerifyResult;
19
25
  }
@@ -6,7 +6,7 @@ export interface IPassportOptions {
6
6
  /**
7
7
  * Секретный ключ, используемый для подписи JWT токенов.
8
8
  */
9
- secretKey: string;
9
+ secretKey?: string;
10
10
  /**
11
11
  * Публичный ключ, используемый для верификации JWT токенов.
12
12
  * Обязателен для асимметричных алгоритмов (например, RS256).
@@ -8,9 +8,29 @@ export interface IPayload {
8
8
  */
9
9
  sub: string | number;
10
10
  /**
11
- * Имя пользователя .
11
+ * Роли пользователя в системе.
12
+ * Определяет уровень доступа и разрешения.
12
13
  */
13
- name: string;
14
+ roles: string[];
15
+ /**
16
+ * Разрешения пользователя в системе.
17
+ * Определяют конкретные действия, которые пользователь может выполнять.
18
+ */
19
+ permissions: string[];
20
+ /**
21
+ * Время выпуска токена (Issued At) в секундах since Unix epoch.
22
+ */
23
+ iat: number;
24
+ /**
25
+ * Время истечения срока действия токена (Expiration Time) в секундах since Unix epoch.
26
+ */
27
+ exp: number;
28
+ }
29
+ export interface IRefreshPayload {
30
+ /**
31
+ * Идентификатор (Subject ID) - уникальный идентификатор пользователя.
32
+ */
33
+ sub: string | number;
14
34
  /**
15
35
  * Время выпуска токена (Issued At) в секундах since Unix epoch.
16
36
  */
@@ -51,5 +71,5 @@ export interface IVerifyResult {
51
71
  /**
52
72
  * Полезная нагрузка токена, если он действителен.
53
73
  */
54
- payload?: IPayload;
74
+ payload?: IPayload | IRefreshPayload;
55
75
  }
@@ -20,6 +20,7 @@ export declare class HS256Strategy implements IJWTStrategy {
20
20
  * @returns Результат проверки токена.
21
21
  */
22
22
  verify(token: string): IVerifyResult;
23
+ verifyRefresh(token: string): IVerifyResult;
23
24
  /**
24
25
  * Вычисляет HMAC-подпись для переданных данных, используя секретный ключ.
25
26
  * Алгоритм шифрования: SHA-256.
@@ -52,6 +52,27 @@ class HS256Strategy {
52
52
  return { valid: false, reason: 'Token is expired' };
53
53
  return { valid: true, payload };
54
54
  }
55
+ verifyRefresh(token) {
56
+ const parts = token.split(HS256Strategy.INTERNAL_SEPARATOR);
57
+ if (parts.length !== HS256Strategy.PARTS_LENGTH) {
58
+ return { valid: false, reason: 'Invalid format' };
59
+ }
60
+ const [headerB64, payloadB64, mac] = parts;
61
+ const serialized = (0, utils_1.serialize)([headerB64, payloadB64], HS256Strategy.INTERNAL_SEPARATOR);
62
+ const expectedMac = this.computeHmac(serialized);
63
+ if (!(0, utils_1.constantTimeEqual)(expectedMac, mac)) {
64
+ return { valid: false, reason: 'Invalid signature' };
65
+ }
66
+ const parsed = JSON.parse((0, utils_1.base64UrlDecode)(payloadB64));
67
+ if (!(0, utils_1.isRefreshPayload)(parsed))
68
+ return { valid: false, reason: 'Invalid payload stucture' };
69
+ const payload = parsed;
70
+ if (!Number.isFinite(payload.exp))
71
+ return { valid: false, reason: 'Expired error format' };
72
+ if ((0, utils_1.now)() > payload.exp)
73
+ return { valid: false, reason: 'Token is expired' };
74
+ return { valid: true, payload };
75
+ }
55
76
  /**
56
77
  * Вычисляет HMAC-подпись для переданных данных, используя секретный ключ.
57
78
  * Алгоритм шифрования: SHA-256.
@@ -27,6 +27,7 @@ export declare class RS256Strategy implements IJWTStrategy {
27
27
  * @returns результат проверки токена со статусом и возможной полезной нагрузкой
28
28
  */
29
29
  verify(token: string): IVerifyResult;
30
+ verifyRefresh(token: string): IVerifyResult;
30
31
  /**
31
32
  * Создание подписи для токена
32
33
  *
@@ -59,6 +59,26 @@ class RS256Strategy {
59
59
  return { valid: false, reason: 'Token is expired' };
60
60
  return { valid: true, payload };
61
61
  }
62
+ verifyRefresh(token) {
63
+ const parts = token.split(RS256Strategy.INTERNAL_SEPARATOR);
64
+ if (parts.length !== RS256Strategy.PARTS_LENGTH)
65
+ return { valid: false, reason: 'Invalid format' };
66
+ const [header64, payload64, mac] = parts;
67
+ const serialized = (0, utils_1.serialize)([header64, payload64], RS256Strategy.INTERNAL_SEPARATOR);
68
+ const signatureBuffer = Buffer.from(mac, 'base64url');
69
+ const verify = (0, crypto_1.createVerify)(RS256Strategy.JWT_ALG).update(serialized);
70
+ if (!verify.verify(this.PUBLIC_KEY, signatureBuffer))
71
+ return { valid: false, reason: 'Invalid signature' };
72
+ const parsed = JSON.parse((0, utils_1.base64UrlDecode)(payload64));
73
+ if (!(0, utils_1.isRefreshPayload)(parsed))
74
+ return { valid: false, reason: 'Invalid payload stucture' };
75
+ const payload = parsed;
76
+ if (!Number.isFinite(payload.exp))
77
+ return { valid: false, reason: 'Expired error format' };
78
+ if ((0, utils_1.now)() > payload.exp)
79
+ return { valid: false, reason: 'Token is expired' };
80
+ return { valid: true, payload };
81
+ }
62
82
  /**
63
83
  * Создание подписи для токена
64
84
  *
@@ -1,4 +1,4 @@
1
- import { IHeader, IPayload } from '../interfaces';
1
+ import { IHeader, IPayload, IRefreshPayload } from '../interfaces';
2
2
  /**
3
3
  * Проверяет, является ли переданный объект полезной нагрузкой токена.
4
4
  * Объект считается полезной нагрузкой, если:
@@ -11,6 +11,17 @@ import { IHeader, IPayload } from '../interfaces';
11
11
  * @returns true, если объект соответствует интерфейсу IPayload, иначе false
12
12
  */
13
13
  export declare function isPayload(data: any): data is IPayload;
14
+ /**
15
+ * Проверяет, является ли переданный объект полезной нагрузкой refresh-токена.
16
+ * Объект считается полезной нагрузкой refresh-токена, если:
17
+ * - свойство sub является строкой или числом
18
+ * - свойство iat является числом
19
+ * - свойство exp является числом
20
+ *
21
+ * @param data - проверяемый объект
22
+ * @returns true, если объект соответствует интерфейсу IRefreshPayload, иначе false
23
+ */
24
+ export declare function isRefreshPayload(data: any): data is IRefreshPayload;
14
25
  /**
15
26
  * Проверяет, является ли переданный объект заголовком токена.
16
27
  * Объект считается заголовком, если:
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isPayload = isPayload;
4
+ exports.isRefreshPayload = isRefreshPayload;
4
5
  exports.isHeader = isHeader;
5
6
  /**
6
7
  * Проверяет, является ли переданный объект полезной нагрузкой токена.
@@ -15,7 +16,25 @@ exports.isHeader = isHeader;
15
16
  */
16
17
  function isPayload(data) {
17
18
  return ((typeof data.sub === 'string' || typeof data.sub === 'number') &&
18
- typeof data.name === 'string' &&
19
+ Array.isArray(data.roles) &&
20
+ data.roles.every((role) => typeof role === 'string') &&
21
+ Array.isArray(data.permissions) &&
22
+ data.permissions.every((perm) => typeof perm === 'string') &&
23
+ typeof data.iat === 'number' &&
24
+ typeof data.exp === 'number');
25
+ }
26
+ /**
27
+ * Проверяет, является ли переданный объект полезной нагрузкой refresh-токена.
28
+ * Объект считается полезной нагрузкой refresh-токена, если:
29
+ * - свойство sub является строкой или числом
30
+ * - свойство iat является числом
31
+ * - свойство exp является числом
32
+ *
33
+ * @param data - проверяемый объект
34
+ * @returns true, если объект соответствует интерфейсу IRefreshPayload, иначе false
35
+ */
36
+ function isRefreshPayload(data) {
37
+ return ((typeof data.sub === 'string' || typeof data.sub === 'number') &&
19
38
  typeof data.iat === 'number' &&
20
39
  typeof data.exp === 'number');
21
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexdevco/passport",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "Lightweight AlexDevCo authentication library",
5
5
  "homepage": "https://github.com/alexdevcoru/passport#readme",
6
6
  "bugs": {