@vardario/cognito-client 1.0.1 → 2.0.0

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/README.md CHANGED
@@ -1,3 +1,4 @@
1
1
  # Cognito Client
2
2
 
3
3
  A lightweight cognito client implementation which support SRP authentication.
4
+ Works in node and the browser.
@@ -150,6 +150,7 @@ export interface ChallengeResponse {
150
150
  };
151
151
  }
152
152
  export declare function authResultToSession(authenticationResult: AuthenticationResult): Session;
153
+ export declare function cognitoRequest(body: object, serviceTarget: CognitoServiceTarget, cognitoEndpoint: string): Promise<any>;
153
154
  /**
154
155
  * Lightweight AWS Cogito client without any AWS SDK dependencies.
155
156
  */
@@ -160,7 +161,6 @@ export declare class CognitoClient {
160
161
  private readonly oAuth?;
161
162
  constructor({ userPoolId, userPoolClientId, endpoint, oAuth2: oAuth }: CognitoClientProps);
162
163
  static getDecodedTokenFromSession(session: Session): DecodedTokens;
163
- private cognitoRequest;
164
164
  /**
165
165
  *
166
166
  * Performs user authentication with username and password through ALLOW_USER_SRP_AUTH .
@@ -168,7 +168,8 @@ export declare class CognitoClient {
168
168
  *
169
169
  * @param username Username
170
170
  * @param password Password
171
- * @throws {CognitoException}
171
+ *
172
+ * @throws {InitiateAuthException}
172
173
  */
173
174
  authenticateUserSrp(username: string, password: string): Promise<Session>;
174
175
  /**
@@ -178,7 +179,7 @@ export declare class CognitoClient {
178
179
  *
179
180
  * @param username Username
180
181
  * @param password Password
181
- * @throws {CognitoException}
182
+ * @throws {InitiateAuthException}
182
183
  */
183
184
  authenticateUser(username: string, password: string): Promise<Session>;
184
185
  /**
@@ -186,7 +187,7 @@ export declare class CognitoClient {
186
187
  *
187
188
  * @param refreshToken
188
189
  * @returns @see Session
189
- * @throws {CognitoError}
190
+ * @throws {InitiateAuthException}
190
191
  */
191
192
  refreshSession(refreshToken: string): Promise<Session>;
192
193
  /**
@@ -194,7 +195,7 @@ export declare class CognitoClient {
194
195
  * @param username Username
195
196
  * @param password Password
196
197
  *
197
- * @throws {CognitoException}
198
+ * @throws {SignUpException}
198
199
  */
199
200
  signUp(username: string, password: string, userAttributes?: UserAttribute[]): Promise<{
200
201
  id: string;
@@ -206,7 +207,7 @@ export declare class CognitoClient {
206
207
  * @param username Username
207
208
  * @param code Confirmation code the user gets through the registration E-Mail
208
209
  *
209
- * @throws {CognitoException}
210
+ * @throws {ConfirmSignUpException}
210
211
  */
211
212
  confirmSignUp(username: string, code: string): Promise<void>;
212
213
  /**
@@ -214,22 +215,39 @@ export declare class CognitoClient {
214
215
  * @param currentPassword Current user password.
215
216
  * @param newPassword New user password.
216
217
  *
217
- * @throws {CognitoException}
218
+ * @throws {ChangePasswordException}
218
219
  */
219
220
  changePassword(currentPassword: string, newPassword: string, accessToken: string): Promise<void>;
221
+ /**
222
+ * Updates the user attributes.
223
+ *
224
+ * @param userAttributes List of user attributes to update.
225
+ * @param accessToken Access token of the current user.
226
+ *
227
+ * @throws {UpdateUserAttributesException}
228
+ */
220
229
  updateUserAttributes(userAttributes: UserAttribute[], accessToken: string): Promise<void>;
230
+ /**
231
+ * Verifies a given user attribute
232
+ *
233
+ * @param attributeName Name of the attribute to verify
234
+ * @param code Verification code
235
+ * @param accessToken Access token of the current user.
236
+ *
237
+ * @throws {VerifyUserAttributeException}
238
+ */
221
239
  verifyUserAttribute(attributeName: string, code: string, accessToken: string): Promise<void>;
222
240
  /**
223
241
  * Sign out the user and remove the current user session.
224
242
  *
225
- * @throws {CognitoException}
243
+ * @throws {RevokeTokenException}
226
244
  */
227
245
  signOut(refreshToken: string): Promise<void>;
228
246
  /**
229
247
  * Request forgot password.
230
248
  * @param username Username
231
249
  *
232
- * @throws {CognitoException}
250
+ * @throws {ForgotPasswordException}
233
251
  */
234
252
  forgotPassword(username: string): Promise<void>;
235
253
  /**
@@ -239,12 +257,14 @@ export declare class CognitoClient {
239
257
  * @param newPassword New password
240
258
  * @param confirmationCode Confirmation code which the user got through E-mail
241
259
  *
242
- * @throws {CognitoException}
260
+ * @throws {ConfirmForgotPasswordException}
243
261
  */
244
262
  confirmForgotPassword(username: string, newPassword: string, confirmationCode: string): Promise<void>;
245
263
  /**
246
264
  * Triggers cognito to resend the confirmation code
247
265
  * @param username Username
266
+ *
267
+ * @throws {ResendConfirmationCodeException}
248
268
  */
249
269
  resendConfirmationCode(username: string): Promise<void>;
250
270
  /**
@@ -1,7 +1,7 @@
1
1
  import hashJs from 'hash.js';
2
2
  import { BigInteger } from 'jsbn';
3
3
  import { Buffer } from 'buffer';
4
- import { CognitoError, CognitoException } from './error.js';
4
+ import { CognitoCommonException, CognitoError } from './error.js';
5
5
  import { calculateSignature, calculateU, decodeJwt, generateA, generateSmallA, getPasswordAuthenticationKey, randomBytes } from './utils.js';
6
6
  /**
7
7
  * List of used and supported Cognito API calls.
@@ -41,6 +41,40 @@ export function authResultToSession(authenticationResult) {
41
41
  refreshToken: authenticationResult.RefreshToken
42
42
  };
43
43
  }
44
+ export async function cognitoRequest(body, serviceTarget, cognitoEndpoint) {
45
+ const cognitoResponse = await fetch(cognitoEndpoint, {
46
+ headers: {
47
+ 'x-amz-target': `AWSCognitoIdentityProviderService.${serviceTarget}`,
48
+ 'content-type': 'application/x-amz-json-1.1'
49
+ },
50
+ method: 'POST',
51
+ body: JSON.stringify(body)
52
+ });
53
+ if (cognitoResponse && cognitoResponse.status < 300) {
54
+ return cognitoResponse.json();
55
+ }
56
+ const cognitoResponseBody = await cognitoResponse.json();
57
+ /**
58
+ * The whole error handling and value sanitization was inspired
59
+ * by @see https://github.com/aws-amplify/amplify-js/blob/1f5eefd9c40285eb99e57764ac8fca1f9519e2c6/packages/core/src/clients/serde/json.ts#L14
60
+ */
61
+ const sanitizeErrorType = (rawValue) => {
62
+ const [cleanValue] = rawValue.toString().split(/[,:]+/);
63
+ if (cleanValue.includes('#')) {
64
+ return cleanValue.split('#')[1];
65
+ }
66
+ return cleanValue;
67
+ };
68
+ const errorMessage = cognitoResponse.headers.get('X-Amzn-ErrorMessage') ??
69
+ cognitoResponseBody.message ??
70
+ cognitoResponseBody.Message ??
71
+ 'Unknown error';
72
+ const cognitoException = sanitizeErrorType(cognitoResponse.headers.get('X-Amzn-ErrorType') ??
73
+ cognitoResponseBody.code ??
74
+ cognitoResponseBody.__type ??
75
+ CognitoCommonException.Unknown);
76
+ throw new CognitoError(errorMessage, cognitoException);
77
+ }
44
78
  /**
45
79
  * Lightweight AWS Cogito client without any AWS SDK dependencies.
46
80
  */
@@ -60,22 +94,6 @@ export class CognitoClient {
60
94
  accessToken
61
95
  };
62
96
  }
63
- async cognitoRequest(body, serviceTarget) {
64
- const cognitoResponse = await fetch(this.cognitoEndpoint, {
65
- headers: {
66
- 'x-amz-target': `AWSCognitoIdentityProviderService.${serviceTarget}`,
67
- 'content-type': 'application/x-amz-json-1.1'
68
- },
69
- method: 'POST',
70
- body: JSON.stringify(body)
71
- });
72
- if (cognitoResponse.status < 200 || cognitoResponse.status > 299) {
73
- const errorMessage = cognitoResponse.headers.get('X-Amzn-ErrorMessage') ?? 'Unknown';
74
- const cognitoException = cognitoResponse.headers.get('X-Amzn-ErrorType') ?? CognitoException.Unknown;
75
- throw new CognitoError(errorMessage, cognitoException);
76
- }
77
- return cognitoResponse.json();
78
- }
79
97
  /**
80
98
  *
81
99
  * Performs user authentication with username and password through ALLOW_USER_SRP_AUTH .
@@ -83,7 +101,8 @@ export class CognitoClient {
83
101
  *
84
102
  * @param username Username
85
103
  * @param password Password
86
- * @throws {CognitoException}
104
+ *
105
+ * @throws {InitiateAuthException}
87
106
  */
88
107
  async authenticateUserSrp(username, password) {
89
108
  const smallA = await generateSmallA();
@@ -97,7 +116,7 @@ export class CognitoClient {
97
116
  },
98
117
  ClientMetadata: {}
99
118
  };
100
- const challenge = (await this.cognitoRequest(initiateAuthPayload, CognitoServiceTarget.InitiateAuth));
119
+ const challenge = (await cognitoRequest(initiateAuthPayload, CognitoServiceTarget.InitiateAuth, this.cognitoEndpoint));
101
120
  const B = new BigInteger(challenge.ChallengeParameters.SRP_B, 16);
102
121
  const salt = new BigInteger(challenge.ChallengeParameters.SALT, 16);
103
122
  const U = calculateU(A, B);
@@ -114,7 +133,7 @@ export class CognitoClient {
114
133
  },
115
134
  ClientMetadata: {}
116
135
  };
