dce-reactkit 3.12.1-beta-cross-server.2 → 3.12.1-beta-cross-server.3

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Sign data with a private reactkit key, package it into a signed data pack
2
+ * Sign a request and get the new request params
3
3
  * @author Gabe Abrams
4
4
  * @param opts object containing all arguments
5
5
  * @param opts.method the method to sign
@@ -7,9 +7,9 @@
7
7
  * @param opts.params the data in the body to sign
8
8
  * @param opts.key the reactkit key to sign with
9
9
  * @param opts.secret the reactkit secret to sign with
10
- * @return the signed data
10
+ * @return augmented params for the request, including a signature, timestamp, and key
11
11
  */
12
- export declare const createSignedPack: (opts: {
12
+ export declare const signRequest: (opts: {
13
13
  method: string;
14
14
  path: string;
15
15
  params: {
@@ -17,22 +17,24 @@ export declare const createSignedPack: (opts: {
17
17
  };
18
18
  key: string;
19
19
  secret: string;
20
- }) => string;
20
+ }) => Promise<{
21
+ [key: string]: any;
22
+ }>;
21
23
  /**
22
- * Parse signed pack. Throws an error if invalid
24
+ * Validate a signed request. Throws an error if invalid
23
25
  * @author Gabe Abrams
24
26
  * @param opts object containing all arguments
25
27
  * @param opts.method the method of the data validate
26
28
  * @param opts.path the http request path to validate
27
29
  * @param opts.scope the name of the scope to validate
28
- * @param opts.signedPack the signed data pack to validate
30
+ * @param opts.params the request data to validate
29
31
  * @returns parsed and validated params
30
32
  */
31
- export declare const parseSignedPack: (opts: {
33
+ export declare const validateSignedRequest: (opts: {
32
34
  method: string;
33
35
  path: string;
34
36
  scope: string;
35
- signedPack: string;
36
- }) => Promise<{
37
- [key: string]: any;
38
- }>;
37
+ params: {
38
+ [key: string]: any;
39
+ };
40
+ }) => Promise<void>;
@@ -5,10 +5,6 @@
5
5
  * @param opts.method the method of the endpoint
6
6
  * @param opts.path the path of the other server's endpoint
7
7
  * @param opts.host the host of the other server
8
- * @param [opts.key=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_KEY] reactkit cross-server
9
- * credential key
10
- * @param [opts.secret=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_SECRET reactkit cross-server
11
- * credential secret
12
8
  * @param [opts.params={}] query/body parameters to include
13
9
  * @param [opts.responseType=JSON] the response type from the other server
14
10
  */
@@ -16,8 +12,6 @@ declare const visitEndpointOnAnotherServer: (opts: {
16
12
  method: 'GET' | 'POST' | 'DELETE' | 'PUT';
17
13
  path: string;
18
14
  host: string;
19
- key?: string | undefined;
20
- secret?: string | undefined;
21
15
  params?: {
22
16
  [x: string]: any;
23
17
  } | undefined;
@@ -21,17 +21,19 @@ declare enum ReactKitErrorCode {
21
21
  NotConnected = "DRK14",
22
22
  SelfSigned = "DRK15",
23
23
  ResponseParseError = "DRK16",
24
- PackUnparseable = "DRK28",
25
- PackInvalidMethod = "DRK19",
26
- PackInvalidPath = "DRK20",
27
- PackInvalidCollection = "DRK21",
28
- PackInvalidCredential = "DRK23",
29
- PackInvalidScope = "DRK22",
30
- PackInvalidTimestamp = "DRK24",
31
- PackInvalidSignature = "DRK25",
32
- PackInvalidBody = "DRK26",
24
+ SignedRequestUnparseable = "DRK28",
25
+ SignedRequestInvalidCollection = "DRK21",
26
+ SignedRequestInvalidCredential = "DRK23",
27
+ SignedRequestInvalidScope = "DRK22",
28
+ SignedRequestInvalidTimestamp = "DRK24",
29
+ SignedRequestInvalidSignature = "DRK25",
30
+ SignedRequestInvalidBody = "DRK26",
33
31
  CrossServerNoCredentialsToSignWith = "DRK27",
34
- CrossServerNoPack = "DRK29",
35
- CrossServerNoCredentialEncodingSalt = "DRK30"
32
+ CrossServerMissingSignedRequestInfo = "DRK29",
33
+ CrossServerNoCredentialEncodingSalt = "DRK30",
34
+ NoOauthLib = "DRK31",
35
+ NoCryptoLib = "DRK32",
36
+ InvalidCrossServerCredentialsFormat = "DRK33",
37
+ UnknownCrossServerError = "DRK34"
36
38
  }
37
39
  export default ReactKitErrorCode;
package/dist/index.d.ts CHANGED
@@ -1674,10 +1674,6 @@ declare const shuffleArray: <T>(arr: T[]) => T[];
1674
1674
  * @param opts.method the method of the endpoint
1675
1675
  * @param opts.path the path of the other server's endpoint
1676
1676
  * @param opts.host the host of the other server
1677
- * @param [opts.key=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_KEY] reactkit cross-server
1678
- * credential key
1679
- * @param [opts.secret=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_SECRET reactkit cross-server
1680
- * credential secret
1681
1677
  * @param [opts.params={}] query/body parameters to include
1682
1678
  * @param [opts.responseType=JSON] the response type from the other server
1683
1679
  */
@@ -1685,8 +1681,6 @@ declare const visitEndpointOnAnotherServer: (opts: {
1685
1681
  method: 'GET' | 'POST' | 'DELETE' | 'PUT';
1686
1682
  path: string;
1687
1683
  host: string;
1688
- key?: string | undefined;
1689
- secret?: string | undefined;
1690
1684
  params?: {
1691
1685
  [x: string]: any;
1692
1686
  } | undefined;
@@ -1716,18 +1710,20 @@ declare enum ReactKitErrorCode {
1716
1710
  NotConnected = "DRK14",
1717
1711
  SelfSigned = "DRK15",
1718
1712
  ResponseParseError = "DRK16",
1719
- PackUnparseable = "DRK28",
1720
- PackInvalidMethod = "DRK19",
1721
- PackInvalidPath = "DRK20",
1722
- PackInvalidCollection = "DRK21",
1723
- PackInvalidCredential = "DRK23",
1724
- PackInvalidScope = "DRK22",
1725
- PackInvalidTimestamp = "DRK24",
1726
- PackInvalidSignature = "DRK25",
1727
- PackInvalidBody = "DRK26",
1713
+ SignedRequestUnparseable = "DRK28",
1714
+ SignedRequestInvalidCollection = "DRK21",
1715
+ SignedRequestInvalidCredential = "DRK23",
1716
+ SignedRequestInvalidScope = "DRK22",
1717
+ SignedRequestInvalidTimestamp = "DRK24",
1718
+ SignedRequestInvalidSignature = "DRK25",
1719
+ SignedRequestInvalidBody = "DRK26",
1728
1720
  CrossServerNoCredentialsToSignWith = "DRK27",
1729
- CrossServerNoPack = "DRK29",
1730
- CrossServerNoCredentialEncodingSalt = "DRK30"
1721
+ CrossServerMissingSignedRequestInfo = "DRK29",
1722
+ CrossServerNoCredentialEncodingSalt = "DRK30",
1723
+ NoOauthLib = "DRK31",
1724
+ NoCryptoLib = "DRK32",
1725
+ InvalidCrossServerCredentialsFormat = "DRK33",
1726
+ UnknownCrossServerError = "DRK34"
1731
1727
  }
1732
1728
 
1733
1729
  /**
@@ -1,13 +1,26 @@
1
- // Import jwt
2
- import jwt from 'jwt-simple';
1
+ // Import crypto
2
+ import crypto from 'crypto';
3
+
4
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
3
5
 
4
6
  // Get args
5
- let { REACTKIT_CRED_ENCODING_SALT } = process.env;
7
+ const REACTKIT_CRED_ENCODING_SALT = process.env.npm_config_salt;
6
8
  if (!REACTKIT_CRED_ENCODING_SALT) {
7
- REACTKIT_CRED_ENCODING_SALT = process.env.npm_config_salt;
9
+ console.log('Encoding salt is required: --salt=...');
10
+ process.exit(1);
8
11
  }
9
- if (!REACTKIT_CRED_ENCODING_SALT) {
10
- console.log('REACTKIT_CRED_ENCODING_SALT is required either as an environment variable or as: --salt=...');
12
+
13
+ // Get the key
14
+ let key = process.env.npm_config_key;
15
+ if (!key) {
16
+ console.log('Key is required: --key=...');
17
+ process.exit(1);
18
+ }
19
+
20
+ // Get the description
21
+ let description = process.env.npm_config_description;
22
+ if (!description) {
23
+ console.log('Description is required: --description=...');
11
24
  process.exit(1);
12
25
  }
13
26
 
@@ -15,14 +28,57 @@ if (!REACTKIT_CRED_ENCODING_SALT) {
15
28
  let secret = process.env.npm_config_secret;
16
29
  if (!secret) {
17
30
  // Generate a random secret
18
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
19
31
  secret = '';
20
- for (let i = 0; i < 64; i++) {
32
+ for (let i = 0; i < 32; i++) {
21
33
  secret += chars.charAt(Math.floor(Math.random() * chars.length));
22
34
  }
23
35
  console.log('Generated a random secret. If you have one in mind, use --secret=...');
24
36
  }
25
37
 
26
- // Encode the secret
27
- const encodedSecret = jwt.encode(secret, REACTKIT_CRED_ENCODING_SALT);
28
- console.log(`\nNew Secret Generated!\n\nSecret: ${secret}\n\nEncoded Secret: ${encodedSecret}`);
38
+ // Get the host name
39
+ const host = process.env.npm_config_host;
40
+ if (!host) {
41
+ console.log('Host of the receiving server is required: --host=...');
42
+ process.exit(1);
43
+ }
44
+
45
+ // Encryption process based on:
46
+ // https://medium.com/@tony.infisical/guide-to-nodes-crypto-module-for-encryption-decryption-65c077176980
47
+
48
+ // Create a random initialization vector
49
+ const iv = crypto.randomBytes(12).toString('base64');
50
+
51
+ // Create a cipher
52
+ const cipher = crypto.createCipheriv(
53
+ 'aes-256-gcm',
54
+ Buffer.from(secret, 'base64'),
55
+ Buffer.from(iv, 'base64'),
56
+ );
57
+
58
+ // Encrypt the string
59
+ let ciphertext = cipher.update(secret, 'utf8', 'base64');
60
+
61
+ // Finalize the encryption
62
+ ciphertext += cipher.final('base64');
63
+
64
+ // Get the authentication tag
65
+ const tag = cipher.getAuthTag();
66
+
67
+ // JSONify the encrypted data
68
+ const encryptionPack = encodeURIComponent(JSON.stringify({
69
+ ciphertext,
70
+ iv,
71
+ tag,
72
+ }));
73
+
74
+ // Show the encrypted data
75
+ console.log('\n\n');
76
+ console.log('––––– Done! What\'s Next: –––––');
77
+ console.log('');
78
+ console.log('On the server *sending* the requests, append the following to the REACTKIT_CROSS_SERVER_CREDENTIALS env var:');
79
+ console.log(`|${host}:${key}:${secret}|`);
80
+ console.log('');
81
+ console.log('On the server *receiving* the requests, add an entry to the "CrossServerCredential" collection:');
82
+ console.log(`{ "description": "${description}", "key": "${key}", "encodedeSecret": "${encryptionPack}", "scopes": [] }`);
83
+ console.log('');
84
+ console.log('For all scopes that the server should have access to, add them to the "scopes" array.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "3.12.1-beta-cross-server.2",
3
+ "version": "3.12.1-beta-cross-server.3",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -25,7 +25,6 @@
25
25
  },
26
26
  "homepage": "https://github.com/harvard-edtech/dce-reactkit#readme",
27
27
  "dependencies": {
28
- "jwt-simple": "^0.5.6",
29
28
  "qs": "^6.x.x",
30
29
  "react-select": "^5.7.3"
31
30
  },
@@ -49,6 +48,7 @@
49
48
  "@types/jest": "^28.1.7",
50
49
  "@types/jwt-simple": "^0.5.36",
51
50
  "@types/node": "^20.2.5",
51
+ "@types/oauth-signature": "^1.5.2",
52
52
  "@types/react": "^17.0.7",
53
53
  "@typescript-eslint/eslint-plugin": "^5.59.9",
54
54
  "@typescript-eslint/parser": "^5.59.9",
@@ -61,6 +61,7 @@
61
61
  "eslint-plugin-react-hooks": "^4.6.0",
62
62
  "jest": "^28.1.3",
63
63
  "jest-environment-jsdom": "^28.1.3",
64
+ "oauth-signature": "^1.5.0",
64
65
  "raixa": "^1.0.21",
65
66
  "rollup": "^2.70.2",
66
67
  "rollup-plugin-dts": "^4.2.1",
package/rollup.config.js CHANGED
@@ -27,6 +27,7 @@ export default [
27
27
  typescript({ tsconfig: "./tsconfig.json" }),
28
28
  sourcemaps(),
29
29
  ],
30
+ inlineDynamicImports: true,
30
31
  external: [
31
32
  ...Object.keys(packageJson.dependencies || {}),
32
33
  ...Object.keys(packageJson.peerDependencies || {}),
@@ -36,6 +37,7 @@ export default [
36
37
  input: "dist/esm/types/index.d.ts",
37
38
  output: [{ file: "dist/index.d.ts", format: "esm" }],
38
39
  plugins: [dts()],
40
+ inlineDynamicImports: true,
39
41
  external: [
40
42
  ...Object.keys(packageJson.dependencies || {}),
41
43
  ...Object.keys(packageJson.peerDependencies || {}),