@croct/sdk 0.15.4 → 0.16.1
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/apiKey.d.ts +31 -3
- package/apiKey.js +93 -38
- package/apiKey.js.map +1 -1
- package/base64Url.d.ts +2 -0
- package/base64Url.js +25 -0
- package/base64Url.js.map +1 -0
- package/constants.d.ts +2 -2
- package/constants.js +1 -1
- package/logging/index.d.ts +1 -0
- package/logging/index.js +3 -1
- package/logging/index.js.map +1 -1
- package/package.json +1 -2
- package/src/apiKey.ts +138 -40
- package/src/base64Url.ts +22 -0
- package/src/logging/index.ts +1 -0
- package/src/token/token.ts +90 -35
- package/token/token.d.ts +12 -7
- package/token/token.js +49 -20
- package/token/token.js.map +1 -1
package/apiKey.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
export type ParsedPrivateKey = {
|
|
2
|
+
algorithm: string;
|
|
3
|
+
encodedKey: string;
|
|
4
|
+
};
|
|
2
5
|
export declare class ApiKey {
|
|
3
6
|
private static readonly IDENTIFIER_PATTERN;
|
|
4
7
|
private static readonly PRIVATE_KEY_PATTERN;
|
|
8
|
+
private static readonly ALGORITHMS;
|
|
5
9
|
private readonly identifier;
|
|
6
10
|
private readonly privateKey?;
|
|
11
|
+
private importedKey;
|
|
7
12
|
private constructor();
|
|
8
13
|
static from(apiKey: string | ApiKey): ApiKey;
|
|
9
14
|
static parse(apiKey: string): ApiKey;
|
|
@@ -11,8 +16,31 @@ export declare class ApiKey {
|
|
|
11
16
|
getIdentifier(): string;
|
|
12
17
|
getIdentifierHash(): Promise<string>;
|
|
13
18
|
hasPrivateKey(): boolean;
|
|
14
|
-
getPrivateKey(): string
|
|
15
|
-
sign(
|
|
19
|
+
getPrivateKey(): string;
|
|
20
|
+
sign(data: string): Promise<string>;
|
|
21
|
+
getSigningAlgorithm(): string;
|
|
22
|
+
private importKey;
|
|
23
|
+
private getParsedPrivateKey;
|
|
16
24
|
export(): string;
|
|
17
25
|
toString(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Create an array buffer from a string.
|
|
28
|
+
*
|
|
29
|
+
* @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
|
|
30
|
+
*
|
|
31
|
+
* @param data The string to convert.
|
|
32
|
+
* @returns The array buffer.
|
|
33
|
+
*/
|
|
34
|
+
private static createByteArrayFromString;
|
|
35
|
+
private static createByteArrayFromHexString;
|
|
36
|
+
/**
|
|
37
|
+
* Convert an array buffer to a string.
|
|
38
|
+
*
|
|
39
|
+
* @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
|
|
40
|
+
*
|
|
41
|
+
* @param buffer The buffer to convert.
|
|
42
|
+
* @returns The string.
|
|
43
|
+
*/
|
|
44
|
+
private static convertBufferToString;
|
|
45
|
+
private static convertBufferToHexString;
|
|
18
46
|
}
|
package/apiKey.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ApiKey = void 0;
|
|
4
|
-
const crypto = require("crypto");
|
|
5
4
|
class ApiKey {
|
|
6
5
|
constructor(identifier, privateKey) {
|
|
7
6
|
this.identifier = identifier;
|
|
@@ -22,68 +21,124 @@ class ApiKey {
|
|
|
22
21
|
}
|
|
23
22
|
static of(identifier, privateKey) {
|
|
24
23
|
if (!ApiKey.IDENTIFIER_PATTERN.test(identifier)) {
|
|
25
|
-
throw new Error('The
|
|
24
|
+
throw new Error('The identifier must be a UUID.');
|
|
26
25
|
}
|
|
27
|
-
if (privateKey === undefined) {
|
|
26
|
+
if (privateKey === undefined || privateKey === '') {
|
|
28
27
|
return new ApiKey(identifier);
|
|
29
28
|
}
|
|
30
29
|
if (!ApiKey.PRIVATE_KEY_PATTERN.test(privateKey)) {
|
|
31
|
-
throw new Error('The
|
|
30
|
+
throw new Error('The private key is malformed.');
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
format: 'der',
|
|
37
|
-
type: 'pkcs8',
|
|
38
|
-
}));
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
throw new Error('Invalid private key.');
|
|
32
|
+
const [algorithmName, encodedKey] = privateKey.split(';');
|
|
33
|
+
if (!(algorithmName in ApiKey.ALGORITHMS)) {
|
|
34
|
+
throw new Error(`Unsupported signing algorithm "${algorithmName}".`);
|
|
42
35
|
}
|
|
36
|
+
return new ApiKey(identifier, {
|
|
37
|
+
algorithm: algorithmName,
|
|
38
|
+
encodedKey: encodedKey,
|
|
39
|
+
});
|
|
43
40
|
}
|
|
44
41
|
getIdentifier() {
|
|
45
42
|
return this.identifier;
|
|
46
43
|
}
|
|
47
44
|
async getIdentifierHash() {
|
|
48
|
-
const identifierBytes =
|
|
45
|
+
const identifierBytes = ApiKey.createByteArrayFromHexString(this.identifier.replace(/-/g, ''));
|
|
49
46
|
const rawHash = await crypto.subtle.digest('SHA-256', identifierBytes);
|
|
50
|
-
return
|
|
47
|
+
return ApiKey.convertBufferToHexString(rawHash);
|
|
51
48
|
}
|
|
52
49
|
hasPrivateKey() {
|
|
53
50
|
return this.privateKey !== undefined;
|
|
54
51
|
}
|
|
55
52
|
getPrivateKey() {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
: this.privateKey
|
|
59
|
-
.export({ format: 'der', type: 'pkcs8' })
|
|
60
|
-
.toString('hex');
|
|
61
|
-
}
|
|
62
|
-
sign(blob) {
|
|
63
|
-
const { privateKey } = this;
|
|
64
|
-
if (privateKey === undefined) {
|
|
65
|
-
return Promise.reject(new Error('The API key does not have a private key.'));
|
|
53
|
+
if (this.privateKey === undefined) {
|
|
54
|
+
throw new Error('The API key does not have a private key.');
|
|
66
55
|
}
|
|
67
|
-
return
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
56
|
+
return `${this.privateKey.algorithm};${this.privateKey.encodedKey}`;
|
|
57
|
+
}
|
|
58
|
+
async sign(data) {
|
|
59
|
+
const key = await this.importKey();
|
|
60
|
+
const algorithm = this.getSigningAlgorithm();
|
|
61
|
+
return ApiKey.convertBufferToString(await crypto.subtle.sign(ApiKey.ALGORITHMS[algorithm].signatureAlgorithm, key, ApiKey.createByteArrayFromString(data)));
|
|
62
|
+
}
|
|
63
|
+
getSigningAlgorithm() {
|
|
64
|
+
const { algorithm } = this.getParsedPrivateKey();
|
|
65
|
+
return algorithm;
|
|
66
|
+
}
|
|
67
|
+
importKey() {
|
|
68
|
+
const { algorithm, encodedKey } = this.getParsedPrivateKey();
|
|
69
|
+
if (this.importedKey === undefined) {
|
|
70
|
+
this.importedKey = crypto.subtle
|
|
71
|
+
.importKey('pkcs8', ApiKey.createByteArrayFromString(atob(encodedKey)), ApiKey.ALGORITHMS[algorithm].keyAlgorithm, false, ['sign']);
|
|
72
|
+
}
|
|
73
|
+
return this.importedKey;
|
|
74
|
+
}
|
|
75
|
+
getParsedPrivateKey() {
|
|
76
|
+
if (this.privateKey === undefined) {
|
|
77
|
+
throw new Error('The API key does not have a private key.');
|
|
78
|
+
}
|
|
79
|
+
return this.privateKey;
|
|
77
80
|
}
|
|
78
81
|
export() {
|
|
79
|
-
|
|
80
|
-
return this.identifier + (privateKey === null ? '' : `:${privateKey}`);
|
|
82
|
+
return this.identifier + (this.hasPrivateKey() ? `:${this.getPrivateKey()}` : '');
|
|
81
83
|
}
|
|
82
84
|
toString() {
|
|
83
85
|
return '[redacted]';
|
|
84
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Create an array buffer from a string.
|
|
89
|
+
*
|
|
90
|
+
* @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
|
|
91
|
+
*
|
|
92
|
+
* @param data The string to convert.
|
|
93
|
+
* @returns The array buffer.
|
|
94
|
+
*/
|
|
95
|
+
static createByteArrayFromString(data) {
|
|
96
|
+
const byteArray = new Uint8Array(data.length);
|
|
97
|
+
for (let i = 0; i < byteArray.length; i++) {
|
|
98
|
+
byteArray[i] = data.charCodeAt(i);
|
|
99
|
+
}
|
|
100
|
+
return byteArray;
|
|
101
|
+
}
|
|
102
|
+
static createByteArrayFromHexString(data) {
|
|
103
|
+
const byteArray = new Uint8Array(data.length / 2);
|
|
104
|
+
for (let i = 0; i < byteArray.length; i++) {
|
|
105
|
+
byteArray[i] = parseInt(data.substring(i * 2, i * 2 + 2), 16);
|
|
106
|
+
}
|
|
107
|
+
return byteArray;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Convert an array buffer to a string.
|
|
111
|
+
*
|
|
112
|
+
* @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
|
|
113
|
+
*
|
|
114
|
+
* @param buffer The buffer to convert.
|
|
115
|
+
* @returns The string.
|
|
116
|
+
*/
|
|
117
|
+
static convertBufferToString(buffer) {
|
|
118
|
+
return String.fromCharCode(...new Uint8Array(buffer));
|
|
119
|
+
}
|
|
120
|
+
static convertBufferToHexString(buffer) {
|
|
121
|
+
const bytes = new Uint8Array(buffer);
|
|
122
|
+
let hexString = '';
|
|
123
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
124
|
+
hexString += bytes[i].toString(16).padStart(2, '0');
|
|
125
|
+
}
|
|
126
|
+
return hexString;
|
|
127
|
+
}
|
|
85
128
|
}
|
|
86
129
|
exports.ApiKey = ApiKey;
|
|
87
130
|
ApiKey.IDENTIFIER_PATTERN = /^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i;
|
|
88
|
-
ApiKey.PRIVATE_KEY_PATTERN = /^[a-
|
|
131
|
+
ApiKey.PRIVATE_KEY_PATTERN = /^[a-z0-9]+;[^;]+$/i;
|
|
132
|
+
ApiKey.ALGORITHMS = {
|
|
133
|
+
ES256: {
|
|
134
|
+
keyAlgorithm: {
|
|
135
|
+
name: 'ECDSA',
|
|
136
|
+
namedCurve: 'P-256',
|
|
137
|
+
},
|
|
138
|
+
signatureAlgorithm: {
|
|
139
|
+
name: 'ECDSA',
|
|
140
|
+
hash: 'SHA-256',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
};
|
|
89
144
|
//# sourceMappingURL=apiKey.js.map
|
package/apiKey.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiKey.js","sourceRoot":"","sources":["src/apiKey.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"apiKey.js","sourceRoot":"","sources":["src/apiKey.ts"],"names":[],"mappings":"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"}
|
package/base64Url.d.ts
ADDED
package/base64Url.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.base64UrlDecode = exports.base64UrlEncode = void 0;
|
|
4
|
+
function base64Unescape(value) {
|
|
5
|
+
return (value + '==='.slice((value.length + 3) % 4)).replace(/-/g, '+').replace(/_/g, '/');
|
|
6
|
+
}
|
|
7
|
+
function base64Escape(value) {
|
|
8
|
+
return value
|
|
9
|
+
.replace(/\+/g, '-')
|
|
10
|
+
.replace(/\//g, '_')
|
|
11
|
+
.replace(/=/g, '');
|
|
12
|
+
}
|
|
13
|
+
function base64UrlEncode(value, utf8 = false) {
|
|
14
|
+
return utf8
|
|
15
|
+
? base64Escape(btoa(String.fromCodePoint(...new TextEncoder().encode(value))))
|
|
16
|
+
: base64Escape(btoa(value));
|
|
17
|
+
}
|
|
18
|
+
exports.base64UrlEncode = base64UrlEncode;
|
|
19
|
+
function base64UrlDecode(value, utf8 = false) {
|
|
20
|
+
return utf8
|
|
21
|
+
? new TextDecoder().decode(Uint8Array.from(atob(base64Unescape(value)), m => m.codePointAt(0)))
|
|
22
|
+
: atob(base64Unescape(value));
|
|
23
|
+
}
|
|
24
|
+
exports.base64UrlDecode = base64UrlDecode;
|
|
25
|
+
//# sourceMappingURL=base64Url.js.map
|
package/base64Url.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64Url.js","sourceRoot":"","sources":["src/base64Url.ts"],"names":[],"mappings":";;;AAAA,SAAS,cAAc,CAAC,KAAa;IACjC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IAC/B,OAAO,KAAK;SACP,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED,SAAgB,eAAe,CAAC,KAAa,EAAE,IAAI,GAAG,KAAK;IACvD,OAAO,IAAI;QACP,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9E,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACpC,CAAC;AAJD,0CAIC;AAED,SAAgB,eAAe,CAAC,KAAa,EAAE,IAAI,GAAG,KAAK;IACvD,OAAO,IAAI;QACP,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,CAAC;QAChG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AACtC,CAAC;AAJD,0CAIC"}
|
package/constants.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const BASE_ENDPOINT_URL = "https://api.croct.io";
|
|
2
2
|
export declare const MAX_QUERY_LENGTH: number;
|
|
3
|
-
export declare const VERSION = "0.
|
|
4
|
-
export declare const CLIENT_LIBRARY = "Croct SDK JS v0.
|
|
3
|
+
export declare const VERSION = "0.16.1";
|
|
4
|
+
export declare const CLIENT_LIBRARY = "Croct SDK JS v0.16.1";
|
package/constants.js
CHANGED
|
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CLIENT_LIBRARY = exports.VERSION = exports.MAX_QUERY_LENGTH = exports.BASE_ENDPOINT_URL = void 0;
|
|
4
4
|
exports.BASE_ENDPOINT_URL = 'https://api.croct.io';
|
|
5
5
|
exports.MAX_QUERY_LENGTH = 500;
|
|
6
|
-
exports.VERSION = '0.
|
|
6
|
+
exports.VERSION = '0.16.1';
|
|
7
7
|
exports.CLIENT_LIBRARY = `Croct SDK JS v${exports.VERSION}`;
|
|
8
8
|
//# sourceMappingURL=constants.js.map
|
package/logging/index.d.ts
CHANGED
package/logging/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NullLogger = exports.NamespacedLogger = exports.ConsoleLogger = void 0;
|
|
3
|
+
exports.FilteredLogger = exports.NullLogger = exports.NamespacedLogger = exports.ConsoleLogger = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
tslib_1.__exportStar(require("./logger"), exports);
|
|
6
6
|
var consoleLogger_1 = require("./consoleLogger");
|
|
@@ -9,4 +9,6 @@ var namespacedLogger_1 = require("./namespacedLogger");
|
|
|
9
9
|
Object.defineProperty(exports, "NamespacedLogger", { enumerable: true, get: function () { return namespacedLogger_1.NamespacedLogger; } });
|
|
10
10
|
var nullLogger_1 = require("./nullLogger");
|
|
11
11
|
Object.defineProperty(exports, "NullLogger", { enumerable: true, get: function () { return nullLogger_1.NullLogger; } });
|
|
12
|
+
var filteredLogger_1 = require("./filteredLogger");
|
|
13
|
+
Object.defineProperty(exports, "FilteredLogger", { enumerable: true, get: function () { return filteredLogger_1.FilteredLogger; } });
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/logging/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/logging/index.ts"],"names":[],"mappings":";;;;AAAA,mDAAyB;AACzB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,uDAAoD;AAA5C,oHAAA,gBAAgB,OAAA;AACxB,2CAAwC;AAAhC,wGAAA,UAAU,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/logging/index.ts"],"names":[],"mappings":";;;;AAAA,mDAAyB;AACzB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,uDAAoD;AAA5C,oHAAA,gBAAgB,OAAA;AACxB,2CAAwC;AAAhC,wGAAA,UAAU,OAAA;AAClB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@croct/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "Croct SDK for JavaScript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@croct/json": "^2.0.1",
|
|
32
|
-
"js-base64": "^3.7.7",
|
|
33
32
|
"tslib": "^2.5.0"
|
|
34
33
|
},
|
|
35
34
|
"devDependencies": {
|
package/src/apiKey.ts
CHANGED
|
@@ -1,16 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export type ParsedPrivateKey = {
|
|
2
|
+
algorithm: string,
|
|
3
|
+
encodedKey: string,
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type Algorithm = {
|
|
7
|
+
keyAlgorithm: EcKeyImportParams,
|
|
8
|
+
signatureAlgorithm: EcdsaParams,
|
|
9
|
+
};
|
|
3
10
|
|
|
4
11
|
export class ApiKey {
|
|
5
12
|
private static readonly IDENTIFIER_PATTERN = /^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i;
|
|
6
13
|
|
|
7
|
-
private static readonly PRIVATE_KEY_PATTERN = /^[a-
|
|
14
|
+
private static readonly PRIVATE_KEY_PATTERN = /^[a-z0-9]+;[^;]+$/i;
|
|
15
|
+
|
|
16
|
+
private static readonly ALGORITHMS: Record<string, Algorithm> = {
|
|
17
|
+
ES256: {
|
|
18
|
+
keyAlgorithm: {
|
|
19
|
+
name: 'ECDSA',
|
|
20
|
+
namedCurve: 'P-256',
|
|
21
|
+
},
|
|
22
|
+
signatureAlgorithm: {
|
|
23
|
+
name: 'ECDSA',
|
|
24
|
+
hash: 'SHA-256',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
8
28
|
|
|
9
29
|
private readonly identifier: string;
|
|
10
30
|
|
|
11
|
-
private readonly privateKey?:
|
|
31
|
+
private readonly privateKey?: ParsedPrivateKey;
|
|
32
|
+
|
|
33
|
+
private importedKey: Promise<CryptoKey>;
|
|
12
34
|
|
|
13
|
-
private constructor(identifier: string, privateKey?:
|
|
35
|
+
private constructor(identifier: string, privateKey?: ParsedPrivateKey) {
|
|
14
36
|
this.identifier = identifier;
|
|
15
37
|
this.privateKey = privateKey;
|
|
16
38
|
}
|
|
@@ -35,26 +57,27 @@ export class ApiKey {
|
|
|
35
57
|
|
|
36
58
|
public static of(identifier: string, privateKey?: string): ApiKey {
|
|
37
59
|
if (!ApiKey.IDENTIFIER_PATTERN.test(identifier)) {
|
|
38
|
-
throw new Error('The
|
|
60
|
+
throw new Error('The identifier must be a UUID.');
|
|
39
61
|
}
|
|
40
62
|
|
|
41
|
-
if (privateKey === undefined) {
|
|
63
|
+
if (privateKey === undefined || privateKey === '') {
|
|
42
64
|
return new ApiKey(identifier);
|
|
43
65
|
}
|
|
44
66
|
|
|
45
67
|
if (!ApiKey.PRIVATE_KEY_PATTERN.test(privateKey)) {
|
|
46
|
-
throw new Error('The
|
|
68
|
+
throw new Error('The private key is malformed.');
|
|
47
69
|
}
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
type: 'pkcs8',
|
|
54
|
-
}));
|
|
55
|
-
} catch {
|
|
56
|
-
throw new Error('Invalid private key.');
|
|
71
|
+
const [algorithmName, encodedKey] = privateKey.split(';');
|
|
72
|
+
|
|
73
|
+
if (!(algorithmName in ApiKey.ALGORITHMS)) {
|
|
74
|
+
throw new Error(`Unsupported signing algorithm "${algorithmName}".`);
|
|
57
75
|
}
|
|
76
|
+
|
|
77
|
+
return new ApiKey(identifier, {
|
|
78
|
+
algorithm: algorithmName,
|
|
79
|
+
encodedKey: encodedKey,
|
|
80
|
+
});
|
|
58
81
|
}
|
|
59
82
|
|
|
60
83
|
public getIdentifier(): string {
|
|
@@ -62,49 +85,124 @@ export class ApiKey {
|
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
public async getIdentifierHash(): Promise<string> {
|
|
65
|
-
const identifierBytes =
|
|
88
|
+
const identifierBytes = ApiKey.createByteArrayFromHexString(this.identifier.replace(/-/g, ''));
|
|
66
89
|
const rawHash = await crypto.subtle.digest('SHA-256', identifierBytes);
|
|
67
90
|
|
|
68
|
-
return
|
|
91
|
+
return ApiKey.convertBufferToHexString(rawHash);
|
|
69
92
|
}
|
|
70
93
|
|
|
71
94
|
public hasPrivateKey(): boolean {
|
|
72
95
|
return this.privateKey !== undefined;
|
|
73
96
|
}
|
|
74
97
|
|
|
75
|
-
public getPrivateKey(): string
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
98
|
+
public getPrivateKey(): string {
|
|
99
|
+
if (this.privateKey === undefined) {
|
|
100
|
+
throw new Error('The API key does not have a private key.');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return `${this.privateKey.algorithm};${this.privateKey.encodedKey}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public async sign(data: string): Promise<string> {
|
|
107
|
+
const key = await this.importKey();
|
|
108
|
+
const algorithm = this.getSigningAlgorithm();
|
|
109
|
+
|
|
110
|
+
return ApiKey.convertBufferToString(
|
|
111
|
+
await crypto.subtle.sign(
|
|
112
|
+
ApiKey.ALGORITHMS[algorithm].signatureAlgorithm,
|
|
113
|
+
key,
|
|
114
|
+
ApiKey.createByteArrayFromString(data),
|
|
115
|
+
),
|
|
116
|
+
);
|
|
81
117
|
}
|
|
82
118
|
|
|
83
|
-
public
|
|
84
|
-
const {
|
|
119
|
+
public getSigningAlgorithm(): string {
|
|
120
|
+
const {algorithm} = this.getParsedPrivateKey();
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
122
|
+
return algorithm;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private importKey(): Promise<CryptoKey> {
|
|
126
|
+
const {algorithm, encodedKey} = this.getParsedPrivateKey();
|
|
127
|
+
|
|
128
|
+
if (this.importedKey === undefined) {
|
|
129
|
+
this.importedKey = crypto.subtle
|
|
130
|
+
.importKey(
|
|
131
|
+
'pkcs8',
|
|
132
|
+
ApiKey.createByteArrayFromString(atob(encodedKey)),
|
|
133
|
+
ApiKey.ALGORITHMS[algorithm].keyAlgorithm,
|
|
134
|
+
false,
|
|
135
|
+
['sign'],
|
|
136
|
+
);
|
|
88
137
|
}
|
|
89
138
|
|
|
90
|
-
return
|
|
91
|
-
crypto.sign(null, blob, privateKey, (error, signature) => {
|
|
92
|
-
if (error == null) {
|
|
93
|
-
resolve(signature);
|
|
94
|
-
} else {
|
|
95
|
-
reject(error);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
});
|
|
139
|
+
return this.importedKey;
|
|
99
140
|
}
|
|
100
141
|
|
|
101
|
-
|
|
102
|
-
|
|
142
|
+
private getParsedPrivateKey(): ParsedPrivateKey {
|
|
143
|
+
if (this.privateKey === undefined) {
|
|
144
|
+
throw new Error('The API key does not have a private key.');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return this.privateKey;
|
|
148
|
+
}
|
|
103
149
|
|
|
104
|
-
|
|
150
|
+
public export(): string {
|
|
151
|
+
return this.identifier + (this.hasPrivateKey() ? `:${this.getPrivateKey()}` : '');
|
|
105
152
|
}
|
|
106
153
|
|
|
107
154
|
public toString(): string {
|
|
108
155
|
return '[redacted]';
|
|
109
156
|
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Create an array buffer from a string.
|
|
160
|
+
*
|
|
161
|
+
* @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
|
|
162
|
+
*
|
|
163
|
+
* @param data The string to convert.
|
|
164
|
+
* @returns The array buffer.
|
|
165
|
+
*/
|
|
166
|
+
private static createByteArrayFromString(data: string): Uint8Array {
|
|
167
|
+
const byteArray = new Uint8Array(data.length);
|
|
168
|
+
|
|
169
|
+
for (let i = 0; i < byteArray.length; i++) {
|
|
170
|
+
byteArray[i] = data.charCodeAt(i);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return byteArray;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private static createByteArrayFromHexString(data: string): Uint8Array {
|
|
177
|
+
const byteArray = new Uint8Array(data.length / 2);
|
|
178
|
+
|
|
179
|
+
for (let i = 0; i < byteArray.length; i++) {
|
|
180
|
+
byteArray[i] = parseInt(data.substring(i * 2, i * 2 + 2), 16);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return byteArray;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Convert an array buffer to a string.
|
|
188
|
+
*
|
|
189
|
+
* @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
|
|
190
|
+
*
|
|
191
|
+
* @param buffer The buffer to convert.
|
|
192
|
+
* @returns The string.
|
|
193
|
+
*/
|
|
194
|
+
private static convertBufferToString(buffer: ArrayLike<number> | ArrayBufferLike): string {
|
|
195
|
+
return String.fromCharCode(...new Uint8Array(buffer));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private static convertBufferToHexString(buffer: ArrayLike<number> | ArrayBufferLike): string {
|
|
199
|
+
const bytes = new Uint8Array(buffer);
|
|
200
|
+
let hexString = '';
|
|
201
|
+
|
|
202
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
203
|
+
hexString += bytes[i].toString(16).padStart(2, '0');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return hexString;
|
|
207
|
+
}
|
|
110
208
|
}
|
package/src/base64Url.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function base64Unescape(value: string): string {
|
|
2
|
+
return (value + '==='.slice((value.length + 3) % 4)).replace(/-/g, '+').replace(/_/g, '/');
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function base64Escape(value: string): string {
|
|
6
|
+
return value
|
|
7
|
+
.replace(/\+/g, '-')
|
|
8
|
+
.replace(/\//g, '_')
|
|
9
|
+
.replace(/=/g, '');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function base64UrlEncode(value: string, utf8 = false): string {
|
|
13
|
+
return utf8
|
|
14
|
+
? base64Escape(btoa(String.fromCodePoint(...new TextEncoder().encode(value))))
|
|
15
|
+
: base64Escape(btoa(value));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function base64UrlDecode(value: string, utf8 = false): string {
|
|
19
|
+
return utf8
|
|
20
|
+
? new TextDecoder().decode(Uint8Array.from(atob(base64Unescape(value)), m => m.codePointAt(0)!))
|
|
21
|
+
: atob(base64Unescape(value));
|
|
22
|
+
}
|
package/src/logging/index.ts
CHANGED
package/src/token/token.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {JsonObject} from '@croct/json';
|
|
2
|
-
import {encodeURI as base64Encode, decode as base64Decode} from 'js-base64';
|
|
3
2
|
import {tokenSchema} from '../schema';
|
|
4
3
|
import {formatCause} from '../error';
|
|
5
4
|
import {ApiKey} from '../apiKey';
|
|
5
|
+
import {base64UrlDecode, base64UrlEncode} from '../base64Url';
|
|
6
6
|
|
|
7
|
-
export type
|
|
7
|
+
export type TokenHeaders = {
|
|
8
8
|
typ: string,
|
|
9
9
|
alg: string,
|
|
10
10
|
kid?: string,
|
|
11
11
|
appId?: string,
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
type
|
|
14
|
+
export type TokenClaims = {
|
|
15
15
|
iss: string,
|
|
16
16
|
aud: string|string[],
|
|
17
17
|
iat: number,
|
|
@@ -20,18 +20,18 @@ type Claims = {
|
|
|
20
20
|
jti?: string,
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
export type TokenPayload = JsonObject &
|
|
23
|
+
export type TokenPayload = JsonObject & TokenClaims;
|
|
24
24
|
|
|
25
25
|
export class Token {
|
|
26
26
|
private static readonly UUID_PATTERN = /^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/;
|
|
27
27
|
|
|
28
|
-
private readonly headers:
|
|
28
|
+
private readonly headers: TokenHeaders;
|
|
29
29
|
|
|
30
30
|
private readonly payload: TokenPayload;
|
|
31
31
|
|
|
32
32
|
private readonly signature: string;
|
|
33
33
|
|
|
34
|
-
private constructor(headers:
|
|
34
|
+
private constructor(headers: TokenHeaders, payload: TokenPayload, signature = '') {
|
|
35
35
|
this.headers = headers;
|
|
36
36
|
this.payload = payload;
|
|
37
37
|
this.signature = signature;
|
|
@@ -81,8 +81,8 @@ export class Token {
|
|
|
81
81
|
let payload;
|
|
82
82
|
|
|
83
83
|
try {
|
|
84
|
-
headers = JSON.parse(
|
|
85
|
-
payload = JSON.parse(
|
|
84
|
+
headers = JSON.parse(base64UrlDecode(parts[0], true));
|
|
85
|
+
payload = JSON.parse(base64UrlDecode(parts[1], true));
|
|
86
86
|
} catch (error) {
|
|
87
87
|
throw new Error('The token is corrupted.');
|
|
88
88
|
}
|
|
@@ -90,7 +90,7 @@ export class Token {
|
|
|
90
90
|
return Token.of(headers, payload, parts[2]);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
public static of(headers:
|
|
93
|
+
public static of(headers: TokenHeaders, payload: TokenPayload, signature = ''): Token {
|
|
94
94
|
try {
|
|
95
95
|
tokenSchema.validate({
|
|
96
96
|
headers: headers,
|
|
@@ -101,23 +101,22 @@ export class Token {
|
|
|
101
101
|
throw new Error(`The token is invalid: ${formatCause(violation)}`);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
return new Token(headers as
|
|
104
|
+
return new Token(headers as TokenHeaders, payload as TokenPayload, signature as string);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
public async signedWith(apiKey: ApiKey): Promise<Token> {
|
|
108
108
|
const keyId = await apiKey.getIdentifierHash();
|
|
109
|
-
const headers:
|
|
109
|
+
const headers: TokenHeaders = {
|
|
110
110
|
...this.headers,
|
|
111
111
|
kid: keyId,
|
|
112
|
-
alg:
|
|
112
|
+
alg: apiKey.getSigningAlgorithm(),
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
const encodedHeader =
|
|
116
|
-
const encodedPayload =
|
|
117
|
-
const
|
|
118
|
-
const signature = await apiKey.sign(Buffer.from(signatureData, 'utf-8'));
|
|
115
|
+
const encodedHeader = base64UrlEncode(JSON.stringify(headers), true);
|
|
116
|
+
const encodedPayload = base64UrlEncode(JSON.stringify(this.payload), true);
|
|
117
|
+
const signature = await apiKey.sign(`${encodedHeader}.${encodedPayload}`);
|
|
119
118
|
|
|
120
|
-
return new Token(headers, this.payload, signature
|
|
119
|
+
return new Token(headers, this.payload, base64UrlEncode(signature, false));
|
|
121
120
|
}
|
|
122
121
|
|
|
123
122
|
public isSigned(): boolean {
|
|
@@ -146,22 +145,7 @@ export class Token {
|
|
|
146
145
|
return this.headers.kid === await apiKey.getIdentifierHash();
|
|
147
146
|
}
|
|
148
147
|
|
|
149
|
-
public
|
|
150
|
-
if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
|
|
151
|
-
throw new Error('The token ID must be a valid UUID.');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return new Token(
|
|
155
|
-
this.headers,
|
|
156
|
-
{
|
|
157
|
-
...this.payload,
|
|
158
|
-
jti: tokenId,
|
|
159
|
-
},
|
|
160
|
-
this.signature,
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public getHeaders(): Headers {
|
|
148
|
+
public getHeaders(): TokenHeaders {
|
|
165
149
|
return {...this.headers};
|
|
166
150
|
}
|
|
167
151
|
|
|
@@ -213,13 +197,84 @@ export class Token {
|
|
|
213
197
|
return this.payload.iss;
|
|
214
198
|
}
|
|
215
199
|
|
|
200
|
+
public withTokenId(tokenId: string): Token {
|
|
201
|
+
if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
|
|
202
|
+
throw new Error('The token ID must be a valid UUID.');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return new Token(
|
|
206
|
+
this.headers,
|
|
207
|
+
{
|
|
208
|
+
...this.payload,
|
|
209
|
+
jti: tokenId,
|
|
210
|
+
},
|
|
211
|
+
this.signature,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
public withDuration(duration: number, now: number = Math.floor(Date.now() / 1000)): Token {
|
|
216
|
+
return new Token(
|
|
217
|
+
this.headers,
|
|
218
|
+
{
|
|
219
|
+
...this.payload,
|
|
220
|
+
iat: now,
|
|
221
|
+
exp: now + duration,
|
|
222
|
+
},
|
|
223
|
+
this.signature,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public withAddedHeaders(headers: Partial<TokenHeaders>): Token {
|
|
228
|
+
return this.withHeaders({
|
|
229
|
+
...this.headers,
|
|
230
|
+
...Object.fromEntries(
|
|
231
|
+
Object.entries(headers)
|
|
232
|
+
.filter(([, value]) => value !== undefined),
|
|
233
|
+
),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
public withAddedClaims(claims: Partial<TokenClaims>): Token {
|
|
238
|
+
return this.withPayload({
|
|
239
|
+
...this.payload,
|
|
240
|
+
...Object.fromEntries(
|
|
241
|
+
Object.entries(claims)
|
|
242
|
+
.filter(([, value]) => value !== undefined),
|
|
243
|
+
),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
public withHeaders(headers: TokenHeaders): Token {
|
|
248
|
+
return new Token(
|
|
249
|
+
headers,
|
|
250
|
+
this.payload,
|
|
251
|
+
this.signature,
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
public withPayload(payload: TokenPayload): Token {
|
|
256
|
+
return new Token(
|
|
257
|
+
this.headers,
|
|
258
|
+
payload,
|
|
259
|
+
this.signature,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
public withSignature(signature: string): Token {
|
|
264
|
+
return new Token(
|
|
265
|
+
this.headers,
|
|
266
|
+
this.payload,
|
|
267
|
+
signature,
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
216
271
|
public toJSON(): string {
|
|
217
272
|
return this.toString();
|
|
218
273
|
}
|
|
219
274
|
|
|
220
275
|
public toString(): string {
|
|
221
|
-
const headers =
|
|
222
|
-
const payload =
|
|
276
|
+
const headers = base64UrlEncode(JSON.stringify(this.headers), true);
|
|
277
|
+
const payload = base64UrlEncode(JSON.stringify(this.payload), true);
|
|
223
278
|
|
|
224
279
|
return `${headers}.${payload}.${this.signature}`;
|
|
225
280
|
}
|
package/token/token.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { JsonObject } from '@croct/json';
|
|
2
2
|
import { ApiKey } from '../apiKey';
|
|
3
|
-
export type
|
|
3
|
+
export type TokenHeaders = {
|
|
4
4
|
typ: string;
|
|
5
5
|
alg: string;
|
|
6
6
|
kid?: string;
|
|
7
7
|
appId?: string;
|
|
8
8
|
};
|
|
9
|
-
type
|
|
9
|
+
export type TokenClaims = {
|
|
10
10
|
iss: string;
|
|
11
11
|
aud: string | string[];
|
|
12
12
|
iat: number;
|
|
@@ -14,7 +14,7 @@ type Claims = {
|
|
|
14
14
|
sub?: string;
|
|
15
15
|
jti?: string;
|
|
16
16
|
};
|
|
17
|
-
export type TokenPayload = JsonObject &
|
|
17
|
+
export type TokenPayload = JsonObject & TokenClaims;
|
|
18
18
|
export declare class Token {
|
|
19
19
|
private static readonly UUID_PATTERN;
|
|
20
20
|
private readonly headers;
|
|
@@ -23,7 +23,7 @@ export declare class Token {
|
|
|
23
23
|
private constructor();
|
|
24
24
|
static issue(appId: string, subject?: string | null, timestamp?: number): Token;
|
|
25
25
|
static parse(token: string): Token;
|
|
26
|
-
static of(headers:
|
|
26
|
+
static of(headers: TokenHeaders, payload: TokenPayload, signature?: string): Token;
|
|
27
27
|
signedWith(apiKey: ApiKey): Promise<Token>;
|
|
28
28
|
isSigned(): boolean;
|
|
29
29
|
isSubject(subject: string): boolean;
|
|
@@ -31,8 +31,7 @@ export declare class Token {
|
|
|
31
31
|
isValidNow(now?: number): boolean;
|
|
32
32
|
isNewerThan(token: Token): boolean;
|
|
33
33
|
matchesKeyId(apiKey: ApiKey): Promise<boolean>;
|
|
34
|
-
|
|
35
|
-
getHeaders(): Headers;
|
|
34
|
+
getHeaders(): TokenHeaders;
|
|
36
35
|
getPayload(): TokenPayload;
|
|
37
36
|
getSignature(): string;
|
|
38
37
|
getApplicationId(): string | null;
|
|
@@ -45,6 +44,13 @@ export declare class Token {
|
|
|
45
44
|
getTokenId(): string | null;
|
|
46
45
|
getAudience(): string | string[];
|
|
47
46
|
getIssuer(): string;
|
|
47
|
+
withTokenId(tokenId: string): Token;
|
|
48
|
+
withDuration(duration: number, now?: number): Token;
|
|
49
|
+
withAddedHeaders(headers: Partial<TokenHeaders>): Token;
|
|
50
|
+
withAddedClaims(claims: Partial<TokenClaims>): Token;
|
|
51
|
+
withHeaders(headers: TokenHeaders): Token;
|
|
52
|
+
withPayload(payload: TokenPayload): Token;
|
|
53
|
+
withSignature(signature: string): Token;
|
|
48
54
|
toJSON(): string;
|
|
49
55
|
toString(): string;
|
|
50
56
|
}
|
|
@@ -59,4 +65,3 @@ export declare class FixedTokenProvider implements TokenProvider {
|
|
|
59
65
|
constructor(token: Token | null);
|
|
60
66
|
getToken(): Token | null;
|
|
61
67
|
}
|
|
62
|
-
export {};
|
package/token/token.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FixedTokenProvider = exports.Token = void 0;
|
|
4
|
-
const js_base64_1 = require("js-base64");
|
|
5
4
|
const schema_1 = require("../schema");
|
|
6
5
|
const error_1 = require("../error");
|
|
6
|
+
const base64Url_1 = require("../base64Url");
|
|
7
7
|
class Token {
|
|
8
8
|
constructor(headers, payload, signature = '') {
|
|
9
9
|
this.headers = headers;
|
|
@@ -40,8 +40,8 @@ class Token {
|
|
|
40
40
|
let headers;
|
|
41
41
|
let payload;
|
|
42
42
|
try {
|
|
43
|
-
headers = JSON.parse((0,
|
|
44
|
-
payload = JSON.parse((0,
|
|
43
|
+
headers = JSON.parse((0, base64Url_1.base64UrlDecode)(parts[0], true));
|
|
44
|
+
payload = JSON.parse((0, base64Url_1.base64UrlDecode)(parts[1], true));
|
|
45
45
|
}
|
|
46
46
|
catch (error) {
|
|
47
47
|
throw new Error('The token is corrupted.');
|
|
@@ -66,13 +66,12 @@ class Token {
|
|
|
66
66
|
const headers = {
|
|
67
67
|
...this.headers,
|
|
68
68
|
kid: keyId,
|
|
69
|
-
alg:
|
|
69
|
+
alg: apiKey.getSigningAlgorithm(),
|
|
70
70
|
};
|
|
71
|
-
const encodedHeader = (0,
|
|
72
|
-
const encodedPayload = (0,
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
return new Token(headers, this.payload, signature.toString('base64url'));
|
|
71
|
+
const encodedHeader = (0, base64Url_1.base64UrlEncode)(JSON.stringify(headers), true);
|
|
72
|
+
const encodedPayload = (0, base64Url_1.base64UrlEncode)(JSON.stringify(this.payload), true);
|
|
73
|
+
const signature = await apiKey.sign(`${encodedHeader}.${encodedPayload}`);
|
|
74
|
+
return new Token(headers, this.payload, (0, base64Url_1.base64UrlEncode)(signature, false));
|
|
76
75
|
}
|
|
77
76
|
isSigned() {
|
|
78
77
|
return this.headers.alg !== 'none' && this.signature !== '';
|
|
@@ -93,15 +92,6 @@ class Token {
|
|
|
93
92
|
async matchesKeyId(apiKey) {
|
|
94
93
|
return this.headers.kid === await apiKey.getIdentifierHash();
|
|
95
94
|
}
|
|
96
|
-
withTokenId(tokenId) {
|
|
97
|
-
if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
|
|
98
|
-
throw new Error('The token ID must be a valid UUID.');
|
|
99
|
-
}
|
|
100
|
-
return new Token(this.headers, {
|
|
101
|
-
...this.payload,
|
|
102
|
-
jti: tokenId,
|
|
103
|
-
}, this.signature);
|
|
104
|
-
}
|
|
105
95
|
getHeaders() {
|
|
106
96
|
return { ...this.headers };
|
|
107
97
|
}
|
|
@@ -146,12 +136,51 @@ class Token {
|
|
|
146
136
|
getIssuer() {
|
|
147
137
|
return this.payload.iss;
|
|
148
138
|
}
|
|
139
|
+
withTokenId(tokenId) {
|
|
140
|
+
if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
|
|
141
|
+
throw new Error('The token ID must be a valid UUID.');
|
|
142
|
+
}
|
|
143
|
+
return new Token(this.headers, {
|
|
144
|
+
...this.payload,
|
|
145
|
+
jti: tokenId,
|
|
146
|
+
}, this.signature);
|
|
147
|
+
}
|
|
148
|
+
withDuration(duration, now = Math.floor(Date.now() / 1000)) {
|
|
149
|
+
return new Token(this.headers, {
|
|
150
|
+
...this.payload,
|
|
151
|
+
iat: now,
|
|
152
|
+
exp: now + duration,
|
|
153
|
+
}, this.signature);
|
|
154
|
+
}
|
|
155
|
+
withAddedHeaders(headers) {
|
|
156
|
+
return this.withHeaders({
|
|
157
|
+
...this.headers,
|
|
158
|
+
...Object.fromEntries(Object.entries(headers)
|
|
159
|
+
.filter(([, value]) => value !== undefined)),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
withAddedClaims(claims) {
|
|
163
|
+
return this.withPayload({
|
|
164
|
+
...this.payload,
|
|
165
|
+
...Object.fromEntries(Object.entries(claims)
|
|
166
|
+
.filter(([, value]) => value !== undefined)),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
withHeaders(headers) {
|
|
170
|
+
return new Token(headers, this.payload, this.signature);
|
|
171
|
+
}
|
|
172
|
+
withPayload(payload) {
|
|
173
|
+
return new Token(this.headers, payload, this.signature);
|
|
174
|
+
}
|
|
175
|
+
withSignature(signature) {
|
|
176
|
+
return new Token(this.headers, this.payload, signature);
|
|
177
|
+
}
|
|
149
178
|
toJSON() {
|
|
150
179
|
return this.toString();
|
|
151
180
|
}
|
|
152
181
|
toString() {
|
|
153
|
-
const headers = (0,
|
|
154
|
-
const payload = (0,
|
|
182
|
+
const headers = (0, base64Url_1.base64UrlEncode)(JSON.stringify(this.headers), true);
|
|
183
|
+
const payload = (0, base64Url_1.base64UrlEncode)(JSON.stringify(this.payload), true);
|
|
155
184
|
return `${headers}.${payload}.${this.signature}`;
|
|
156
185
|
}
|
|
157
186
|
}
|
package/token/token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token/token.ts"],"names":[],"mappings":";;;AACA,
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token/token.ts"],"names":[],"mappings":"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"}
|