117
- const { AuthenticationResult } = await this.cognitoRequest(respondToAuthChallengePayload, CognitoServiceTarget.RespondToAuthChallenge);
136
+ const { AuthenticationResult } = await cognitoRequest(respondToAuthChallengePayload, CognitoServiceTarget.RespondToAuthChallenge, this.cognitoEndpoint);
118
137
  return authResultToSession(AuthenticationResult);
119
138
  }
120
139
  /**
@@ -124,7 +143,7 @@ export class CognitoClient {
124
143
  *
125
144
  * @param username Username
126
145
  * @param password Password
127
- * @throws {CognitoException}
146
+ * @throws {InitiateAuthException}
128
147
  */
129
148
  async authenticateUser(username, password) {
130
149
  const initiateAuthPayload = {
@@ -136,7 +155,7 @@ export class CognitoClient {
136
155
  },
137
156
  ClientMetadata: {}
138
157
  };
139
- const { AuthenticationResult } = (await this.cognitoRequest(initiateAuthPayload, CognitoServiceTarget.InitiateAuth));
158
+ const { AuthenticationResult } = (await cognitoRequest(initiateAuthPayload, CognitoServiceTarget.InitiateAuth, this.cognitoEndpoint));
140
159
  const session = authResultToSession(AuthenticationResult);
141
160
  return session;
142
161
  }
