@carecard/auth-util 3.1.13 → 3.1.16
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/.agents/config.toml +2 -0
- package/.agents/skills/carecard-workspace-standards/SKILL.md +401 -0
- package/.agents/skills/carecard-workspace-standards/agents/openai.yaml +4 -0
- package/.agents/skills/github-pr-create-update/SKILL.md +188 -0
- package/.agents/skills/github-pr-create-update/agents/openai.yaml +5 -0
- package/.agents/skills/github-pr-merge-cleanup/SKILL.md +175 -0
- package/.agents/skills/github-pr-merge-cleanup/agents/openai.yaml +5 -0
- package/.agents/skills/pkg-auth-util-auth-crypto-library/SKILL.md +239 -0
- package/.agents/skills/pkg-auth-util-auth-crypto-library/agents/openai.yaml +4 -0
- package/.agents/skills/software-design-patterns-and-clean-code/SKILL.md +73 -0
- package/.codex/config.toml +2 -0
- package/.prettierrc.js +12 -0
- package/eslint.config.mjs +14 -0
- package/index.d.ts +197 -151
- package/index.js +29 -28
- package/lib/jwtUtilAuth.js +152 -86
- package/lib/keyGen.js +18 -22
- package/lib/pwdUtilAuth.js +25 -25
- package/lib/stringUtilAuth.js +43 -49
- package/package.json +23 -11
- package/readme.md +37 -5
package/lib/jwtUtilAuth.js
CHANGED
|
@@ -1,55 +1,72 @@
|
|
|
1
|
-
const crypto = require(
|
|
1
|
+
const crypto = require('crypto');
|
|
2
2
|
|
|
3
|
-
const _normalizePayload =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
const _normalizePayload = payloadObject => {
|
|
4
|
+
const payload = { ...payloadObject };
|
|
5
|
+
const now = Math.floor(Date.now() / 1000);
|
|
6
|
+
const fieldsToNormalize = ['iat', 'exp', 'nbf', 'auth_time'];
|
|
7
|
+
const msThreshold = 1000000000000;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
if (!payload.iat) {
|
|
10
|
+
payload.iat = now;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
fieldsToNormalize.forEach(field => {
|
|
14
|
+
if (payload[field] && payload[field] > msThreshold) {
|
|
15
|
+
payload[field] = Math.floor(payload[field] / 1000);
|
|
11
16
|
}
|
|
17
|
+
});
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
if (!payload.exp) {
|
|
20
|
+
payload.exp = payload.iat + 3600;
|
|
21
|
+
}
|
|
22
|
+
return payload;
|
|
23
|
+
};
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
return payload;
|
|
25
|
+
const _encode = obj => {
|
|
26
|
+
return Buffer.from(JSON.stringify(obj)).toString('base64url');
|
|
23
27
|
};
|
|
24
28
|
|
|
25
|
-
const
|
|
26
|
-
|
|
29
|
+
const _decode = str => {
|
|
30
|
+
return JSON.parse(Buffer.from(str, 'base64url').toString('utf8'));
|
|
27
31
|
};
|
|
28
32
|
|
|
29
|
-
const
|
|
30
|
-
|
|
33
|
+
const _sign = (token, alg, privateKey) => {
|
|
34
|
+
if (alg === 'EdDSA' || alg === 'Ed25519') {
|
|
35
|
+
return crypto.sign(null, Buffer.from(token), privateKey).toString('base64url');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const sign = crypto.createSign(alg);
|
|
39
|
+
sign.write(token);
|
|
40
|
+
sign.end();
|
|
41
|
+
return sign.sign(privateKey, 'base64url');
|
|
31
42
|
};
|
|
32
43
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
const _verify = (token, signature, alg, publicKey) => {
|
|
45
|
+
if (alg === 'EdDSA' || alg === 'Ed25519') {
|
|
46
|
+
return crypto.verify(null, Buffer.from(token), publicKey, Buffer.from(signature, 'base64url'));
|
|
47
|
+
}
|
|
37
48
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
49
|
+
const verify = crypto.createVerify(alg);
|
|
50
|
+
verify.update(token);
|
|
51
|
+
verify.end();
|
|
52
|
+
return verify.verify(publicKey, signature, 'base64url');
|
|
42
53
|
};
|
|
43
54
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
const isNonEmptyString = value => {
|
|
56
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const audienceIsNonEmptyStringArray = audience => {
|
|
60
|
+
return Array.isArray(audience) && audience.length > 0 && audience.every(audienceValue => isNonEmptyString(audienceValue));
|
|
61
|
+
};
|
|
48
62
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
const isNonEmptyAudience = audience => {
|
|
64
|
+
return isNonEmptyString(audience) || audienceIsNonEmptyStringArray(audience);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const normalizeSeconds = value => {
|
|
68
|
+
if (!Number.isFinite(value)) return null;
|
|
69
|
+
return value > 1000000000000 ? Math.floor(value / 1000) : Math.floor(value);
|
|
53
70
|
};
|
|
54
71
|
|
|
55
72
|
/**
|
|
@@ -59,48 +76,93 @@ const _verify = ( token, signature, alg, publicKey ) => {
|
|
|
59
76
|
* @param privateKey
|
|
60
77
|
* @return {string|null}
|
|
61
78
|
*/
|
|
62
|
-
const createSignedJwtFromObject = (
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
const createSignedJwtFromObject = (headerObject, payloadObject, privateKey) => {
|
|
80
|
+
try {
|
|
81
|
+
if (!privateKey) return null;
|
|
65
82
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
83
|
+
const header = { ...headerObject };
|
|
84
|
+
header.alg = header.alg || 'EdDSA';
|
|
85
|
+
header.typ = 'JWT';
|
|
69
86
|
|
|
70
|
-
|
|
87
|
+
const payload = _normalizePayload(payloadObject);
|
|
71
88
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
const headerBase64UrlSafe = _encode(header);
|
|
90
|
+
const payloadBase64UrlSafe = _encode(payload);
|
|
91
|
+
const token = headerBase64UrlSafe + '.' + payloadBase64UrlSafe;
|
|
75
92
|
|
|
76
|
-
|
|
93
|
+
const signature = _sign(token, header.alg, privateKey);
|
|
77
94
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
95
|
+
return token + '.' + signature;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
82
99
|
};
|
|
83
100
|
|
|
101
|
+
function createServiceJwt({
|
|
102
|
+
issuer,
|
|
103
|
+
audience,
|
|
104
|
+
privateKey,
|
|
105
|
+
subject = issuer,
|
|
106
|
+
issuedAt = Math.floor(Date.now() / 1000),
|
|
107
|
+
expiresInSeconds = 60,
|
|
108
|
+
algorithm = 'EdDSA',
|
|
109
|
+
claims = {},
|
|
110
|
+
} = {}) {
|
|
111
|
+
if (
|
|
112
|
+
!isNonEmptyString(issuer) ||
|
|
113
|
+
!isNonEmptyAudience(audience) ||
|
|
114
|
+
!isNonEmptyString(subject) ||
|
|
115
|
+
!isNonEmptyString(privateKey) ||
|
|
116
|
+
!Number.isInteger(expiresInSeconds) ||
|
|
117
|
+
expiresInSeconds <= 0
|
|
118
|
+
) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const iat = normalizeSeconds(issuedAt);
|
|
123
|
+
if (!Number.isInteger(iat)) return null;
|
|
124
|
+
|
|
125
|
+
// Service-to-service tokens use registered JWT claims so receivers can
|
|
126
|
+
// validate sender, intended audience, subject, and lifetime consistently.
|
|
127
|
+
return createSignedJwtFromObject(
|
|
128
|
+
{ alg: algorithm, typ: 'JWT' },
|
|
129
|
+
{
|
|
130
|
+
...claims,
|
|
131
|
+
iss: issuer,
|
|
132
|
+
aud: audience,
|
|
133
|
+
sub: subject,
|
|
134
|
+
iat,
|
|
135
|
+
exp: iat + expiresInSeconds,
|
|
136
|
+
},
|
|
137
|
+
privateKey,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function createServiceAuthorizationHeader(options = {}) {
|
|
142
|
+
const token = createServiceJwt(options);
|
|
143
|
+
return token ? `Bearer ${token}` : null;
|
|
144
|
+
}
|
|
145
|
+
|
|
84
146
|
/**
|
|
85
147
|
* Verify signature of jwt
|
|
86
148
|
* @param jwt
|
|
87
149
|
* @param publicKey
|
|
88
150
|
* @return {boolean}
|
|
89
151
|
*/
|
|
90
|
-
const verifyJwtSignature = (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
152
|
+
const verifyJwtSignature = (jwt, publicKey) => {
|
|
153
|
+
try {
|
|
154
|
+
if (!jwt || !publicKey) return false;
|
|
155
|
+
const splitJWT = jwt.split('.');
|
|
156
|
+
if (splitJWT.length !== 3) return false;
|
|
157
|
+
|
|
158
|
+
const [header, payload, signature] = splitJWT;
|
|
159
|
+
const token = header + '.' + payload;
|
|
160
|
+
const headerObject = _decode(header);
|
|
161
|
+
|
|
162
|
+
return _verify(token, signature, headerObject.alg, publicKey);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
104
166
|
};
|
|
105
167
|
|
|
106
168
|
/**
|
|
@@ -109,27 +171,31 @@ const verifyJwtSignature = ( jwt, publicKey ) => {
|
|
|
109
171
|
* @return {{payload: *, header: *}|null}
|
|
110
172
|
*/
|
|
111
173
|
const getHeaderPayloadFromJwt = jwt => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
174
|
+
try {
|
|
175
|
+
if (typeof jwt !== 'string') return null;
|
|
176
|
+
const splitJWT = jwt.split('.');
|
|
177
|
+
if (splitJWT.length !== 3) return null;
|
|
178
|
+
|
|
179
|
+
const headerObject = _decode(splitJWT[0]);
|
|
180
|
+
const payloadObject = _decode(splitJWT[1]);
|
|
181
|
+
|
|
182
|
+
return { header: headerObject, payload: payloadObject };
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
124
186
|
};
|
|
125
187
|
|
|
126
188
|
module.exports = {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
189
|
+
createSignedJwtFromObject,
|
|
190
|
+
createServiceJwt,
|
|
191
|
+
createServiceAuthorizationHeader,
|
|
192
|
+
verifyJwtSignature,
|
|
193
|
+
getHeaderPayloadFromJwt,
|
|
194
|
+
_normalizePayload,
|
|
195
|
+
_encode,
|
|
196
|
+
_decode,
|
|
197
|
+
_sign,
|
|
198
|
+
_verify,
|
|
199
|
+
_isNonEmptyAudience: isNonEmptyAudience,
|
|
200
|
+
_normalizeSeconds: normalizeSeconds,
|
|
135
201
|
};
|
package/lib/keyGen.js
CHANGED
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
const {
|
|
2
|
-
generateKeyPairSync,
|
|
3
|
-
} = require( 'node:crypto' );
|
|
1
|
+
const { generateKeyPairSync } = require('node:crypto');
|
|
4
2
|
|
|
3
|
+
const generateKeyPair = (algorithm = 'ed25519') => {
|
|
4
|
+
const options = {
|
|
5
|
+
publicKeyEncoding: {
|
|
6
|
+
type: 'spki',
|
|
7
|
+
format: 'pem',
|
|
8
|
+
},
|
|
9
|
+
privateKeyEncoding: {
|
|
10
|
+
type: 'pkcs8',
|
|
11
|
+
format: 'pem',
|
|
12
|
+
},
|
|
13
|
+
};
|
|
5
14
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type: 'spki',
|
|
10
|
-
format: 'pem',
|
|
11
|
-
},
|
|
12
|
-
privateKeyEncoding: {
|
|
13
|
-
type: 'pkcs8',
|
|
14
|
-
format: 'pem',
|
|
15
|
-
},
|
|
16
|
-
};
|
|
15
|
+
if (algorithm === 'rsa') {
|
|
16
|
+
options.modulusLength = 2048;
|
|
17
|
+
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
options.modulusLength = 2048;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return generateKeyPairSync( algorithm, options );
|
|
19
|
+
return generateKeyPairSync(algorithm, options);
|
|
23
20
|
};
|
|
24
21
|
|
|
25
|
-
|
|
26
22
|
module.exports = {
|
|
27
|
-
|
|
28
|
-
};
|
|
23
|
+
generateKeyPair,
|
|
24
|
+
};
|
package/lib/pwdUtilAuth.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const crypto = require(
|
|
1
|
+
const crypto = require('crypto');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Automatically adds random salt.
|
|
@@ -7,15 +7,15 @@ const crypto = require( 'crypto' );
|
|
|
7
7
|
* @param algorithm
|
|
8
8
|
* @return {string}
|
|
9
9
|
*/
|
|
10
|
-
const createPasswordHashWithRandomSalt = (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
const createPasswordHashWithRandomSalt = (password, secret, algorithm) => {
|
|
11
|
+
try {
|
|
12
|
+
const salt = crypto.randomBytes(32).toString('base64');
|
|
13
|
+
const algorithmBase64 = Buffer.from(algorithm).toString('base64');
|
|
14
|
+
const hashBase64 = crypto.createHmac(algorithm, secret).update(password).digest('base64');
|
|
15
|
+
return '$1$' + algorithmBase64 + '$' + hashBase64 + '$' + salt + '$';
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -25,23 +25,23 @@ const createPasswordHashWithRandomSalt = ( password, secret, algorithm ) => {
|
|
|
25
25
|
* @param secret
|
|
26
26
|
* @return {string}
|
|
27
27
|
*/
|
|
28
|
-
const createPasswordHashBasedOnSavedAlgorithmSalt = (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const createPasswordHashBasedOnSavedAlgorithmSalt = (password, savedPasswordHash, secret) => {
|
|
29
|
+
try {
|
|
30
|
+
const splitStringArray = savedPasswordHash.split('$');
|
|
31
|
+
if (splitStringArray.length !== 6) return null;
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const algBase64 = splitStringArray[2];
|
|
34
|
+
const salt = splitStringArray[4];
|
|
35
|
+
const algorithm = Buffer.from(algBase64, 'base64').toString('utf8');
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
const hashBase64 = crypto.createHmac(algorithm, secret).update(password).digest('base64');
|
|
38
|
+
return '$1$' + algBase64 + '$' + hashBase64 + '$' + salt + '$';
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
module.exports = {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
45
|
+
createPasswordHashWithRandomSalt,
|
|
46
|
+
createPasswordHashBasedOnSavedAlgorithmSalt,
|
|
47
|
+
};
|
package/lib/stringUtilAuth.js
CHANGED
|
@@ -11,19 +11,16 @@
|
|
|
11
11
|
* @return {*}
|
|
12
12
|
*/
|
|
13
13
|
const adjustBase64Padding = base64String => {
|
|
14
|
-
|
|
15
|
-
}
|
|
14
|
+
return base64String.padEnd(base64String.length + ((4 - (base64String.length % 4)) % 4), '=');
|
|
15
|
+
};
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Removes /, + and = from the string
|
|
19
19
|
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
20
20
|
* @returns {string}
|
|
21
21
|
*/
|
|
22
|
-
const makeStringUrlSafe = (
|
|
23
|
-
|
|
24
|
-
.replaceAll( '+', '-' )
|
|
25
|
-
.replaceAll( '/', '_' )
|
|
26
|
-
.replaceAll( '=', '' );
|
|
22
|
+
const makeStringUrlSafe = (urlUnsafeString = '') => {
|
|
23
|
+
return urlUnsafeString.replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '');
|
|
27
24
|
};
|
|
28
25
|
|
|
29
26
|
/**
|
|
@@ -31,11 +28,9 @@ const makeStringUrlSafe = ( urlUnsafeString = '' ) => {
|
|
|
31
28
|
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
32
29
|
* @returns {string}
|
|
33
30
|
*/
|
|
34
|
-
const reverseStringUrlSafe = (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.replaceAll( '_', '/' );
|
|
38
|
-
return adjustBase64Padding( myString );
|
|
31
|
+
const reverseStringUrlSafe = (urlSafeString = '') => {
|
|
32
|
+
let myString = urlSafeString.replaceAll('-', '+').replaceAll('_', '/');
|
|
33
|
+
return adjustBase64Padding(myString);
|
|
39
34
|
};
|
|
40
35
|
|
|
41
36
|
/**
|
|
@@ -44,18 +39,18 @@ const reverseStringUrlSafe = ( urlSafeString = '' ) => {
|
|
|
44
39
|
* @param unCodedString
|
|
45
40
|
* @returns {string}
|
|
46
41
|
*/
|
|
47
|
-
const asciiToBase64 =
|
|
48
|
-
|
|
49
|
-
}
|
|
42
|
+
const asciiToBase64 = unCodedString => {
|
|
43
|
+
return Buffer.from(unCodedString).toString('base64');
|
|
44
|
+
};
|
|
50
45
|
|
|
51
46
|
/** Decode string from base64
|
|
52
47
|
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
53
48
|
* @param codedString
|
|
54
49
|
* @returns {string}
|
|
55
50
|
*/
|
|
56
|
-
const base64ToAscii =
|
|
57
|
-
|
|
58
|
-
}
|
|
51
|
+
const base64ToAscii = codedString => {
|
|
52
|
+
return Buffer.from(codedString, 'base64').toString('utf8');
|
|
53
|
+
};
|
|
59
54
|
|
|
60
55
|
/**
|
|
61
56
|
* Decompose $ connected string and return an object
|
|
@@ -63,16 +58,16 @@ const base64ToAscii = ( codedString ) => {
|
|
|
63
58
|
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
64
59
|
* @param passwordHash
|
|
65
60
|
*/
|
|
66
|
-
const dollarSignConnectedStringToAlgorithmHashSalt =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
61
|
+
const dollarSignConnectedStringToAlgorithmHashSalt = passwordHash => {
|
|
62
|
+
const splitStringArray = passwordHash.split('$');
|
|
63
|
+
if (splitStringArray.length !== 6) return null;
|
|
64
|
+
return {
|
|
65
|
+
version: splitStringArray[1],
|
|
66
|
+
alg: splitStringArray[2],
|
|
67
|
+
hash: splitStringArray[3],
|
|
68
|
+
salt: splitStringArray[4],
|
|
69
|
+
};
|
|
70
|
+
};
|
|
76
71
|
|
|
77
72
|
/**
|
|
78
73
|
* Decompose . connected string and return an object with
|
|
@@ -80,17 +75,16 @@ const dollarSignConnectedStringToAlgorithmHashSalt = ( passwordHash ) => {
|
|
|
80
75
|
* return null if error
|
|
81
76
|
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
82
77
|
*/
|
|
83
|
-
const dotConnectedStringToHeaderPayloadSignature =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
78
|
+
const dotConnectedStringToHeaderPayloadSignature = jwt => {
|
|
79
|
+
if (typeof jwt !== 'string') return null;
|
|
80
|
+
const splitJWT = jwt.split('.');
|
|
81
|
+
if (splitJWT.length !== 3) return null;
|
|
82
|
+
return {
|
|
83
|
+
header: splitJWT[0],
|
|
84
|
+
payload: splitJWT[1],
|
|
85
|
+
signature: splitJWT[2],
|
|
86
|
+
};
|
|
87
|
+
};
|
|
94
88
|
|
|
95
89
|
/**
|
|
96
90
|
* Turns object into url safe string
|
|
@@ -99,7 +93,7 @@ const dotConnectedStringToHeaderPayloadSignature = ( jwt ) => {
|
|
|
99
93
|
* @return {string}
|
|
100
94
|
*/
|
|
101
95
|
const objectToBase64UrlSafeString = object => {
|
|
102
|
-
|
|
96
|
+
return Buffer.from(JSON.stringify(object)).toString('base64url');
|
|
103
97
|
};
|
|
104
98
|
|
|
105
99
|
/**
|
|
@@ -109,16 +103,16 @@ const objectToBase64UrlSafeString = object => {
|
|
|
109
103
|
* @return {any}
|
|
110
104
|
*/
|
|
111
105
|
const urlSafeBase64ToObject = urlSafeBase64String => {
|
|
112
|
-
|
|
106
|
+
return JSON.parse(Buffer.from(urlSafeBase64String, 'base64url').toString('utf8'));
|
|
113
107
|
};
|
|
114
108
|
|
|
115
109
|
module.exports = {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
110
|
+
makeStringUrlSafe,
|
|
111
|
+
reverseStringUrlSafe,
|
|
112
|
+
asciiToBase64,
|
|
113
|
+
base64ToAscii,
|
|
114
|
+
dollarSignConnectedStringToAlgorithmHashSalt,
|
|
115
|
+
dotConnectedStringToHeaderPayloadSignature,
|
|
116
|
+
objectToBase64UrlSafeString,
|
|
117
|
+
urlSafeBase64ToObject,
|
|
124
118
|
};
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carecard/auth-util",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.16",
|
|
4
4
|
"repository": "https://github.com/CareCard-ca/pkg-auth-util.git",
|
|
5
5
|
"description": "Auth utility functions",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"test": "
|
|
9
|
+
"test": "mocha --recursive",
|
|
10
10
|
"test:types": "tsc --noEmit && mocha -r ts-node/register test/types.test.ts",
|
|
11
|
-
"test:coverage": "tsc --noEmit &&
|
|
12
|
-
"
|
|
11
|
+
"test:coverage": "tsc --noEmit && nyc mocha --recursive -r ts-node/register 'test/**/*.{js,ts}'",
|
|
12
|
+
"test:All": "npm run test && npm run test:types",
|
|
13
|
+
"format": "prettier --write .",
|
|
14
|
+
"format:check": "prettier --check .",
|
|
15
|
+
"prepare": "husky",
|
|
16
|
+
"lint:fix": "eslint --fix",
|
|
17
|
+
"lint": "eslint"
|
|
13
18
|
},
|
|
14
19
|
"keywords": [
|
|
15
20
|
"auth",
|
|
@@ -20,17 +25,24 @@
|
|
|
20
25
|
"author": "CareCard team",
|
|
21
26
|
"license": "ISC",
|
|
22
27
|
"devDependencies": {
|
|
28
|
+
"@istanbuljs/nyc-config-typescript": "1.0.2",
|
|
23
29
|
"@types/express": "5.0.6",
|
|
24
30
|
"@types/mocha": "10.0.10",
|
|
25
|
-
"@types/node": "25.
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
31
|
+
"@types/node": "25.9.1",
|
|
32
|
+
"eslint": "9.39.4",
|
|
33
|
+
"express": "5.2.1",
|
|
34
|
+
"husky": "9.1.7",
|
|
35
|
+
"lint-staged": "17.0.5",
|
|
36
|
+
"mocha": "11.7.6",
|
|
37
|
+
"nyc": "18.0.0",
|
|
38
|
+
"prettier": "3.8.3",
|
|
39
|
+
"source-map-support": "0.5.21",
|
|
40
|
+
"supertest": "7.2.2",
|
|
29
41
|
"ts-node": "10.9.2",
|
|
30
|
-
"typescript": "
|
|
42
|
+
"typescript": "6.0.3"
|
|
31
43
|
},
|
|
32
44
|
"dependencies": {
|
|
33
|
-
"@carecard/common-util": "3.1.
|
|
34
|
-
"@carecard/validate": "3.
|
|
45
|
+
"@carecard/common-util": "3.1.15",
|
|
46
|
+
"@carecard/validate": "3.1.27"
|
|
35
47
|
}
|
|
36
48
|
}
|