@vardario/cognito-client 1.0.0 → 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.
@@ -134,7 +134,6 @@ export interface AuthenticationResult {
134
134
  AccessToken: string;
135
135
  ExpiresIn: number;
136
136
  IdToken: string;
137
- TokenType: string;
138
137
  RefreshToken: string;
139
138
  }
140
139
  export interface AuthenticationResponse {
@@ -150,6 +149,8 @@ export interface ChallengeResponse {
150
149
  USER_ID_FOR_SRP: string;
151
150
  };
152
151
  }
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,8 +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
- private static authResultToSession;
165
164
  /**
166
165
  *
167
166
  * Performs user authentication with username and password through ALLOW_USER_SRP_AUTH .
@@ -169,7 +168,8 @@ export declare class CognitoClient {
169
168
  *
170
169
  * @param username Username
171
170
  * @param password Password
172
- * @throws {CognitoException}
171
+ *
172
+ * @throws {InitiateAuthException}
173
173
  */
174
174
  authenticateUserSrp(username: string, password: string): Promise<Session>;
175
175
  /**
@@ -179,7 +179,7 @@ export declare class CognitoClient {
179
179
  *
180
180
  * @param username Username
181
181
  * @param password Password
182
- * @throws {CognitoException}
182
+ * @throws {InitiateAuthException}
183
183
  */
184
184
  authenticateUser(username: string, password: string): Promise<Session>;
185
185
  /**
@@ -187,7 +187,7 @@ export declare class CognitoClient {
187
187
  *
188
188
  * @param refreshToken
189
189
  * @returns @see Session
190
- * @throws {CognitoError}
190
+ * @throws {InitiateAuthException}
191
191
  */
192
192
  refreshSession(refreshToken: string): Promise<Session>;
193
193
  /**
@@ -195,7 +195,7 @@ export declare class CognitoClient {
195
195
  * @param username Username
196
196
  * @param password Password
197
197
  *
198
- * @throws {CognitoException}
198
+ * @throws {SignUpException}
199
199
  */
200
200
  signUp(username: string, password: string, userAttributes?: UserAttribute[]): Promise<{
201
201
  id: string;
@@ -207,7 +207,7 @@ export declare class CognitoClient {
207
207
  * @param username Username
208
208
  * @param code Confirmation code the user gets through the registration E-Mail
209
209
  *
210
- * @throws {CognitoException}
210
+ * @throws {ConfirmSignUpException}
211
211
  */
212
212
  confirmSignUp(username: string, code: string): Promise<void>;
213
213
  /**
@@ -215,22 +215,39 @@ export declare class CognitoClient {
215
215
  * @param currentPassword Current user password.
216
216
  * @param newPassword New user password.
217
217
  *
218
- * @throws {CognitoException}
218
+ * @throws {ChangePasswordException}
219
219
  */
220
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
+ */
221
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
+ */
222
239
  verifyUserAttribute(attributeName: string, code: string, accessToken: string): Promise<void>;
223
240
  /**
224
241
  * Sign out the user and remove the current user session.
225
242
  *
226
- * @throws {CognitoException}
243
+ * @throws {RevokeTokenException}
227
244
  */
228
245
  signOut(refreshToken: string): Promise<void>;
229
246
  /**
230
247
  * Request forgot password.
231
248
  * @param username Username
232
249
  *
233
- * @throws {CognitoException}
250
+ * @throws {ForgotPasswordException}
234
251
  */
235
252
  forgotPassword(username: string): Promise<void>;
236
253
  /**
@@ -240,12 +257,14 @@ export declare class CognitoClient {
240
257
  * @param newPassword New password
241
258
  * @param confirmationCode Confirmation code which the user got through E-mail
242
259
  *
243
- * @throws {CognitoException}
260
+ * @throws {ConfirmForgotPasswordException}
244
261
  */
245
262
  confirmForgotPassword(username: string, newPassword: string, confirmationCode: string): Promise<void>;
246
263
  /**
247
264
  * Triggers cognito to resend the confirmation code
248
265
  * @param username Username
266
+ *
267
+ * @throws {ResendConfirmationCodeException}
249
268
  */
250
269
  resendConfirmationCode(username: string): Promise<void>;
251
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.
@@ -33,6 +33,48 @@ export var CognitoIdentityProvider;
33
33
  CognitoIdentityProvider["Amazon"] = "LoginWithAmazon";
34
34
  CognitoIdentityProvider["Apple"] = "SignInWithApple";
35
35
  })(CognitoIdentityProvider || (CognitoIdentityProvider = {}));
