@carecard/auth-util 3.1.13 → 3.1.15

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.
Files changed (42) hide show
  1. package/.agents/config.toml +2 -0
  2. package/.agents/skills/carecard-workspace-standards/SKILL.md +388 -0
  3. package/.agents/skills/carecard-workspace-standards/agents/openai.yaml +4 -0
  4. package/.agents/skills/github-pr-create-update/SKILL.md +188 -0
  5. package/.agents/skills/github-pr-create-update/agents/openai.yaml +5 -0
  6. package/.agents/skills/github-pr-merge-cleanup/SKILL.md +175 -0
  7. package/.agents/skills/github-pr-merge-cleanup/agents/openai.yaml +5 -0
  8. package/.agents/skills/pkg-auth-util-auth-crypto-library/SKILL.md +236 -0
  9. package/.agents/skills/pkg-auth-util-auth-crypto-library/agents/openai.yaml +4 -0
  10. package/.agents/skills/software-design-patterns-and-clean-code/SKILL.md +73 -0
  11. package/.codex/config.toml +2 -0
  12. package/.prettierignore +17 -0
  13. package/.prettierrc.cjs +32 -0
  14. package/.prettierrc.js +12 -0
  15. package/eslint.config.mjs +14 -0
  16. package/index.d.ts +197 -151
  17. package/index.js +29 -28
  18. package/jest.config.js +16 -0
  19. package/lib/jwtUtilAuth.js +152 -86
  20. package/lib/keyGen.js +18 -22
  21. package/lib/pwdUtilAuth.js +25 -25
  22. package/lib/stringUtilAuth.js +43 -49
  23. package/package.json +24 -12
  24. package/readme.md +24 -5
  25. package/scripts/rename-cjs.js +13 -0
  26. package/src/cryptoUtilAuth.ts +111 -0
  27. package/src/index.ts +6 -0
  28. package/src/jwtUtilAuth.ts +85 -0
  29. package/src/keyGen.ts +14 -0
  30. package/src/pwdUtilAuth.ts +78 -0
  31. package/src/strEncryptUtil.ts +159 -0
  32. package/src/stringUtilAuth.ts +102 -0
  33. package/tests/cryptoUtilAuth.test.ts +97 -0
  34. package/tests/index.test.ts +157 -0
  35. package/tests/indexStringUtilAuth.test.ts +95 -0
  36. package/tests/jwtUtilAuth.test.ts +33 -0
  37. package/tests/keyGen.test.ts +26 -0
  38. package/tests/keys/keys.ts +24 -0
  39. package/tests/pwdUtilAuth.test.ts +40 -0
  40. package/tsconfig.base.json +14 -0
  41. package/tsconfig.cjs.json +7 -0
  42. package/tsconfig.esm.json +7 -0
package/readme.md CHANGED
@@ -24,21 +24,39 @@ npm install @carecard/auth-util
24
24
  ### JWT Utilities (`jwtUtilAuth`)
25
25
 
26
26
  ```javascript
27
- const { jwtUtilAuth } = require('@carecard/auth-util');
27
+ const { jwtCreateSignedToken, jwtGetHeaderPayload, jwtVerifySignedToken } = require('@carecard/auth-util');
28
28
 
29
29
  const header = { alg: 'EdDSA', typ: 'JWT' };
30
30
  const payload = { sub: '1234567890', name: 'John Doe' };
31
31
  const privateKey = '...'; // Your private PEM key
32
32
 
33
33
  // Create a signed JWT
34
- const token = jwtUtilAuth.createSignedJwtFromObject(header, payload, privateKey);
34
+ const token = jwtCreateSignedToken(header, payload, privateKey);
35
35
 
36
36
  // Verify a JWT signature
37
37
  const publicKey = '...'; // Your public PEM key
38
- const isValid = jwtUtilAuth.verifyJwtSignature(token, publicKey);
38
+ const isValid = jwtVerifySignedToken(token, publicKey);
39
39
 
40
40
  // Get header and payload from a JWT
41
- const { header: decodedHeader, payload: decodedPayload } = jwtUtilAuth.getHeaderPayloadFromJwt(token);
41
+ const { header: decodedHeader, payload: decodedPayload } = jwtGetHeaderPayload(token);
42
+ ```
43
+
44
+ ### Service-To-Service JWT Creation
45
+
46
+ ```javascript
47
+ const { jwtCreateServiceAuthorizationHeader, jwtCreateServiceToken } = require('@carecard/auth-util');
48
+
49
+ const token = jwtCreateServiceToken({
50
+ issuer: 'ms-institutions',
51
+ audience: 'ms-auth',
52
+ privateKey: institutionsPrivateKey,
53
+ });
54
+
55
+ const authorization = jwtCreateServiceAuthorizationHeader({
56
+ issuer: 'ms-institutions',
57
+ audience: 'ms-auth',
58
+ privateKey: institutionsPrivateKey,
59
+ });
42
60
  ```
