@carecard/auth-util 3.0.10 → 3.1.11
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/index.d.ts +189 -120
- package/index.js +22 -8
- package/lib/jwtUtilAuth.js +61 -68
- package/lib/pwdUtilAuth.js +22 -46
- package/lib/stringUtilAuth.js +9 -0
- package/package.json +13 -3
- package/readme.md +85 -28
- package/lib/cryptoUtilAuth.js +0 -71
package/index.d.ts
CHANGED
|
@@ -1,115 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for authentication and authorization in the CareCard ecosystem.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {Request} from 'express';
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* Represents the standard JWT header structure.
|
|
3
9
|
*/
|
|
4
10
|
export interface JwtHeader {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
/** The cryptographic algorithm used to secure the JWT. */
|
|
12
|
+
alg?: string;
|
|
13
|
+
/** The media type of the JWT. Defaults to 'JWT'. */
|
|
14
|
+
typ?: string;
|
|
15
|
+
|
|
16
|
+
/** Any other custom header fields. */
|
|
17
|
+
[key: string]: any;
|
|
11
18
|
}
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
21
|
* Represents the standard JWT payload (claims) structure.
|
|
15
22
|
*/
|
|
16
23
|
export interface JwtPayload {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
/** Issued at time, in seconds since the epoch. */
|
|
25
|
+
iat?: number;
|
|
26
|
+
/** Expiration time, in seconds since the epoch. */
|
|
27
|
+
exp?: number;
|
|
28
|
+
/** Not before time, in seconds since the epoch. */
|
|
29
|
+
nbf?: number;
|
|
30
|
+
/** Authentication time, in seconds since the epoch. */
|
|
31
|
+
auth_time?: number;
|
|
32
|
+
/** Subject (usually the client ID). */
|
|
33
|
+
sub?: string;
|
|
34
|
+
/** Roles assigned to the user. */
|
|
35
|
+
roles?: string[];
|
|
36
|
+
|
|
37
|
+
/** Any other custom payload fields. */
|
|
38
|
+
[key: string]: any;
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
/**
|
|
30
42
|
* Container for the decoded header and payload of a JWT.
|
|
31
43
|
*/
|
|
32
44
|
export interface JwtParts {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
45
|
+
/** Decoded JWT header. */
|
|
46
|
+
header: JwtHeader;
|
|
47
|
+
/** Decoded JWT payload. */
|
|
48
|
+
payload: JwtPayload;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Structure of the JWT object attached to the request.
|
|
53
|
+
*/
|
|
54
|
+
export interface JwtRequestObject {
|
|
55
|
+
header: JwtHeader;
|
|
56
|
+
payload: JwtPayload;
|
|
57
|
+
age?: number;
|
|
58
|
+
jwtClientId: (req?: any) => string | undefined;
|
|
59
|
+
doesJwtUserHasRole: (role: string) => boolean;
|
|
60
|
+
isJwtExpired: (jwtValiditySeconds?: number) => boolean;
|
|
61
|
+
jwtAgeInSeconds: (req?: any) => number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Structure of the visitor object attached to the request.
|
|
66
|
+
*/
|
|
67
|
+
export interface VisitorRequestObject {
|
|
68
|
+
header: JwtHeader;
|
|
69
|
+
payload: JwtPayload;
|
|
70
|
+
visitorClientId: (req?: any) => string | undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Extended Express Request to include jwt and visitor objects.
|
|
75
|
+
*/
|
|
76
|
+
export interface AuthenticatedRequest extends Request {
|
|
77
|
+
jwt?: JwtRequestObject | null;
|
|
78
|
+
visitor?: VisitorRequestObject | null;
|
|
37
79
|
}
|
|
38
80
|
|
|
39
81
|
/**
|
|
40
82
|
* Represents the decomposed parts of a stored password hash.
|
|
83
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
41
84
|
*/
|
|
42
85
|
export interface PasswordParts {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
86
|
+
/** Version indicator of the hashing format. */
|
|
87
|
+
version: string;
|
|
88
|
+
/** Base64 encoded algorithm name. */
|
|
89
|
+
alg: string;
|
|
90
|
+
/** Base64 encoded password hash. */
|
|
91
|
+
hash: string;
|
|
92
|
+
/** Base64 encoded random salt. */
|
|
93
|
+
salt: string;
|
|
51
94
|
}
|
|
52
95
|
|
|
53
96
|
/**
|
|
54
97
|
* Contains a pair of public and private cryptographic keys.
|
|
55
98
|
*/
|
|
56
99
|
export interface KeyPair {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
100
|
+
/** PEM formatted public key string. */
|
|
101
|
+
publicKey: string;
|
|
102
|
+
/** PEM formatted private key string. */
|
|
103
|
+
privateKey: string;
|
|
61
104
|
}
|
|
62
105
|
|
|
63
106
|
/**
|
|
64
107
|
* Utility functions for creating, verifying, and parsing JSON Web Tokens (JWT).
|
|
108
|
+
* @deprecated use direct import of the new functions.
|
|
65
109
|
*/
|
|
66
110
|
export const jwtUtilAuth: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Creates a signed JWT from header and payload objects.
|
|
113
|
+
* Automatically normalizes header (sets alg/typ) and payload (sets iat/exp/etc. in seconds).
|
|
114
|
+
* @param headerObject - Header data for the JWT.
|
|
115
|
+
* @param payloadObject - Payload data for the JWT.
|
|
116
|
+
* @param privateKey - PEM formatted private key to sign the token.
|
|
117
|
+
* @returns Signed JWT string or null if an error occurs.
|
|
118
|
+
*/
|
|
119
|
+
createSignedJwtFromObject: (headerObject: JwtHeader, payloadObject: JwtPayload, privateKey: string) => string | null;
|
|
120
|
+
/**
|
|
121
|
+
* Verifies the signature of a JWT using a public key.
|
|
122
|
+
* @param jwt - The JWT string to verify.
|
|
123
|
+
* @param publicKey - PEM formatted public key.
|
|
124
|
+
* @returns True if the signature is valid, false otherwise.
|
|
125
|
+
*/
|
|
126
|
+
verifyJwtSignature: (jwt: string, publicKey: string) => boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Decodes a JWT and returns its header and payload as objects.
|
|
129
|
+
* Note: This does NOT verify the signature.
|
|
130
|
+
* @param jwt - The JWT string to parse.
|
|
131
|
+
* @returns An object containing the header and payload, or null if parsing fails.
|
|
132
|
+
*/
|
|
133
|
+
getHeaderPayloadFromJwt: (jwt: string) => JwtParts | null;
|
|
90
134
|
};
|
|
91
135
|
|
|
92
136
|
/**
|
|
93
137
|
* Utility functions for password hashing and verification.
|
|
138
|
+
* @deprecated use direct imports of the new functions.
|
|
94
139
|
*/
|
|
95
140
|
export const pwdUtilAuth: {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
141
|
+
/**
|
|
142
|
+
* Generates a password hash using a random salt and specified algorithm.
|
|
143
|
+
* @param password - The plain-text password to hash.
|
|
144
|
+
* @param secret - A pepper/secret key to combine with the password.
|
|
145
|
+
* @param algorithm - The hashing algorithm to use (e.g., 'sha256').
|
|
146
|
+
* @returns A string containing the formatted hash with metadata ($1$alg$hash$salt$).
|
|
147
|
+
*/
|
|
148
|
+
createPasswordHashWithRandomSalt: (password: string, secret: string, algorithm: string) => string;
|
|
149
|
+
/**
|
|
150
|
+
* Generates a password hash using the same algorithm and salt from a previously saved hash.
|
|
151
|
+
* Useful for verifying a password against a stored hash.
|
|
152
|
+
* @param password - The plain-text password to verify.
|
|
153
|
+
* @param savedPasswordHash - The full stored hash string (including salt and metadata).
|
|
154
|
+
* @param secret - The pepper/secret key used for hashing.
|
|
155
|
+
* @returns A hash string that should match the saved hash if the password is correct.
|
|
156
|
+
*/
|
|
157
|
+
createPasswordHashBasedOnSavedAlgorithmSalt: (password: string, savedPasswordHash: string, secret: string) => string;
|
|
113
158
|
};
|
|
114
159
|
|
|
115
160
|
/**
|
|
@@ -121,54 +166,78 @@ export const createKeys: (algorithm?: 'ed25519' | 'rsa' | string) => KeyPair;
|
|
|
121
166
|
|
|
122
167
|
/**
|
|
123
168
|
* Utility functions for string manipulation, base64 encoding, and parsing auth-related strings.
|
|
169
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
124
170
|
*/
|
|
125
171
|
export const stringUtilAuth: {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Converts a base64 string to be URL-safe (replaces + with -, / with _, and removes =).
|
|
174
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
175
|
+
* @param urlUnsafeString - The string to convert.
|
|
176
|
+
* @returns URL-safe string.
|
|
177
|
+
*/
|
|
178
|
+
makeStringUrlSafe: (urlUnsafeString?: string) => string;
|
|
179
|
+
/**
|
|
180
|
+
* Reverses URL-safe conversion and restores standard base64 characters and padding.
|
|
181
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
182
|
+
* @param urlSafeString - The URL-safe string to restore.
|
|
183
|
+
* @returns Standard base64 string.
|
|
184
|
+
*/
|
|
185
|
+
reverseStringUrlSafe: (urlSafeString?: string) => string;
|
|
186
|
+
/**
|
|
187
|
+
* Encodes a plain-text string to base64.
|
|
188
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
189
|
+
* @param unCodedString - Plain-text string.
|
|
190
|
+
* @returns Base64 encoded string.
|
|
191
|
+
*/
|
|
192
|
+
asciiToBase64: (unCodedString: string) => string;
|
|
193
|
+
/**
|
|
194
|
+
* Decodes a base64 string to UTF-8 plain-text.
|
|
195
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
196
|
+
* @param codedString - Base64 encoded string.
|
|
197
|
+
* @returns Decoded plain-text string.
|
|
198
|
+
*/
|
|
199
|
+
base64ToAscii: (codedString: string) => string;
|
|
200
|
+
/**
|
|
201
|
+
* Parses a stored password hash string into its constituent parts.
|
|
202
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
203
|
+
* @param passwordHash - The formatted hash string ($1$alg$hash$salt$).
|
|
204
|
+
* @returns A PasswordParts object or null if the format is invalid.
|
|
205
|
+
*/
|
|
206
|
+
dollarSignConnectedStringToAlgorithmHashSalt: (passwordHash: string) => PasswordParts | null;
|
|
207
|
+
/**
|
|
208
|
+
* Splits a JWT into its three base64-encoded string parts (header, payload, signature).
|
|
209
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
210
|
+
* @param jwt - The full JWT string.
|
|
211
|
+
* @returns An object with the three raw parts, or null if the format is invalid.
|
|
212
|
+
*/
|
|
213
|
+
dotConnectedStringToHeaderPayloadSignature: (jwt: string) => {
|
|
214
|
+
header: string,
|
|
215
|
+
payload: string,
|
|
216
|
+
signature: string
|
|
217
|
+
} | null;
|
|
218
|
+
/**
|
|
219
|
+
* Serializes an object into a URL-safe base64 string.
|
|
220
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
221
|
+
* @param object - The object to serialize.
|
|
222
|
+
* @returns URL-safe base64 string.
|
|
223
|
+
*/
|
|
224
|
+
objectToBase64UrlSafeString: (object: any) => string;
|
|
225
|
+
/**
|
|
226
|
+
* Parses a URL-safe base64 string into an object.
|
|
227
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
228
|
+
* @param urlSafeBase64String - URL-safe base64 string.
|
|
229
|
+
* @returns The parsed object.
|
|
230
|
+
*/
|
|
231
|
+
urlSafeBase64ToObject: (urlSafeBase64String: string) => any;
|
|
174
232
|
};
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
export function jwtCreateSignedFromObject(headerObject: JwtHeader, payloadObject: JwtPayload, privateKey: string): string | null;
|
|
236
|
+
|
|
237
|
+
export function jwtVerifySignature(jwt: string, publicKey: string): boolean;
|
|
238
|
+
|
|
239
|
+
export function jwtGetHeaderPayloadFromJwt(jwt: string): JwtParts | null;
|
|
240
|
+
|
|
241
|
+
export function passwordCreateHashWithRandomSalt(password: string, secret: string, algorithm: string): string;
|
|
242
|
+
|
|
243
|
+
export function passwordCreateHashBasedOnSavedAlgorithmSalt(password: string, savedPasswordHash: string, secret: string): string;
|
package/index.js
CHANGED
|
@@ -1,21 +1,35 @@
|
|
|
1
|
-
const pwdUtilAuth = require(
|
|
2
|
-
const jwtUtilAuth = require(
|
|
3
|
-
const keyGen = require(
|
|
1
|
+
const pwdUtilAuth = require('./lib/pwdUtilAuth');
|
|
2
|
+
const jwtUtilAuth = require('./lib/jwtUtilAuth');
|
|
3
|
+
const keyGen = require('./lib/keyGen');
|
|
4
4
|
|
|
5
5
|
module.exports = {
|
|
6
|
+
// New
|
|
7
|
+
createKeys: keyGen.generateKeyPair,
|
|
8
|
+
jwtCreateSignedFromObject: jwtUtilAuth.createSignedJwtFromObject,
|
|
9
|
+
jwtVerifySignature: jwtUtilAuth.verifyJwtSignature,
|
|
10
|
+
jwtGetHeaderPayloadFromJwt: jwtUtilAuth.getHeaderPayloadFromJwt,
|
|
11
|
+
passwordCreateHashWithRandomSalt: pwdUtilAuth.createPasswordHashWithRandomSalt,
|
|
12
|
+
passwordCreateHashBasedOnSavedAlgorithmSalt: pwdUtilAuth.createPasswordHashBasedOnSavedAlgorithmSalt,
|
|
13
|
+
|
|
14
|
+
// Deprecated
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
17
|
+
*/
|
|
6
18
|
jwtUtilAuth: {
|
|
7
19
|
createSignedJwtFromObject: jwtUtilAuth.createSignedJwtFromObject,
|
|
8
20
|
verifyJwtSignature: jwtUtilAuth.verifyJwtSignature,
|
|
9
21
|
getHeaderPayloadFromJwt: jwtUtilAuth.getHeaderPayloadFromJwt
|
|
10
22
|
},
|
|
11
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
25
|
+
*/
|
|
12
26
|
pwdUtilAuth: {
|
|
13
27
|
createPasswordHashWithRandomSalt: pwdUtilAuth.createPasswordHashWithRandomSalt,
|
|
14
28
|
createPasswordHashBasedOnSavedAlgorithmSalt: pwdUtilAuth.createPasswordHashBasedOnSavedAlgorithmSalt
|
|
15
29
|
},
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
stringUtilAuth: require(
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
32
|
+
*/
|
|
33
|
+
stringUtilAuth: require('./lib/stringUtilAuth'),
|
|
20
34
|
};
|
|
21
35
|
|
package/lib/jwtUtilAuth.js
CHANGED
|
@@ -1,35 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
const cryptoUtilAuth = require( './cryptoUtilAuth' );
|
|
1
|
+
const crypto = require( 'crypto' );
|
|
3
2
|
|
|
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
|
-
const _assembleJwt = ( headerBase64, payloadBase64, signatureBase64 ) => {
|
|
12
|
-
return headerBase64 + "." + payloadBase64 + "." + signatureBase64;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Normalizes jwt header
|
|
17
|
-
* @param headerObject
|
|
18
|
-
* @returns {{alg: string, typ: string}}
|
|
19
|
-
*/
|
|
20
|
-
const normalizeHeader = ( headerObject ) => {
|
|
21
|
-
const header = { ...headerObject };
|
|
22
|
-
header.alg = header.alg || 'EdDSA';
|
|
23
|
-
header.typ = 'JWT';
|
|
24
|
-
return header;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Normalizes jwt payload time-related fields
|
|
29
|
-
* @param payloadObject
|
|
30
|
-
* @returns {*}
|
|
31
|
-
*/
|
|
32
|
-
const normalizePayload = ( payloadObject ) => {
|
|
3
|
+
const _normalizePayload = ( payloadObject ) => {
|
|
33
4
|
const payload = { ...payloadObject };
|
|
34
5
|
const now = Math.floor( Date.now() / 1000 );
|
|
35
6
|
const fieldsToNormalize = [ 'iat', 'exp', 'nbf', 'auth_time' ];
|
|
@@ -46,22 +17,39 @@ const normalizePayload = ( payloadObject ) => {
|
|
|
46
17
|
} );
|
|
47
18
|
|
|
48
19
|
if ( !payload.exp ) {
|
|
49
|
-
// Default 1 hour expiration if not provided
|
|
50
20
|
payload.exp = payload.iat + 3600;
|
|
51
|
-
} else if ( payload.exp > msThreshold ) {
|
|
52
|
-
payload.exp = Math.floor( payload.exp / 1000 );
|
|
53
21
|
}
|
|
54
|
-
|
|
55
22
|
return payload;
|
|
56
23
|
};
|
|
57
24
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
25
|
+
const _encode = ( obj ) => {
|
|
26
|
+
return Buffer.from( JSON.stringify( obj ) ).toString( 'base64url' );
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const _decode = ( str ) => {
|
|
30
|
+
return JSON.parse( Buffer.from( str, 'base64url' ).toString( 'utf8' ) );
|
|
31
|
+
};
|
|
32
|
+
|
|
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' );
|
|
42
|
+
};
|
|
43
|
+
|
|
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
|
+
}
|
|
48
|
+
|
|
49
|
+
const verify = crypto.createVerify( alg );
|
|
50
|
+
verify.update( token );
|
|
51
|
+
verify.end();
|
|
52
|
+
return verify.verify( publicKey, signature, 'base64url' );
|
|
65
53
|
};
|
|
66
54
|
|
|
67
55
|
/**
|
|
@@ -75,17 +63,19 @@ const createSignedJwtFromObject = ( headerObject, payloadObject, privateKey ) =>
|
|
|
75
63
|
try {
|
|
76
64
|
if ( !privateKey ) return null;
|
|
77
65
|
|
|
78
|
-
const header =
|
|
79
|
-
|
|
66
|
+
const header = { ...headerObject };
|
|
67
|
+
header.alg = header.alg || 'EdDSA';
|
|
68
|
+
header.typ = 'JWT';
|
|
80
69
|
|
|
81
|
-
const
|
|
82
|
-
|
|
70
|
+
const payload = _normalizePayload( payloadObject );
|
|
71
|
+
|
|
72
|
+
const headerBase64UrlSafe = _encode( header );
|
|
73
|
+
const payloadBase64UrlSafe = _encode( payload );
|
|
83
74
|
const token = headerBase64UrlSafe + "." + payloadBase64UrlSafe;
|
|
84
75
|
|
|
85
|
-
const signature =
|
|
86
|
-
const urlSafeSignature = stringUtilAuth.makeStringUrlSafe( signature );
|
|
76
|
+
const signature = _sign( token, header.alg, privateKey );
|
|
87
77
|
|
|
88
|
-
return
|
|
78
|
+
return token + "." + signature;
|
|
89
79
|
} catch ( error ) {
|
|
90
80
|
return null;
|
|
91
81
|
}
|
|
@@ -100,13 +90,14 @@ const createSignedJwtFromObject = ( headerObject, payloadObject, privateKey ) =>
|
|
|
100
90
|
const verifyJwtSignature = ( jwt, publicKey ) => {
|
|
101
91
|
try {
|
|
102
92
|
if ( !jwt || !publicKey ) return false;
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
|
|
93
|
+
const splitJWT = jwt.split( '.' );
|
|
94
|
+
if ( splitJWT.length !== 3 ) return false;
|
|
95
|
+
|
|
96
|
+
const [ header, payload, signature ] = splitJWT;
|
|
97
|
+
const token = header + "." + payload;
|
|
98
|
+
const headerObject = _decode( header );
|
|
99
|
+
|
|
100
|
+
return _verify( token, signature, headerObject.alg, publicKey );
|
|
110
101
|
} catch ( error ) {
|
|
111
102
|
return false;
|
|
112
103
|
}
|
|
@@ -115,28 +106,30 @@ const verifyJwtSignature = ( jwt, publicKey ) => {
|
|
|
115
106
|
/**
|
|
116
107
|
* Returns header and payload object for jwt.
|
|
117
108
|
* @param jwt
|
|
118
|
-
* @return {{payload:
|
|
109
|
+
* @return {{payload: *, header: *}|null}
|
|
119
110
|
*/
|
|
120
111
|
const getHeaderPayloadFromJwt = jwt => {
|
|
121
112
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
113
|
+
if ( typeof jwt !== 'string' ) return null;
|
|
114
|
+
const splitJWT = jwt.split( '.' );
|
|
115
|
+
if ( splitJWT.length !== 3 ) return null;
|
|
116
|
+
|
|
117
|
+
const headerObject = _decode( splitJWT[ 0 ] );
|
|
118
|
+
const payloadObject = _decode( splitJWT[ 1 ] );
|
|
119
|
+
|
|
127
120
|
return { header: headerObject, payload: payloadObject }
|
|
128
121
|
} catch ( e ) {
|
|
129
122
|
return null;
|
|
130
123
|
}
|
|
131
124
|
};
|
|
132
125
|
|
|
133
|
-
|
|
134
126
|
module.exports = {
|
|
135
|
-
_assembleJwt,
|
|
136
|
-
_splitJwtInToHeaderPayloadSignature,
|
|
137
|
-
normalizeHeader,
|
|
138
|
-
normalizePayload,
|
|
139
127
|
createSignedJwtFromObject,
|
|
140
128
|
verifyJwtSignature,
|
|
141
|
-
getHeaderPayloadFromJwt
|
|
129
|
+
getHeaderPayloadFromJwt,
|
|
130
|
+
_normalizePayload,
|
|
131
|
+
_encode,
|
|
132
|
+
_decode,
|
|
133
|
+
_sign,
|
|
134
|
+
_verify
|
|
142
135
|
};
|
package/lib/pwdUtilAuth.js
CHANGED
|
@@ -1,40 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
const stringUtilAuth = require( './stringUtilAuth' );
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Just assemble password together
|
|
6
|
-
* @param algorithmBase64
|
|
7
|
-
* @param hashBase64
|
|
8
|
-
* @param saltBase64
|
|
9
|
-
* @return {string}
|
|
10
|
-
*/
|
|
11
|
-
const _assemblePasswordHash = ( algorithmBase64, hashBase64, saltBase64 ) => {
|
|
12
|
-
return "$1$" + algorithmBase64 + "$" + hashBase64 + "$" + saltBase64 + "$";
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Break password into its parts does not reverse base64 encoding.
|
|
17
|
-
* @param passwordHashStored
|
|
18
|
-
* @return {{salt: *, version: *, alg: *, hash: *}}
|
|
19
|
-
*/
|
|
20
|
-
const _disassemblePasswordHash = passwordHashStored => {
|
|
21
|
-
return stringUtilAuth.dollarSignConnectedStringToAlgorithmHashSalt( passwordHashStored );
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Creates password hash ready to be saved in database.
|
|
27
|
-
* @param password
|
|
28
|
-
* @param secret
|
|
29
|
-
* @param salt
|
|
30
|
-
* @param algorithm
|
|
31
|
-
* @return {string}
|
|
32
|
-
*/
|
|
33
|
-
const _createPasswordHash = ( password, secret, salt, algorithm ) => {
|
|
34
|
-
const algorithmBase64 = stringUtilAuth.asciiToBase64( algorithm );
|
|
35
|
-
const hashBase64 = cryptoUtilAuth.createHmacBase64( password, secret, algorithm );
|
|
36
|
-
return _assemblePasswordHash( algorithmBase64, hashBase64, salt );
|
|
37
|
-
};
|
|
1
|
+
const crypto = require( 'crypto' );
|
|
38
2
|
|
|
39
3
|
/**
|
|
40
4
|
* Automatically adds random salt.
|
|
@@ -44,8 +8,14 @@ const _createPasswordHash = ( password, secret, salt, algorithm ) => {
|
|
|
44
8
|
* @return {string}
|
|
45
9
|
*/
|
|
46
10
|
const createPasswordHashWithRandomSalt = ( password, secret, algorithm ) => {
|
|
47
|
-
|
|
48
|
-
|
|
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
|
+
}
|
|
49
19
|
};
|
|
50
20
|
|
|
51
21
|
/**
|
|
@@ -56,16 +26,22 @@ const createPasswordHashWithRandomSalt = ( password, secret, algorithm ) => {
|
|
|
56
26
|
* @return {string}
|
|
57
27
|
*/
|
|
58
28
|
const createPasswordHashBasedOnSavedAlgorithmSalt = ( password, savedPasswordHash, secret ) => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
29
|
+
try {
|
|
30
|
+
const splitStringArray = savedPasswordHash.split( '$' );
|
|
31
|
+
if ( splitStringArray.length !== 6 ) return null;
|
|
32
|
+
|
|
33
|
+
const algBase64 = splitStringArray[ 2 ];
|
|
34
|
+
const salt = splitStringArray[ 4 ];
|
|
35
|
+
const algorithm = Buffer.from( algBase64, 'base64' ).toString( 'utf8' );
|
|
36
|
+
|
|
37
|
+
const hashBase64 = crypto.createHmac( algorithm, secret ).update( password ).digest( 'base64' );
|
|
38
|
+
return "$1$" + algBase64 + "$" + hashBase64 + "$" + salt + "$";
|
|
39
|
+
} catch ( e ) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
62
42
|
};
|
|
63
43
|
|
|
64
|
-
|
|
65
44
|
module.exports = {
|
|
66
|
-
_assemblePasswordHash,
|
|
67
|
-
_disassemblePasswordHash,
|
|
68
|
-
_createPasswordHash,
|
|
69
45
|
createPasswordHashWithRandomSalt,
|
|
70
46
|
createPasswordHashBasedOnSavedAlgorithmSalt
|
|
71
47
|
}
|
package/lib/stringUtilAuth.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Adjusts padding of base64String
|
|
9
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
9
10
|
* @param base64String
|
|
10
11
|
* @return {*}
|
|
11
12
|
*/
|
|
@@ -15,6 +16,7 @@ const adjustBase64Padding = base64String => {
|
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Removes /, + and = from the string
|
|
19
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
18
20
|
* @returns {string}
|
|
19
21
|
*/
|
|
20
22
|
const makeStringUrlSafe = ( urlUnsafeString = '' ) => {
|
|
@@ -26,6 +28,7 @@ const makeStringUrlSafe = ( urlUnsafeString = '' ) => {
|
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* Put back /, + and = into the string
|
|
31
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
29
32
|
* @returns {string}
|
|
30
33
|
*/
|
|
31
34
|
const reverseStringUrlSafe = ( urlSafeString = '' ) => {
|
|
@@ -37,6 +40,7 @@ const reverseStringUrlSafe = ( urlSafeString = '' ) => {
|
|
|
37
40
|
|
|
38
41
|
/**
|
|
39
42
|
* Encode string to base64 string
|
|
43
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
40
44
|
* @param unCodedString
|
|
41
45
|
* @returns {string}
|
|
42
46
|
*/
|
|
@@ -45,6 +49,7 @@ const asciiToBase64 = ( unCodedString ) => {
|
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
/** Decode string from base64
|
|
52
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
48
53
|
* @param codedString
|
|
49
54
|
* @returns {string}
|
|
50
55
|
*/
|
|
@@ -55,6 +60,7 @@ const base64ToAscii = ( codedString ) => {
|
|
|
55
60
|
/**
|
|
56
61
|
* Decompose $ connected string and return an object
|
|
57
62
|
* return null if error
|
|
63
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
58
64
|
* @param passwordHash
|
|
59
65
|
*/
|
|
60
66
|
const dollarSignConnectedStringToAlgorithmHashSalt = ( passwordHash ) => {
|
|
@@ -72,6 +78,7 @@ const dollarSignConnectedStringToAlgorithmHashSalt = ( passwordHash ) => {
|
|
|
72
78
|
* Decompose . connected string and return an object with
|
|
73
79
|
* {header: 'string', payload: 'string', signature: 'string'}
|
|
74
80
|
* return null if error
|
|
81
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
75
82
|
*/
|
|
76
83
|
const dotConnectedStringToHeaderPayloadSignature = ( jwt ) => {
|
|
77
84
|
if ( typeof jwt !== 'string' ) return null;
|
|
@@ -87,6 +94,7 @@ const dotConnectedStringToHeaderPayloadSignature = ( jwt ) => {
|
|
|
87
94
|
|
|
88
95
|
/**
|
|
89
96
|
* Turns object into url safe string
|
|
97
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
90
98
|
* @param object
|
|
91
99
|
* @return {string}
|
|
92
100
|
*/
|
|
@@ -96,6 +104,7 @@ const objectToBase64UrlSafeString = object => {
|
|
|
96
104
|
|
|
97
105
|
/**
|
|
98
106
|
* Turns base64 into object
|
|
107
|
+
* @deprecated Use native Buffer methods or other modern alternatives.
|
|
99
108
|
* @param urlSafeBase64String
|
|
100
109
|
* @return {any}
|
|
101
110
|
*/
|
package/package.json
CHANGED
|
@@ -1,26 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carecard/auth-util",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.11",
|
|
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
9
|
"test": "export NODE_ENV=test && mocha --recursive",
|
|
10
|
-
"test:types": "tsc --noEmit && mocha -r ts-node/register test/types.test.ts"
|
|
10
|
+
"test:types": "tsc --noEmit && mocha -r ts-node/register test/types.test.ts",
|
|
11
|
+
"test:coverage": "tsc --noEmit && export NODE_ENV=test && nyc mocha --recursive -r ts-node/register 'test/**/*.{js,ts}'",
|
|
12
|
+
"prepare": "husky"
|
|
11
13
|
},
|
|
12
14
|
"keywords": [
|
|
13
15
|
"auth",
|
|
14
16
|
"utility",
|
|
15
|
-
"cryptology"
|
|
17
|
+
"cryptology",
|
|
18
|
+
"jwt"
|
|
16
19
|
],
|
|
17
20
|
"author": "CareCard team",
|
|
18
21
|
"license": "ISC",
|
|
19
22
|
"devDependencies": {
|
|
23
|
+
"@types/express": "5.0.6",
|
|
20
24
|
"@types/mocha": "10.0.10",
|
|
21
25
|
"@types/node": "25.5.0",
|
|
26
|
+
"husky": "^9.1.7",
|
|
22
27
|
"mocha": "11.7.5",
|
|
28
|
+
"nyc": "^18.0.0",
|
|
23
29
|
"ts-node": "10.9.2",
|
|
24
30
|
"typescript": "5.9.3"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@carecard/common-util": "3.1.11",
|
|
34
|
+
"@carecard/validate": "3.0.11"
|
|
25
35
|
}
|
|
26
36
|
}
|
package/readme.md
CHANGED
|
@@ -1,51 +1,108 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @carecard/auth-util
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+

|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Utility package for authentication and authorization in the CareCard ecosystem.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
## Features
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
- **JWT Utilities**: Create, verify, and parse JSON Web Tokens with support for EdDSA (Ed25519) and RSA.
|
|
11
|
+
- **Password Utilities**: Secure password hashing using HMAC with random salt and a custom string format for easy storage.
|
|
12
|
+
- **Key Generation**: Generate Ed25519 and RSA key pairs for JWT signing.
|
|
13
|
+
- **Crypto Utilities**: Low-level cryptographic primitives for signing, verification, and hashing.
|
|
14
|
+
- **String Utilities**: Base64 and Base64UrlSafe encoding/decoding, and custom string parsing.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @carecard/auth-util
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### JWT Utilities (`jwtUtilAuth`)
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
const { jwtUtilAuth } = require('@carecard/auth-util');
|
|
28
|
+
|
|
29
|
+
const header = { alg: 'EdDSA', typ: 'JWT' };
|
|
30
|
+
const payload = { sub: '1234567890', name: 'John Doe' };
|
|
31
|
+
const privateKey = '...'; // Your private PEM key
|
|
32
|
+
|
|
33
|
+
// Create a signed JWT
|
|
34
|
+
const token = jwtUtilAuth.createSignedJwtFromObject(header, payload, privateKey);
|
|
35
|
+
|
|
36
|
+
// Verify a JWT signature
|
|
37
|
+
const publicKey = '...'; // Your public PEM key
|
|
38
|
+
const isValid = jwtUtilAuth.verifyJwtSignature(token, publicKey);
|
|
39
|
+
|
|
40
|
+
// Get header and payload from a JWT
|
|
41
|
+
const { header: decodedHeader, payload: decodedPayload } = jwtUtilAuth.getHeaderPayloadFromJwt(token);
|
|
11
42
|
```
|
|
12
43
|
|
|
13
|
-
|
|
44
|
+
### Password Utilities (`pwdUtilAuth`)
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
const { pwdUtilAuth } = require('@carecard/auth-util');
|
|
14
48
|
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
...
|
|
19
|
-
};
|
|
49
|
+
const password = 'mySecretPassword';
|
|
50
|
+
const secret = 'application-wide-secret';
|
|
51
|
+
const algorithm = 'sha512';
|
|
20
52
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
53
|
+
// Create a new password hash with a random salt
|
|
54
|
+
const hash = pwdUtilAuth.createPasswordHashWithRandomSalt(password, secret, algorithm);
|
|
55
|
+
// Resulting format: $1$base64(algorithm)$base64(hash)$base64(salt)$
|
|
24
56
|
|
|
25
|
-
|
|
57
|
+
// Verify a password against a saved hash
|
|
58
|
+
const isCorrect = (pwdUtilAuth.createPasswordHashBasedOnSavedAlgorithmSalt(password, hash, secret) === hash);
|
|
26
59
|
```
|
|
27
60
|
|
|
28
|
-
|
|
61
|
+
### Key Generation
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
const { createKeys } = require('@carecard/auth-util');
|
|
29
65
|
|
|
30
|
-
|
|
31
|
-
const
|
|
66
|
+
// Generate Ed25519 keys (default)
|
|
67
|
+
const { publicKey, privateKey } = createKeys();
|
|
68
|
+
|
|
69
|
+
// Generate RSA keys
|
|
70
|
+
const rsaKeys = createKeys('rsa');
|
|
32
71
|
```
|
|
33
72
|
|
|
34
|
-
|
|
73
|
+
### String Utilities (`stringUtilAuth`)
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const { stringUtilAuth } = require('@carecard/auth-util');
|
|
35
77
|
|
|
36
|
-
|
|
37
|
-
const
|
|
78
|
+
const base64 = stringUtilAuth.asciiToBase64('Hello World');
|
|
79
|
+
const original = stringUtilAuth.base64ToAscii(base64);
|
|
80
|
+
|
|
81
|
+
const urlSafe = stringUtilAuth.makeStringUrlSafe('a+b/c==');
|
|
82
|
+
// Result: a-b_c
|
|
38
83
|
```
|
|
39
84
|
|
|
40
|
-
|
|
85
|
+
## Testing
|
|
86
|
+
|
|
87
|
+
Run tests using:
|
|
41
88
|
|
|
42
|
-
```
|
|
43
|
-
|
|
89
|
+
```bash
|
|
90
|
+
npm test
|
|
44
91
|
```
|
|
45
92
|
|
|
46
|
-
|
|
93
|
+
To run type tests:
|
|
47
94
|
|
|
48
|
-
```
|
|
49
|
-
|
|
95
|
+
```bash
|
|
96
|
+
npm run test:types
|
|
50
97
|
```
|
|
51
98
|
|
|
99
|
+
## Architecture
|
|
100
|
+
|
|
101
|
+
The package is organized into several modules:
|
|
102
|
+
- `jwtUtilAuth`: Manages the JWT lifecycle.
|
|
103
|
+
- `pwdUtilAuth`: Handles password hashing and verification.
|
|
104
|
+
- `keyGen`: Utility for generating cryptographic keys.
|
|
105
|
+
- `cryptoUtilAuth`: Core cryptographic operations using Node.js `crypto` module.
|
|
106
|
+
- `stringUtilAuth`: String manipulation and format conversions.
|
|
107
|
+
|
|
108
|
+
All modules are exported through the main `index.js`.
|
package/lib/cryptoUtilAuth.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
const crypto = require( "crypto" );
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Signs a token returns signature string
|
|
6
|
-
* @param token
|
|
7
|
-
* @param privateKey
|
|
8
|
-
* @param signingAlgorithm
|
|
9
|
-
* @returns {string}
|
|
10
|
-
*/
|
|
11
|
-
const createBase64SignatureOfToken = function ( token = '', privateKey, signingAlgorithm = 'EdDSA' ) {
|
|
12
|
-
if ( signingAlgorithm === 'EdDSA' || signingAlgorithm === 'Ed25519' ) {
|
|
13
|
-
return crypto.sign( null, Buffer.from( token ), privateKey ).toString( 'base64' );
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const sign = crypto.createSign( signingAlgorithm );
|
|
17
|
-
sign.write( token );
|
|
18
|
-
sign.end();
|
|
19
|
-
return sign.sign( privateKey, 'base64' );
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Verifies the signature returns true or false
|
|
24
|
-
* @param token
|
|
25
|
-
* @param signature
|
|
26
|
-
* @param publicKey
|
|
27
|
-
* @param signingAlgorithm
|
|
28
|
-
* @returns {boolean}
|
|
29
|
-
*/
|
|
30
|
-
const verifyBase64SignatureOfToken = function ( token = '', signature, publicKey, signingAlgorithm = 'EdDSA' ) {
|
|
31
|
-
try {
|
|
32
|
-
if ( signingAlgorithm === 'EdDSA' || signingAlgorithm === 'Ed25519' ) {
|
|
33
|
-
return crypto.verify( null, Buffer.from( token ), publicKey, Buffer.from( signature, 'base64' ) );
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const verify = crypto.createVerify( signingAlgorithm );
|
|
37
|
-
verify.update( token );
|
|
38
|
-
verify.end();
|
|
39
|
-
return verify.verify( publicKey, signature, 'base64' );
|
|
40
|
-
} catch ( e ) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Creates the hash of given string
|
|
47
|
-
* @param string
|
|
48
|
-
* @param secret
|
|
49
|
-
* @param algorithm
|
|
50
|
-
* @returns {string}
|
|
51
|
-
*/
|
|
52
|
-
const createHmacBase64 = function ( string = '', secret, algorithm ) {
|
|
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
|
-
const createSaltBase64 = ( size = 32 ) => {
|
|
63
|
-
return crypto.randomBytes( size ).toString( 'base64' );
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
module.exports = {
|
|
67
|
-
createBase64SignatureOfToken,
|
|
68
|
-
verifyBase64SignatureOfToken,
|
|
69
|
-
createHmacBase64,
|
|
70
|
-
createSaltBase64
|
|
71
|
-
};
|