36
+ export function authResultToSession(authenticationResult) {
37
+ return {
38
+ accessToken: authenticationResult.AccessToken,
39
+ idToken: authenticationResult.IdToken,
40
+ expiresIn: new Date().getTime() + authenticationResult.ExpiresIn * 1000,
41
+ refreshToken: authenticationResult.RefreshToken
42
+ };
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
+ }
36
78
  /**
37
79
  * Lightweight AWS Cogito client without any AWS SDK dependencies.
38
80
  */
@@ -52,30 +94,6 @@ export class CognitoClient {
52
94
  accessToken
53
95
  };
54
96
  }
55
- async cognitoRequest(body, serviceTarget) {
56
- const cognitoResponse = await fetch(this.cognitoEndpoint, {
57
- headers: {
58
- 'x-amz-target': `AWSCognitoIdentityProviderService.${serviceTarget}`,
59
- 'content-type': 'application/x-amz-json-1.1'
60
- },
61
- method: 'POST',
62
- body: JSON.stringify(body)
63
- });
64
- if (cognitoResponse.status < 200 || cognitoResponse.status > 299) {
65
- const errorMessage = cognitoResponse.headers.get('X-Amzn-ErrorMessage') ?? 'Unknown';
66
- const cognitoException = cognitoResponse.headers.get('X-Amzn-ErrorType') ?? CognitoException.Unknown;
67
- throw new CognitoError(errorMessage, cognitoException);
68
- }
69
- return cognitoResponse.json();
70
- }
71
- static authResultToSession(authenticationResult) {
72
- return {
73
- accessToken: authenticationResult.AccessToken,
74
- idToken: authenticationResult.IdToken,
75
- expiresIn: new Date().getMilliseconds() / 1000 + authenticationResult.ExpiresIn,
76
- refreshToken: authenticationResult.RefreshToken
77
- };
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,8 +133,8 @@ export class CognitoClient {
114
133
  },
115
134
  ClientMetadata: {}
116
135
  };
117
- const { AuthenticationResult } = await this.cognitoRequest(respondToAuthChallengePayload, CognitoServiceTarget.RespondToAuthChallenge);
118
- return CognitoClient.authResultToSession(AuthenticationResult);
136
+ const { AuthenticationResult } = await cognitoRequest(respondToAuthChallengePayload, CognitoServiceTarget.RespondToAuthChallenge, this.cognitoEndpoint);
137
+ return authResultToSession(AuthenticationResult);
119
138
  }
120
139
  /**
121
140
  *
@@ -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,8 +155,8 @@ export class CognitoClient {
136
155
  },
137
156
  ClientMetadata: {}
138
157
  };
139
- const { AuthenticationResult } = (await this.cognitoRequest(initiateAuthPayload, CognitoServiceTarget.InitiateAuth));
140
- const session = CognitoClient.authResultToSession(AuthenticationResult);
158
+ const { AuthenticationResult } = (await cognitoRequest(initiateAuthPayload, CognitoServiceTarget.InitiateAuth, this.cognitoEndpoint));
159
+ const session = authResultToSession(AuthenticationResult);
141
160
  return session;
142
161
  }
143
162
  /**
@@ -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,18 +175,18 @@ 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
  }
163
- return CognitoClient.authResultToSession(AuthenticationResult);
182
+ return authResultToSession(AuthenticationResult);
164
183
  }
165
184
  /**
166
185
  *
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.
@@ -352,16 +390,15 @@ export class CognitoClient {
352
390
  },
353
391
  body: urlParams.toString()
354
392
  });
355
- const { access_token, refresh_token, id_token, expires_in, token_type, error } = await response.json();
393
+ const { access_token, refresh_token, id_token, expires_in, error } = await response.json();
356
394
  if (error) {
357
395
  throw new Error(error);
358
396
  }
359
- const session = CognitoClient.authResultToSession({
397
+ const session = authResultToSession({
360
398
  AccessToken: access_token,
361
399
  RefreshToken: refresh_token,
362
400
  IdToken: id_token,
363
- ExpiresIn: expires_in,
364
- TokenType: token_type
401
+ ExpiresIn: expires_in
365
402
  });
366
403
  return session;
367
404
  }