@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 +1 -0
- package/dist/index.js +1 -0
- package/dist/jwt/jwt.service.d.ts +55 -0
- package/dist/jwt/jwt.service.js +68 -0
- package/package.json +3 -1
- package/src/index.ts +1 -0
- package/src/jwt/jwt.service.ts +143 -0
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.
|
|
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
|
+
}
|