@@ -145,7 +164,7 @@ export class CognitoClient {
145
164
  *
146
165
  * @param refreshToken
147
166
  * @returns @see Session
148
- * @throws {CognitoError}
167
+ * @throws {InitiateAuthException}
149
168
  */
150
169
  async refreshSession(refreshToken) {
151
170
  const refreshTokenPayload = {
@@ -156,7 +175,7 @@ export class CognitoClient {
156
175
  },
157
176
  ClientMetadata: {}
158
177
  };
159
- const { AuthenticationResult } = (await this.cognitoRequest(refreshTokenPayload, CognitoServiceTarget.InitiateAuth));
178
+ const { AuthenticationResult } = (await cognitoRequest(refreshTokenPayload, CognitoServiceTarget.InitiateAuth, this.cognitoEndpoint));
160
179
  if (!AuthenticationResult.RefreshToken) {
161
180
  AuthenticationResult.RefreshToken = refreshToken;
162
181
  }
@@ -167,7 +186,7 @@ export class CognitoClient {
167
186
  * @param username Username
168
187
  * @param password Password
169
188
  *
170
- * @throws {CognitoException}
189
+ * @throws {SignUpException}
171
190
  */
172
191
  async signUp(username, password, userAttributes) {
173
192
  const signUpPayload = {
@@ -176,7 +195,7 @@ export class CognitoClient {
176
195
  Password: password,
177
196
  UserAttributes: userAttributes
178
197
  };
179
- const data = await this.cognitoRequest(signUpPayload, CognitoServiceTarget.SignUp);
198
+ const data = await cognitoRequest(signUpPayload, CognitoServiceTarget.SignUp, this.cognitoEndpoint);
180
199
  return {
181
200
  id: data.UserSub,
182
201
  confirmed: data.UserConfirmed
@@ -188,7 +207,7 @@ export class CognitoClient {
188
207
  * @param username Username
189
208
  * @param code Confirmation code the user gets through the registration E-Mail
190
209
  *
191
- * @throws {CognitoException}
210
+ * @throws {ConfirmSignUpException}
192
211
  */
193
212
  async confirmSignUp(username, code) {
194
213
  const confirmSignUpPayload = {
@@ -196,14 +215,14 @@ export class CognitoClient {
196
215
  ConfirmationCode: code,
197
216
  Username: username
198
217
  };
199
- await this.cognitoRequest(confirmSignUpPayload, CognitoServiceTarget.ConfirmSignUp);
218
+ await cognitoRequest(confirmSignUpPayload, CognitoServiceTarget.ConfirmSignUp, this.cognitoEndpoint);
200
219
  }
201
220
  /**
202
221
  *
203
222
  * @param currentPassword Current user password.
204
223
  * @param newPassword New user password.
205
224
  *
206
- * @throws {CognitoException}
225
+ * @throws {ChangePasswordException}
207
226
  */
208
227
  async changePassword(currentPassword, newPassword, accessToken) {
209
228
  const changePasswordPayload = {
@@ -211,47 +230,64 @@ export class CognitoClient {
211
230
  ProposedPassword: newPassword,
212
231
  AccessToken: accessToken
213
232
  };
214
- await this.cognitoRequest(changePasswordPayload, CognitoServiceTarget.ChangePassword);
233
+ await cognitoRequest(changePasswordPayload, CognitoServiceTarget.ChangePassword, this.cognitoEndpoint);
215
234
  }
235
+ /**
236
+ * Updates the user attributes.
237
+ *
238
+ * @param userAttributes List of user attributes to update.
239
+ * @param accessToken Access token of the current user.
240
+ *
241
+ * @throws {UpdateUserAttributesException}
242
+ */
216
243
  async updateUserAttributes(userAttributes, accessToken) {
217
244
  const updateUserAttributesPayload = {
218
245
  UserAttributes: userAttributes,
219
246
  AccessToken: accessToken
220
247
  };
221
- await this.cognitoRequest(updateUserAttributesPayload, CognitoServiceTarget.UpdateUserAttributes);
248
+ await cognitoRequest(updateUserAttributesPayload, CognitoServiceTarget.UpdateUserAttributes, this.cognitoEndpoint);
222
249
  }
250
+ /**
251
+ * Verifies a given user attribute
252
+ *
253
+ * @param attributeName Name of the attribute to verify
254
+ * @param code Verification code
255
+ * @param accessToken Access token of the current user.
256
+ *
257
+ * @throws {VerifyUserAttributeException}
258
+ */
223
259
  async verifyUserAttribute(attributeName, code, accessToken) {
224
260
  const verifyUserAttributePayload = {
225
261
  AttributeName: attributeName,
226
262
  Code: code,
227
263
  AccessToken: accessToken
228
264
  };
229
- await this.cognitoRequest(verifyUserAttributePayload, CognitoServiceTarget.VerifyUserAttribute);
265
+ await cognitoRequest(verifyUserAttributePayload, CognitoServiceTarget.VerifyUserAttribute, this.cognitoEndpoint);
230
266
  }
231
267
  /**
232
268
  * Sign out the user and remove the current user session.
233
269
  *
234
- * @throws {CognitoException}
270
+ * @throws {RevokeTokenException}
235
271
  */
236
272
  async signOut(refreshToken) {
237
273
  const revokeTokenPayload = {
238
274
  Token: refreshToken,
239
275
  ClientId: this.userPoolClientId
240
276
  };
241
- await this.cognitoRequest(revokeTokenPayload, CognitoServiceTarget.RevokeToken);
277
+ await cognitoRequest(revokeTokenPayload, CognitoServiceTarget.RevokeToken, this.cognitoEndpoint);
242
278
  }
243
279
  /**
244
280
  * Request forgot password.
245
281
  * @param username Username
246
282
  *
247
- * @throws {CognitoException}
283
+ * @throws {ForgotPasswordException}
248
284
  */
249
285
  async forgotPassword(username) {
250
286
  const forgotPasswordPayload = {
251
287
  ClientId: this.userPoolClientId,
252
288
  Username: username
253
289
  };
254
- await this.cognitoRequest(forgotPasswordPayload, CognitoServiceTarget.ForgotPassword);
290
+ await cognitoRequest(forgotPasswordPayload, CognitoServiceTarget.ForgotPassword, this.cognitoEndpoint);
255
291
  }
256
292
  /**
257
293
  * Confirms the new password via the given code send via cognito triggered by @see forgotPassword .
@@ -260,7 +296,7 @@ export class CognitoClient {
260
296
  * @param newPassword New password
261
297
  * @param confirmationCode Confirmation code which the user got through E-mail
262
298
  *
263
- * @throws {CognitoException}
299
+ * @throws {ConfirmForgotPasswordException}
264
300
  */
265
301
  async confirmForgotPassword(username, newPassword, confirmationCode) {
266
302
  const confirmForgotPasswordPayload = {
@@ -269,18 +305,20 @@ export class CognitoClient {
269
305
  ConfirmationCode: confirmationCode,
270
306
  Password: newPassword
271
307
  };
272
- await this.cognitoRequest(confirmForgotPasswordPayload, CognitoServiceTarget.ConfirmForgotPassword);
308
+ await cognitoRequest(confirmForgotPasswordPayload, CognitoServiceTarget.ConfirmForgotPassword, this.cognitoEndpoint);
273
309
  }
274
310
  /**
275
311
  * Triggers cognito to resend the confirmation code
276
312
  * @param username Username
313
+ *
314
+ * @throws {ResendConfirmationCodeException}
277
315
  */
278
316
  async resendConfirmationCode(username) {
279
317
  const resendConfirmationCodePayLoad = {
280
318
  ClientId: this.userPoolClientId,
281
319
  Username: username
282
320
  };
283
- await this.cognitoRequest(resendConfirmationCodePayLoad, CognitoServiceTarget.ResendConfirmationCode);
321
+ await cognitoRequest(resendConfirmationCodePayLoad, CognitoServiceTarget.ResendConfirmationCode, this.cognitoEndpoint);
284
322
  }
285
323
  /**
286
324
  * Returns a link to Cognito`s Hosted UI for OAuth2 authentication.