43
61
 
44
62
  ### Password Utilities (`pwdUtilAuth`)
@@ -55,7 +73,7 @@ const hash = pwdUtilAuth.createPasswordHashWithRandomSalt(password, secret, algo
55
73
  // Resulting format: $1$base64(algorithm)$base64(hash)$base64(salt)$
56
74
 
57
75
  // Verify a password against a saved hash
58
- const isCorrect = (pwdUtilAuth.createPasswordHashBasedOnSavedAlgorithmSalt(password, hash, secret) === hash);
76
+ const isCorrect = pwdUtilAuth.createPasswordHashBasedOnSavedAlgorithmSalt(password, hash, secret) === hash;
59
77
  ```
60
78
 
61
79
  ### Key Generation
@@ -99,6 +117,7 @@ npm run test:types
99
117
  ## Architecture
100
118
 
101
119
  The package is organized into several modules:
120
+
102
121
  - `jwtUtilAuth`: Manages the JWT lifecycle.
103
122
  - `pwdUtilAuth`: Handles password hashing and verification.
104
123
  - `keyGen`: Utility for generating cryptographic keys.
@@ -0,0 +1,13 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ const dir = './dist/cjs';
5
+
6
+ for (const file of fs.readdirSync(dir)) {
7
+ if (file.endsWith('.js')) {
8
+ fs.renameSync(
9
+ path.join(dir, file),
10
+ path.join(dir, file.replace('.js', '.cjs'))
11
+ );
12
+ }
13
+ }
@@ -0,0 +1,111 @@
1
+ import * as crypto from 'crypto';
2
+
3
+ /**
4
+ * Signs a token returns signature string
5
+ * @param token
6
+ * @param privateKey
7
+ * @param signingAlgorithm
8
+ * @returns {string}
9
+ */
10
+ export const createBase64SignatureOfToken = function (
11
+ token: string = '',
12
+ privateKey: string,
13
+ signingAlgorithm: string,
14
+ ): string {
15
+ const sign = crypto.createSign(signingAlgorithm);
16
+ sign.write(token);
17
+ sign.end();
18
+ return sign.sign(privateKey, 'base64');
19
+ };
20
+
21
+ /**
22
+ * Verifies the signature returns true or false
23
+ * @param token
24
+ * @param signature
25
+ * @param publicKey
26
+ * @param signingAlgorithm
27
+ * @returns {boolean}
28
+ */
29
+ export const verifyBase64SignatureOfToken = function (
30
+ token: string = '',
31
+ signature: string,
32
+ publicKey: string,
33
+ signingAlgorithm: string,
34
+ ): boolean {
35
+ const verify = crypto.createVerify(signingAlgorithm);
36
+ verify.update(token);
37
+ verify.end();
38
+ return verify.verify(publicKey, signature, 'base64');
39
+ };
40
+
41
+ /**
42
+ * Creates the hash of given string
43
+ * @param string
44
+ * @param secret
45
+ * @param algorithm
46
+ * @returns {string}
47
+ */
48
+ export const createHmacBase64 = function (
49
+ string: string = '',
50
+ secret: string,
51
+ algorithm: string,
52
+ ): string {
53
+ const hmac = crypto.createHmac(algorithm, secret);
54
+ hmac.update(string);
55
+ return hmac.digest('base64');
56
+ };
57
+
58
+ /**
59
+ * Create random salt
60
+ * @returns {string}
61
+ */
62
+ export const createSaltBase64 = (): string => {
63
+ const date = new Date().valueOf();
64
+ const hmac = crypto.createHmac('SHA256', date.toString());
65
+ hmac.update(date.toString());
66
+ return hmac.digest('base64');
67
+ };
68
+
69
+ /**
70
+ * Encrypt given string
71
+ * @param string
72
+ * @param salt
73
+ * @param secret
74
+ * @param algorithm
75
+ * @returns {string}
76
+ */
77
+ export const encryptStringAsciiToBase64 = (
78
+ string: string,
79
+ salt: string,
80
+ secret: string,
81
+ algorithm: string,
82
+ ): string => {
83
+ const key = crypto.scryptSync(secret, salt, 24);
84
+ const iv = Buffer.alloc(16, 0);
85
+ const cipher = crypto.createCipheriv(algorithm, key, iv);
86
+ let encrypted = cipher.update(string, 'ascii', 'base64');
87
+ encrypted += cipher.final('base64');
88
+ return encrypted;
89
+ };
90
+
91
+ /**
92
+ * Decrypts given string
93
+ * @param encryptedString
94
+ * @param salt
95
+ * @param secret
96
+ * @param algorithm
97
+ * @returns {string}
98
+ */
99
+ export const decryptStringBase64ToAscii = (
100
+ encryptedString: string,
101
+ salt: string,
102
+ secret: string,
103
+ algorithm: string,
104
+ ): string => {
105
+ const key = crypto.scryptSync(secret, salt, 24);
106
+ const iv = Buffer.alloc(16, 0);
107
+ const decipher = crypto.createDecipheriv(algorithm, key, iv);
108
+ let decrypted = decipher.update(encryptedString, 'base64', 'ascii');
109
+ decrypted += decipher.final('ascii');
110
+ return decrypted;
111
+ };
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './cryptoUtilAuth';
2
+ export * from './jwtUtilAuth';
3
+ export * from './keyGen';
4
+ export * from './pwdUtilAuth';
5
+ export * from './strEncryptUtil';
6
+ export * from './stringUtilAuth';
@@ -0,0 +1,85 @@
1
+ import * as stringUtilAuth from './stringUtilAuth';
2
+ import * as cryptoUtilAuth from './cryptoUtilAuth';
3
+
4
+ /**
5
+ * User supplied header, payload and signature create jwt.
6
+ * @returns {string|null}
7
+ * @param headerBase64
8
+ * @param payloadBase64
9
+ * @param signatureBase64
10
+ */
11
+ export const _assembleJwt = (
12
+ headerBase64: string,
13
+ payloadBase64: string,
14
+ signatureBase64: string,
15
+ ): string => {
16
+ return headerBase64 + '.' + payloadBase64 + '.' + signatureBase64;
17
+ };
18
+
19
+ /**
20
+ * User supplied header, payload and signature create jwt.
21
+ * @returns {{payload: *, signature: *, header: *}}
22
+ * @param jwt
23
+ */
24
+ export const _splitJwtInToHeaderPayloadSignature = (jwt: string): any => {
25
+ return stringUtilAuth.dotConnectedStringToHeaderPayloadSignature(jwt);
26
+ };
27
+
28
+ /**
29
+ * Creates Url safe jwt
30
+ * @param headerObject
31
+ * @param payloadObject
32
+ * @param privateKey
33
+ * @return {string|null}
34
+ */
35
+ export const createSignedJwtFromObject = (
36
+ headerObject: any,
37
+ payloadObject: any,
38
+ privateKey: string,
39
+ ): any => {
40
+ try {
41
+ const algorithm = headerObject.alg;
42
+ const headerBase64UrlSafe = stringUtilAuth.objectToBase64UrlSafeString(headerObject);
43
+ const payloadBase64UrlSafe = stringUtilAuth.objectToBase64UrlSafeString(payloadObject);
44
+ const token = headerBase64UrlSafe + '.' + payloadBase64UrlSafe;
45
+ const signature = cryptoUtilAuth.createBase64SignatureOfToken(token, privateKey, algorithm);
46
+ const urlSafeSignature = stringUtilAuth.makeStringUrlSafe(signature);
47
+ return _assembleJwt(headerBase64UrlSafe, payloadBase64UrlSafe, urlSafeSignature);
48
+ } catch (error) {
49
+ return null;
50
+ }
51
+ };
52
+
53
+ /**
54
+ * Verify signature of jwt
55
+ * @param jwt
56
+ * @param publicKey
57
+ * @return {boolean}
58
+ */
59
+ export const verifyJwtSignature = (jwt: string, publicKey: string): boolean => {
60
+ try {
61
+ const { header, payload, signature } = _splitJwtInToHeaderPayloadSignature(jwt);
62
+ const token = header + '.' + payload;
63
+ const headerObject = stringUtilAuth.urlSafeBase64ToObject(header);
64
+ return cryptoUtilAuth.verifyBase64SignatureOfToken(
65
+ token,
66
+ signature,
67
+ publicKey,
68
+ headerObject.alg,
69
+ );
70
+ } catch (error) {
71
+ return false;
72
+ }
73
+ };
74
+
75
+ /**
76
+ * Returns header and payload object for jwt.
77
+ * @param jwt
78
+ * @return {{payload: any, header: any}}
79
+ */
80
+ export const getHeaderPayloadFromJwt = (jwt: string): any => {
81
+ const { header, payload } = _splitJwtInToHeaderPayloadSignature(jwt);
82
+ let headerAscii = stringUtilAuth.base64ToAscii(header);
83
+ let payloadAscii = stringUtilAuth.base64ToAscii(payload);
84
+ return { header: JSON.parse(headerAscii), payload: JSON.parse(payloadAscii) };
85
+ };
package/src/keyGen.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { generateKeyPairSync } from 'node:crypto';
2
+
3
+ export const generateKeyPair = (modulusLength: number = 4096) =>
4
+ generateKeyPairSync('rsa', {
5
+ modulusLength: modulusLength,
6
+ publicKeyEncoding: {
7
+ type: 'spki',
8
+ format: 'pem',
9
+ },
10
+ privateKeyEncoding: {
11
+ type: 'pkcs8',
12
+ format: 'pem',
13
+ },
14
+ });
@@ -0,0 +1,78 @@
1
+ import * as cryptoUtilAuth from './cryptoUtilAuth';
2
+ import * as stringUtilAuth from './stringUtilAuth';
3
+
4
+ /**
5
+ * Just assemble password together
6
+ * @param algorithmBase64
7
+ * @param hashBase64
8
+ * @param saltBase64
9
+ * @return {string}
10
+ */
11
+ export const _assemblePasswordHash = (
12
+ algorithmBase64: string,
13
+ hashBase64: string,
14
+ saltBase64: string,
15
+ ): string => {
16
+ return '$1$' + algorithmBase64 + '$' + hashBase64 + '$' + saltBase64 + '$';
17
+ };
18
+
19
+ /**
20
+ * Break password into its parts does not reverse base64 encoding.
21
+ * @param passwordHashStored
22
+ * @return {{salt: *, version: *, alg: *, hash: *}}
23
+ */
24
+ export const _disassemblePasswordHash = (passwordHashStored: string): any => {
25
+ return stringUtilAuth.dollarSignConnectedStringToAlgorithmHashSalt(passwordHashStored);
26
+ };
27
+
28
+ /**
29
+ * Creates password hash ready to be saved in database.
30
+ * @param password
31
+ * @param secret
32
+ * @param salt
33
+ * @param algorithm
34
+ * @return {string}
35
+ */
36
+ export const _createPasswordHash = (
37
+ password: string,
38
+ secret: string,
39
+ salt: string,
40
+ algorithm: string,
41
+ ): string => {
42
+ const algorithmBase64 = stringUtilAuth.asciiToBase64(algorithm);
43
+ const hashBase64 = cryptoUtilAuth.createHmacBase64(password, secret, algorithm);
44
+ return _assemblePasswordHash(algorithmBase64, hashBase64, salt);
45
+ };
46
+
47
+ /**
48
+ * Automatically adds random salt.
49
+ * @param password
50
+ * @param secret
51
+ * @param algorithm
52
+ * @return {string}
53
+ */
54
+ export const createPasswordHashWithRandomSalt = (
55
+ password: string,
56
+ secret: string,
57
+ algorithm: string,
58
+ ): string => {
59
+ const salt = cryptoUtilAuth.createSaltBase64();
60
+ return _createPasswordHash(password, secret, salt, algorithm);
61
+ };
62
+
63
+ /**
64
+ * Creates hash based on saved hash in database.
65
+ * @param password
66
+ * @param savedPasswordHash
67
+ * @param secret
68
+ * @return {string}
69
+ */
70
+ export const createPasswordHashBasedOnSavedAlgorithmSalt = (
71
+ password: string,
72
+ savedPasswordHash: string,
73
+ secret: string,
74
+ ): string => {
75
+ const { alg, salt } = _disassemblePasswordHash(savedPasswordHash);
76
+ const algorithm = stringUtilAuth.base64ToAscii(alg);
77
+ return _createPasswordHash(password, secret, salt, algorithm);
78
+ };
@@ -0,0 +1,159 @@
1
+ // src/strEncryptUtil.ts
2
+ import * as crypto from 'crypto';
3
+
4
+ /**
5
+ * Derive a key using scrypt.
6
+ */
7
+ export function createKey(key: crypto.BinaryLike, keyLength = 32): Buffer {
8
+ // scryptSync returns a Buffer
9
+ return crypto.scryptSync(key, key, keyLength);
10
+ }
11
+
12
+ /* --------------------------------------------------
13
+ * Config Types
14
+ * -------------------------------------------------- */
15
+
16
+ export interface EncryptionConfig {
17
+ privateKey: string | Buffer | crypto.KeyObject;
18
+ encryptedTextEncoding: BufferEncoding; // e.g., 'base64' | 'hex' | ...
19
+ }
20
+
21
+ export interface DecryptionConfig {
22
+ publicKey: string | Buffer | crypto.KeyObject;
23
+ encryptedTextEncoding: BufferEncoding; // encoding of input cipher text buffer
24
+ plainTextEncoding: BufferEncoding; // encoding for output text, e.g., 'utf8'
25
+ }
26
+
27
+ export interface SymmetricCryptoConfig {
28
+ cipherAlgorithm: string; // e.g., 'aes-256-cbc'
29
+ encryptionKey: crypto.BinaryLike; // passphrase or raw key-like data
30
+ keyLength: number; // e.g., 32 for aes-256
31
+ plainTextEncoding: BufferEncoding; // e.g., 'utf8'
32
+ encryptedTextEncoding: BufferEncoding; // e.g., 'base64' | 'hex'
33
+ }
34
+
35
+ /* --------------------------------------------------
36
+ * Helpers
37
+ * -------------------------------------------------- */
38
+
39
+ function getErrorCodeOrFallback(error: unknown): string {
40
+ // Safely narrow 'unknown' to read 'code' when available
41
+ if (
42
+ typeof error === 'object' &&
43
+ error !== null &&
44
+ 'code' in error &&
45
+ typeof (error as { code?: unknown }).code === 'string'
46
+ ) {
47
+ return (error as { code: string }).code;
48
+ }
49
+ if (error instanceof Error) {
50
+ // You can return message or name; using name keeps it short
51
+ return `ERROR:${error.name}`;
52
+ }
53
+ return 'UNKNOWN_ERROR';
54
+ }
55
+
56
+ /* --------------------------------------------------
57
+ * Asymmetric Encryption (RSA or similar)
58
+ * -------------------------------------------------- */
59
+
60
+ /**
61
+ * Encrypts text using a private key, returning an encoded cipher text string.
62
+ * On error, returns a code string if present, otherwise a fallback.
63
+ */
64
+ export const encryptByPrivateKey = (
65
+ encryptionConfigObj: EncryptionConfig,
66
+ textToEncrypt: string,
67
+ ): string => {
68
+ try {
69
+ const encrypted = crypto.privateEncrypt(
70
+ encryptionConfigObj.privateKey,
71
+ Buffer.from(textToEncrypt, 'utf8'),
72
+ );
73
+ return encrypted.toString(encryptionConfigObj.encryptedTextEncoding);
74
+ } catch (error: unknown) {
75
+ return getErrorCodeOrFallback(error);
76
+ }
77
+ };
78
+
79
+ /**
80
+ * Decrypts text using a public key, returning a plain text string.
81
+ * On error, returns a code string if present, otherwise a fallback.
82
+ */
83
+ export const decryptByPublicKey = (
84
+ decryptionConfigObj: DecryptionConfig,
85
+ textToDecrypt: string,
86
+ ): string => {
87
+ try {
88
+ const decrypted = crypto.publicDecrypt(
89
+ decryptionConfigObj.publicKey,
90
+ Buffer.from(textToDecrypt, decryptionConfigObj.encryptedTextEncoding),
91
+ );
92
+ return decrypted.toString(decryptionConfigObj.plainTextEncoding);
93
+ } catch (error: unknown) {
94
+ return getErrorCodeOrFallback(error);
95
+ }
96
+ };
97
+
98
+ /* --------------------------------------------------
99
+ * Symmetric Encryption (AES or similar)
100
+ * -------------------------------------------------- */
101
+
102
+ /**
103
+ * Encrypts text using a symmetric algorithm and derived key, returning an encoded cipher string.
104
+ * On error, returns a code string if present, otherwise a fallback.
105
+ *
106
+ * NOTE: This uses a zero IV (Buffer.alloc(16, 0)) which is generally **not recommended** for production.
107
+ * Prefer a random IV per encryption and prepend/append it to the output for decryption.
108
+ */
109
+ export const encryptByKey = (
110
+ encryptConfigObj: SymmetricCryptoConfig,
111
+ textToEncrypt: string,
112
+ ): string => {
113
+ try {
114
+ const iv = Buffer.alloc(16, 0); // ⚠️ consider using a random IV for security
115
+ const key = createKey(encryptConfigObj.encryptionKey, encryptConfigObj.keyLength);
116
+
117
+ const cipher = crypto.createCipheriv(encryptConfigObj.cipherAlgorithm, key, iv);
118
+
119
+ let encrypted = cipher.update(
120
+ textToEncrypt,
121
+ encryptConfigObj.plainTextEncoding,
122
+ encryptConfigObj.encryptedTextEncoding,
123
+ );
124
+ encrypted += cipher.final(encryptConfigObj.encryptedTextEncoding);
125
+
126
+ return encrypted;
127
+ } catch (error: unknown) {
128
+ return getErrorCodeOrFallback(error);
129
+ }
130
+ };
131
+
132
+ /**
133
+ * Decrypts a cipher string using a symmetric algorithm and derived key,
134
+ * returning the plain text string. On error, returns a code string or fallback.
135
+ *
136
+ * NOTE: Must use the same IV that was used during encryption. Here it assumes a zero IV.
137
+ */
138
+ export const decryptByKey = (
139
+ encryptConfigObj: SymmetricCryptoConfig,
140
+ textToDecrypt: string,
141
+ ): string => {
142
+ try {
143
+ const iv = Buffer.alloc(16, 0); // ⚠️ must match the IV used in encryptByKey
144
+ const key = createKey(encryptConfigObj.encryptionKey, encryptConfigObj.keyLength);
145
+
146
+ const decipher = crypto.createDecipheriv(encryptConfigObj.cipherAlgorithm, key, iv);
147
+
148
+ let decrypted = decipher.update(
149
+ textToDecrypt,
150
+ encryptConfigObj.encryptedTextEncoding,
151
+ encryptConfigObj.plainTextEncoding,
152
+ );
153
+ decrypted += decipher.final(encryptConfigObj.plainTextEncoding);
154
+
155
+ return decrypted;
156
+ } catch (error: unknown) {
157
+ return getErrorCodeOrFallback(error);
158
+ }
159
+ };
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+ /**
3
+ * For incoming jwt token validation, splitting and parsing.
4
+ * For outgoing jwt token assembling to jwt, make it url safe.
5
+ */
6
+
7
+ /**
8
+ * Adjusts padding of base64String
9
+ * @param base64String
10
+ * @return {*}
11
+ */
12
+ export const adjustBase64Padding = (base64String: string): string => {
13
+ while (base64String.length % 4) base64String += '=';
14
+ return base64String;
15
+ };
16
+
17
+ /**
18
+ * Removes /, + and = from the string
19
+ * @returns {string}
20
+ */
21
+ export const makeStringUrlSafe = (urlUnsafeString: string = ''): string => {
22
+ return urlUnsafeString.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
23
+ };
24
+
25
+ /**
26
+ * Put back /, + and = into the string
27
+ * @returns {string}
28
+ */
29
+ export const reverseStringUrlSafe = (urlSafeString: string = ''): string => {
30
+ let myString = urlSafeString.replace(/-/g, '+').replace(/_/g, '/');
31
+ return adjustBase64Padding(myString);
32
+ };
33
+
34
+ /**
35
+ * Encode string to base64 string
36
+ * @param unCodedString
37
+ * @returns {string}
38
+ */
39
+ export const asciiToBase64 = (unCodedString: string): string => {
40
+ return Buffer.from(unCodedString).toString('base64');
41
+ };
42
+
43
+ /** Decode string from base64
44
+ * @param codedString
45
+ * @returns {string}
46
+ */
47
+ export const base64ToAscii = (codedString: string): string => {
48
+ return Buffer.from(codedString, 'base64').toString('ascii');
49
+ };
50
+
51
+ /**
52
+ * Decompose $ connected string and return an object
53
+ * return null if error
54
+ * @param passwordHash
55
+ */
56
+ export const dollarSignConnectedStringToAlgorithmHashSalt = (passwordHash: string) => {
57
+ const splitStringArray = passwordHash.split('$');
58
+ if (splitStringArray.length !== 6) return null;
59
+ return {
60
+ version: splitStringArray[1],
61
+ alg: splitStringArray[2],
62
+ hash: splitStringArray[3],
63
+ salt: splitStringArray[4],
64
+ };
65
+ };
66
+
67
+ /**
68
+ * Decompose . connected string and return an object with
69
+ * {header: 'string', payload: 'string', signature: 'string'}
70
+ * return null if error
71
+ */
72
+ export const dotConnectedStringToHeaderPayloadSignature = (jwt: string) => {
73
+ const splitJWT = jwt.split('.');
74
+ if (splitJWT.length !== 3) return null;
75
+ return {
76
+ header: splitJWT[0],
77
+ payload: splitJWT[1],
78
+ signature: splitJWT[2],
79
+ };
80
+ };
81
+
82
+ /**
83
+ * Turns object into url safe string
84
+ * @param object
85
+ * @return {string}
86
+ */
87
+ export const objectToBase64UrlSafeString = (object: any): string => {
88
+ let stringAscii = JSON.stringify(object);
89
+ let base64String = asciiToBase64(stringAscii);
90
+ return makeStringUrlSafe(base64String);
91
+ };
92
+
93
+ /**
94
+ * Turns base64 into object
95
+ * @param urlSafeBase64String
96
+ * @return {any}
97
+ */
98
+ export const urlSafeBase64ToObject = (urlSafeBase64String: string): any => {
99
+ let base64String = reverseStringUrlSafe(urlSafeBase64String);
100
+ let stringAscii = base64ToAscii(base64String);
101
+ return JSON.parse(stringAscii);
102
+ };