@openstax/ts-utils 1.1.32 → 1.1.34
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/cjs/services/authProvider/decryption.d.ts +5 -2
- package/dist/cjs/services/authProvider/decryption.js +2 -26
- package/dist/cjs/services/authProvider/index.d.ts +3 -3
- package/dist/cjs/services/authProvider/index.js +5 -5
- package/dist/cjs/services/authProvider/utils/decryptAndVerify.d.ts +2 -0
- package/dist/cjs/services/authProvider/utils/decryptAndVerify.js +66 -0
- package/dist/cjs/tsconfig.withoutspecs.cjs.tsbuildinfo +1 -1
- package/dist/esm/services/authProvider/decryption.d.ts +5 -2
- package/dist/esm/services/authProvider/decryption.js +2 -26
- package/dist/esm/services/authProvider/index.d.ts +3 -3
- package/dist/esm/services/authProvider/index.js +2 -2
- package/dist/esm/services/authProvider/utils/decryptAndVerify.d.ts +2 -0
- package/dist/esm/services/authProvider/utils/decryptAndVerify.js +36 -0
- package/dist/esm/tsconfig.withoutspecs.esm.tsbuildinfo +1 -1
- package/package.json +3 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ConfigProviderForConfig } from '../../config';
|
|
2
|
-
import { CookieAuthProvider } from '.';
|
|
1
|
+
import type { ConfigProviderForConfig } from '../../config';
|
|
2
|
+
import { CookieAuthProvider, User } from '.';
|
|
3
3
|
declare type Config = {
|
|
4
4
|
cookieName: string;
|
|
5
5
|
encryptionPrivateKey: string;
|
|
@@ -8,6 +8,9 @@ declare type Config = {
|
|
|
8
8
|
interface Initializer<C> {
|
|
9
9
|
configSpace?: C;
|
|
10
10
|
}
|
|
11
|
+
export declare type Jwt = {
|
|
12
|
+
sub?: User;
|
|
13
|
+
};
|
|
11
14
|
export declare const decryptionAuthProvider: <C extends string = "decryption">(initializer: Initializer<C>) => (configProvider: { [key in C]: {
|
|
12
15
|
cookieName: import("../../config").ConfigValueProvider<string>;
|
|
13
16
|
encryptionPrivateKey: import("../../config").ConfigValueProvider<string>;
|
|
@@ -1,29 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.decryptionAuthProvider = void 0;
|
|
4
|
-
const jose_1 = require("jose");
|
|
5
4
|
const resolveConfigValue_1 = require("../../config/resolveConfigValue");
|
|
6
5
|
const guards_1 = require("../../guards");
|
|
7
6
|
const helpers_1 = require("../../misc/helpers");
|
|
7
|
+
const decryptAndVerify_1 = require("./utils/decryptAndVerify");
|
|
8
8
|
const _1 = require(".");
|
|
9
9
|
const decryptionAuthProvider = (initializer) => (configProvider) => {
|
|
10
10
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'decryption')];
|
|
11
11
|
const cookieName = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.cookieName));
|
|
12
12
|
const encryptionPrivateKey = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.encryptionPrivateKey));
|
|
13
13
|
const signaturePublicKey = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.signaturePublicKey));
|
|
14
|
-
const decryptAndVerify = async (jwt) => {
|
|
15
|
-
try {
|
|
16
|
-
// Decrypt SSO cookie
|
|
17
|
-
const { plaintext } = await (0, jose_1.compactDecrypt)(jwt, Buffer.from(await encryptionPrivateKey()), // Note: Buffer.from() is node-js only
|
|
18
|
-
{ contentEncryptionAlgorithms: ['A256GCM'], keyManagementAlgorithms: ['dir'] });
|
|
19
|
-
// Verify SSO cookie signature
|
|
20
|
-
const { payload } = await (0, jose_1.compactVerify)(plaintext, await (0, jose_1.importSPKI)(await signaturePublicKey(), 'RS256'), { algorithms: ['RS256'] });
|
|
21
|
-
return payload;
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
14
|
return ({ request, profile }) => {
|
|
28
15
|
let user;
|
|
29
16
|
const getAuthorizedFetchConfig = profile.track('getAuthorizedFetchConfig', () => async () => {
|
|
@@ -38,18 +25,7 @@ const decryptionAuthProvider = (initializer) => (configProvider) => {
|
|
|
38
25
|
if (!token) {
|
|
39
26
|
return undefined;
|
|
40
27
|
}
|
|
41
|
-
|
|
42
|
-
if (!payload) {
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
// Note: Uint8Array.toString() returns text in node-js only
|
|
46
|
-
// The browser version is new TextDecoder().decode(payload)
|
|
47
|
-
const jwt = JSON.parse(payload.toString());
|
|
48
|
-
// Allow clock skew up to 5 minutes
|
|
49
|
-
if (!jwt.sub || !jwt.sub.uuid || (jwt.exp && jwt.exp < Math.floor(Date.now() / 1000) - 300)) {
|
|
50
|
-
return undefined;
|
|
51
|
-
}
|
|
52
|
-
return jwt.sub;
|
|
28
|
+
return (0, decryptAndVerify_1.decryptAndVerify)(token, await encryptionPrivateKey(), await signaturePublicKey());
|
|
53
29
|
});
|
|
54
30
|
return {
|
|
55
31
|
getAuthorizedFetchConfig,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FetchConfig } from '../../fetch';
|
|
2
|
-
import { Track } from '../../profile';
|
|
3
|
-
import { HttpHeaders } from '../../routing';
|
|
1
|
+
import type { FetchConfig } from '../../fetch';
|
|
2
|
+
import type { Track } from '../../profile';
|
|
3
|
+
import type { HttpHeaders } from '../../routing';
|
|
4
4
|
export interface User {
|
|
5
5
|
id: number;
|
|
6
6
|
name: string;
|
|
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getAuthTokenOrCookie = exports.stubAuthProvider = void 0;
|
|
7
7
|
const cookie_1 = __importDefault(require("cookie"));
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const helpers_1 = require("../../misc/helpers");
|
|
9
|
+
const helpers_2 = require("../../routing/helpers");
|
|
10
10
|
const stubAuthProvider = (user) => ({
|
|
11
11
|
getUser: () => Promise.resolve(user),
|
|
12
12
|
getAuthorizedFetchConfig: () => Promise.resolve(user ? { headers: { Authorization: user.uuid } } : {})
|
|
@@ -14,10 +14,10 @@ const stubAuthProvider = (user) => ({
|
|
|
14
14
|
exports.stubAuthProvider = stubAuthProvider;
|
|
15
15
|
const getAuthTokenOrCookie = (request, cookieName) => {
|
|
16
16
|
var _a;
|
|
17
|
-
const authHeader = (0,
|
|
17
|
+
const authHeader = (0, helpers_2.getHeader)(request.headers, 'authorization');
|
|
18
18
|
const cookieValue = cookie_1.default.parse(((_a = request.cookies) === null || _a === void 0 ? void 0 : _a.join('; ')) || '')[cookieName];
|
|
19
19
|
return authHeader && authHeader.length >= 8 && authHeader.startsWith('Bearer ')
|
|
20
|
-
? (0,
|
|
21
|
-
: (0,
|
|
20
|
+
? (0, helpers_1.tuple)(authHeader.slice(7), { Authorization: authHeader })
|
|
21
|
+
: (0, helpers_1.tuple)(cookieValue, { cookie: cookie_1.default.serialize(cookieName, cookieValue) });
|
|
22
22
|
};
|
|
23
23
|
exports.getAuthTokenOrCookie = getAuthTokenOrCookie;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.decryptAndVerify = void 0;
|
|
30
|
+
const crypto = __importStar(require("crypto"));
|
|
31
|
+
const util_1 = require("util");
|
|
32
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
33
|
+
const guards_1 = require("../../../guards");
|
|
34
|
+
const decrypt = (input, key) => {
|
|
35
|
+
const splitInput = input.split('.');
|
|
36
|
+
const aad = new util_1.TextEncoder().encode(splitInput[0]);
|
|
37
|
+
const iv = Buffer.from(splitInput[2], 'base64');
|
|
38
|
+
const ciphertext = Buffer.from(splitInput[3], 'base64');
|
|
39
|
+
const tag = Buffer.from(splitInput[4], 'base64');
|
|
40
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', Buffer.from(key), iv, { authTagLength: 16 });
|
|
41
|
+
decipher.setAAD(aad, { plaintextLength: ciphertext.length });
|
|
42
|
+
decipher.setAuthTag(tag);
|
|
43
|
+
const result = Buffer.concat([
|
|
44
|
+
decipher.update(ciphertext),
|
|
45
|
+
decipher.final(),
|
|
46
|
+
]);
|
|
47
|
+
return result.toString('utf-8');
|
|
48
|
+
};
|
|
49
|
+
const decryptAndVerify = (token, encryptionPrivateKey, signaturePublicKey) => {
|
|
50
|
+
try {
|
|
51
|
+
// Decrypt SSO cookie
|
|
52
|
+
const plaintext = decrypt(token, encryptionPrivateKey);
|
|
53
|
+
const payload = jsonwebtoken_1.default.verify(plaintext, signaturePublicKey, {
|
|
54
|
+
clockTolerance: 300 // 5 minutes
|
|
55
|
+
});
|
|
56
|
+
if (!(0, guards_1.isPlainObject)(payload) || !(0, guards_1.isPlainObject)(payload.sub) || !payload.sub.uuid) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
// TS is confused because the library types the `sub` as a string
|
|
60
|
+
return payload.sub;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
exports.decryptAndVerify = decryptAndVerify;
|