@naturalcycles/nodejs-lib 12.80.4 → 12.81.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/dist/index.d.ts CHANGED
@@ -72,5 +72,6 @@ export * from './validation/joi/joi.shared.schemas';
72
72
  export * from './validation/joi/joi.validation.error';
73
73
  export * from './validation/joi/joi.validation.util';
74
74
  export * from './script';
75
+ export * from './jwt/jwt.service';
75
76
  export type { GlobbyOptions, FastGlobOptions, ValidationErrorItem, AnySchema, Got, AfterResponseHook, BeforeErrorHook, BeforeRequestHook, };
76
77
  export { globby, fastGlob, RequestError, TimeoutError, Ajv };
package/dist/index.js CHANGED
@@ -77,3 +77,4 @@ tslib_1.__exportStar(require("./validation/joi/joi.shared.schemas"), exports);
77
77
  tslib_1.__exportStar(require("./validation/joi/joi.validation.error"), exports);
78
78
  tslib_1.__exportStar(require("./validation/joi/joi.validation.util"), exports);
79
79
  tslib_1.__exportStar(require("./script"), exports);
80
+ tslib_1.__exportStar(require("./jwt/jwt.service"), exports);
@@ -0,0 +1,55 @@
1
+ /// <reference types="node" />
2
+ import { AnyObject, ErrorData, JWTString } from '@naturalcycles/js-lib';
3
+ import type { Algorithm, VerifyOptions, JwtHeader, SignOptions } from 'jsonwebtoken';
4
+ import * as jsonwebtoken from 'jsonwebtoken';
5
+ import { AnySchemaTyped } from '../validation/joi/joi.model';
6
+ export { jsonwebtoken };
7
+ export type { Algorithm, VerifyOptions, SignOptions, JwtHeader };
8
+ export interface JWTServiceCfg {
9
+ /**
10
+ * Public key is required to Verify incoming tokens.
11
+ * Optional if you only want to Decode or Sign.
12
+ */
13
+ publicKey?: string | Buffer;
14
+ /**
15
+ * Private key is required to Sign (create) outgoing tokens.
16
+ * Optional if you only want to Decode or Verify.
17
+ */
18
+ privateKey?: string | Buffer;
19
+ /**
20
+ * Recommended: ES256
21
+ */
22
+ algorithm: Algorithm;
23
+ /**
24
+ * If provided - will be applied to every Sign operation.
25
+ */
26
+ signOptions?: SignOptions;
27
+ /**
28
+ * If provided - will be applied to every Sign operation.
29
+ */
30
+ verifyOptions?: VerifyOptions;
31
+ /**
32
+ * If set - errors thrown from this service will be extended
33
+ * with this errorData (in err.data)
34
+ */
35
+ errorData?: ErrorData;
36
+ }
37
+ /**
38
+ * Wraps popular `jsonwebtoken` library.
39
+ * You should create one instance of JWTService for each pair of private/public key.
40
+ *
41
+ * Generate key pair like this:
42
+ * openssl ecparam -name secp256k1 -genkey -noout -out key.pem
43
+ * openssl ec -in key.pem -pubout > key.pub.pem
44
+ */
45
+ export declare class JWTService {
46
+ cfg: JWTServiceCfg;
47
+ constructor(cfg: JWTServiceCfg);
48
+ sign<T extends AnyObject>(payload: T, schema?: AnySchemaTyped<T>, opt?: SignOptions): JWTString;
49
+ verify<T extends AnyObject>(token: JWTString, schema?: AnySchemaTyped<T>, opt?: VerifyOptions): T;
50
+ decode<T extends AnyObject>(token: JWTString, schema?: AnySchemaTyped<T>): {
51
+ header: JwtHeader;
52
+ payload: T;
53
+ signature: string;
54
+ };
55
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JWTService = exports.jsonwebtoken = void 0;
4
+ const js_lib_1 = require("@naturalcycles/js-lib");
5
+ const jsonwebtoken = require("jsonwebtoken");
6
+ exports.jsonwebtoken = jsonwebtoken;
7
+ const joi_shared_schemas_1 = require("../validation/joi/joi.shared.schemas");
8
+ const joi_validation_util_1 = require("../validation/joi/joi.validation.util");
9
+ // todo: define JWTError and list possible options
10
+ /**
11
+ * Wraps popular `jsonwebtoken` library.
12
+ * You should create one instance of JWTService for each pair of private/public key.
13
+ *
14
+ * Generate key pair like this:
15
+ * openssl ecparam -name secp256k1 -genkey -noout -out key.pem
16
+ * openssl ec -in key.pem -pubout > key.pub.pem
17
+ */
18
+ class JWTService {
19
+ constructor(cfg) {
20
+ this.cfg = cfg;
21
+ }
22
+ sign(payload, schema, opt = {}) {
23
+ (0, js_lib_1._assert)(this.cfg.privateKey, 'JWTService: privateKey is required to be able to verify, but not provided');
24
+ if (schema) {
25
+ (0, joi_validation_util_1.validate)(payload, schema);
26
+ }
27
+ return jsonwebtoken.sign(payload, this.cfg.privateKey, {
28
+ algorithm: this.cfg.algorithm,
29
+ noTimestamp: true,
30
+ ...this.cfg.signOptions,
31
+ ...opt,
32
+ });
33
+ }
34
+ verify(token, schema, opt = {}) {
35
+ (0, js_lib_1._assert)(this.cfg.publicKey, 'JWTService: publicKey is required to be able to verify, but not provided');
36
+ try {
37
+ const data = jsonwebtoken.verify(token, this.cfg.publicKey, {
38
+ algorithms: [this.cfg.algorithm],
39
+ ...this.cfg.verifyOptions,
40
+ ...opt,
41
+ });
42
+ if (schema) {
43
+ (0, joi_validation_util_1.validate)(data, schema);
44
+ }
45
+ return data;
46
+ }
47
+ catch (err) {
48
+ if (this.cfg.errorData) {
49
+ (0, js_lib_1._typeCast)(err);
50
+ (0, js_lib_1._errorDataAppend)(err, {
51
+ ...this.cfg.errorData,
52
+ });
53
+ }
54
+ throw err;
55
+ }
56
+ }
57
+ decode(token, schema) {
58
+ const data = jsonwebtoken.decode(token, {
59
+ complete: true,
60
+ });
61
+ (0, js_lib_1._assert)(data, 'invalid token, decoded value is null', {
62
+ ...this.cfg.errorData,
63
+ });
64
+ (0, joi_validation_util_1.validate)(data.payload, schema || joi_shared_schemas_1.anyObjectSchema);
65
+ return data;
66
+ }
67
+ }
68
+ exports.JWTService = JWTService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
- "version": "12.80.4",
3
+ "version": "12.81.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "docs-serve": "vuepress dev docs",
@@ -15,6 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@naturalcycles/js-lib": "^14.0.0",
18
+ "@types/jsonwebtoken": "^8.5.9",
18
19
  "@types/through2-concurrent": "^2.0.0",
19
20
  "ajv": "^8.6.2",
20
21
  "ajv-formats": "^2.1.0",
@@ -31,6 +32,7 @@
31
32
  "globby": "^11.0.0",
32
33
  "got": "^11.0.1",
33
34
  "joi": "17.4.2",
35
+ "jsonwebtoken": "^8.5.1",
34
36
  "lru-cache": "^7.4.0",
35
37
  "move-file": "^2.0.0",
36
38
  "through2-concurrent": "^2.0.0",
package/src/index.ts CHANGED
@@ -72,6 +72,7 @@ export * from './validation/joi/joi.shared.schemas'
72
72
  export * from './validation/joi/joi.validation.error'
73
73
  export * from './validation/joi/joi.validation.util'
74
74
  export * from './script'
75
+ export * from './jwt/jwt.service'
75
76
 
76
77
  export type {
77
78
  GlobbyOptions,
@@ -0,0 +1,143 @@
1
+ import {
2
+ _assert,
3
+ _errorDataAppend,
4
+ _typeCast,
5
+ AnyObject,
6
+ ErrorData,
7
+ JWTString,
8
+ } from '@naturalcycles/js-lib'
9
+ import type { Algorithm, VerifyOptions, JwtHeader, SignOptions } from 'jsonwebtoken'
10
+ import * as jsonwebtoken from 'jsonwebtoken'
11
+ import { AnySchemaTyped } from '../validation/joi/joi.model'
12
+ import { anyObjectSchema } from '../validation/joi/joi.shared.schemas'
13
+ import { validate } from '../validation/joi/joi.validation.util'
14
+ export { jsonwebtoken }
15
+ export type { Algorithm, VerifyOptions, SignOptions, JwtHeader }
16
+
17
+ export interface JWTServiceCfg {
18
+ /**
19
+ * Public key is required to Verify incoming tokens.
20
+ * Optional if you only want to Decode or Sign.
21
+ */
22
+ publicKey?: string | Buffer
23
+ /**
24
+ * Private key is required to Sign (create) outgoing tokens.
25
+ * Optional if you only want to Decode or Verify.
26
+ */
27
+ privateKey?: string | Buffer
28
+
29
+ /**
30
+ * Recommended: ES256
31
+ */
32
+ algorithm: Algorithm
33
+
34
+ /**
35
+ * If provided - will be applied to every Sign operation.
36
+ */
37
+ signOptions?: SignOptions
38
+
39
+ /**
40
+ * If provided - will be applied to every Sign operation.
41
+ */
42
+ verifyOptions?: VerifyOptions
43
+
44
+ /**
45
+ * If set - errors thrown from this service will be extended
46
+ * with this errorData (in err.data)
47
+ */
48
+ errorData?: ErrorData
49
+ }
50
+
51
+ // todo: define JWTError and list possible options
52
+
53
+ /**
54
+ * Wraps popular `jsonwebtoken` library.
55
+ * You should create one instance of JWTService for each pair of private/public key.
56
+ *
57
+ * Generate key pair like this:
58
+ * openssl ecparam -name secp256k1 -genkey -noout -out key.pem
59
+ * openssl ec -in key.pem -pubout > key.pub.pem
60
+ */
61
+ export class JWTService {
62
+ constructor(public cfg: JWTServiceCfg) {}
63
+
64
+ sign<T extends AnyObject>(
65
+ payload: T,
66
+ schema?: AnySchemaTyped<T>,
67
+ opt: SignOptions = {},
68
+ ): JWTString {
69
+ _assert(
70
+ this.cfg.privateKey,
71
+ 'JWTService: privateKey is required to be able to verify, but not provided',
72
+ )
73
+
74
+ if (schema) {
75
+ validate(payload, schema)
76
+ }
77
+
78
+ return jsonwebtoken.sign(payload, this.cfg.privateKey, {
79
+ algorithm: this.cfg.algorithm,
80
+ noTimestamp: true,
81
+ ...this.cfg.signOptions,
82
+ ...opt,
83
+ })
84
+ }
85
+
86
+ verify<T extends AnyObject>(
87
+ token: JWTString,
88
+ schema?: AnySchemaTyped<T>,
89
+ opt: VerifyOptions = {},
90
+ ): T {
91
+ _assert(
92
+ this.cfg.publicKey,
93
+ 'JWTService: publicKey is required to be able to verify, but not provided',
94
+ )
95
+
96
+ try {
97
+ const data = jsonwebtoken.verify(token, this.cfg.publicKey, {
98
+ algorithms: [this.cfg.algorithm],
99
+ ...this.cfg.verifyOptions,
100
+ ...opt,
101
+ }) as T
102
+
103
+ if (schema) {
104
+ validate(data, schema)
105
+ }
106
+
107
+ return data
108
+ } catch (err) {
109
+ if (this.cfg.errorData) {
110
+ _typeCast<Error>(err)
111
+ _errorDataAppend(err, {
112
+ ...this.cfg.errorData,
113
+ })
114
+ }
115
+ throw err
116
+ }
117
+ }
118
+
119
+ decode<T extends AnyObject>(
120
+ token: JWTString,
121
+ schema?: AnySchemaTyped<T>,
122
+ ): {
123
+ header: JwtHeader
124
+ payload: T
125
+ signature: string
126
+ } {
127
+ const data = jsonwebtoken.decode(token, {
128
+ complete: true,
129
+ }) as {
130
+ header: JwtHeader
131
+ payload: T
132
+ signature: string
133
+ } | null
134
+
135
+ _assert(data, 'invalid token, decoded value is null', {
136
+ ...this.cfg.errorData,
137
+ })
138
+
139
+ validate(data.payload, schema || anyObjectSchema)
140
+
141
+ return data
142
+ }
143
+ }