@vardario/cognito-client 5.3.0 → 6.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/lib/browser.js CHANGED
@@ -644,6 +644,28 @@ function publicKeyCredentialToJSON(cred) {
644
644
  type: cred.type
645
645
  });
646
646
  }
647
+ function credentialCreateOptionsToPublicKey(credentialCreateOptions) {
648
+ credentialCreateOptions.challenge = base64UrlToUint8Array(credentialCreateOptions.challenge);
649
+ credentialCreateOptions.user.id = base64UrlToUint8Array(credentialCreateOptions.user.id);
650
+ credentialCreateOptions.excludeCredentials = (credentialCreateOptions.excludeCredentials || []).map(
651
+ (excludeCred) => ({
652
+ ...excludeCred,
653
+ id: base64UrlToUint8Array(excludeCred.id)
654
+ })
655
+ );
656
+ return credentialCreateOptions;
657
+ }
658
+ function createCredentialFromInitWebAuthResponse(reposne) {
659
+ const credentialRequestOptions = JSON.parse(reposne.ChallengeParameters.CREDENTIAL_REQUEST_OPTIONS);
660
+ credentialRequestOptions.challenge = base64UrlToUint8Array(credentialRequestOptions.challenge);
661
+ credentialRequestOptions.allowCredentials = (credentialRequestOptions.allowCredentials || []).map(
662
+ (allowCred) => ({
663
+ ...allowCred,
664
+ id: base64UrlToUint8Array(allowCred.id)
665
+ })
666
+ );
667
+ return credentialRequestOptions;
668
+ }
647
669
  var N = BigInt(
648
670
  "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
649
671
  );
@@ -809,12 +831,6 @@ var IdentityProvider = {
809
831
  Facebook: "Facebook",
810
832
  Apple: "SignInWithApple"
811
833
  };
812
- function adaptExpiresIn(auth) {
813
- return {
814
- ...auth,
815
- ExpiresIn: (/* @__PURE__ */ new Date()).getTime() + auth.ExpiresIn * 1e3
816
- };
817
- }
818
834
  async function cognitoRequest(body, serviceTarget, cognitoEndpoint) {
819
835
  const cognitoResponse = await fetch(cognitoEndpoint, {
820
836
  headers: {
@@ -881,17 +897,17 @@ async function cognitoRequest(body, serviceTarget, cognitoEndpoint) {
881
897
  }
882
898
  var CognitoClient = class {
883
899
  cognitoEndpoint;
900
+ cognitoDomain;
884
901
  cognitoPoolName;
885
902
  userPoolClientId;
886
- oAuth;
887
903
  clientSecret;
888
- constructor({ userPoolId, userPoolClientId, endpoint, oAuth2: oAuth, clientSecret }) {
904
+ constructor({ userPoolId, userPoolClientId, endpoint, clientSecret, cognitoDomain }) {
889
905
  const [cognitoPoolRegion, cognitoPoolName] = userPoolId.split("_");
890
906
  this.cognitoEndpoint = (endpoint || `https://cognito-idp.${cognitoPoolRegion}.amazonaws.com`).replace(/\/$/, "");
891
907
  this.cognitoPoolName = cognitoPoolName;
892
908
  this.userPoolClientId = userPoolClientId;
893
- this.oAuth = oAuth;
894
909
  this.clientSecret = clientSecret;
910
+ this.cognitoDomain = cognitoDomain;
895
911
  }
896
912
  static getDecodedTokenFromSession(auth) {
897
913
  const { payload: idToken } = decodeJwt(auth.IdToken);
@@ -902,17 +918,18 @@ var CognitoClient = class {
902
918
  };
903
919
  }
904
920
  async initiateAuth(request) {
905
- const cognitoResponse = await cognitoRequest(
906
- {
907
- ...request,
908
- ClientId: this.userPoolClientId
909
- },
910
- "InitiateAuth" /* InitiateAuth */,
911
- this.cognitoEndpoint
912
- );
913
- if (cognitoResponse.AuthenticationResult) {
914
- cognitoResponse.AuthenticationResult = adaptExpiresIn(cognitoResponse.AuthenticationResult);
921
+ const _request = {
922
+ ...request,
923
+ ClientId: this.userPoolClientId
924
+ };
925
+ if (this.clientSecret && request.AuthParameters.USERNAME) {
926
+ _request.AuthParameters.SECRET_HASH = await calculateSecretHash(
927
+ this.clientSecret,
928
+ this.userPoolClientId,
929
+ request.AuthParameters.USERNAME
930
+ );
915
931
  }
932
+ const cognitoResponse = await cognitoRequest(_request, "InitiateAuth" /* InitiateAuth */, this.cognitoEndpoint);
916
933
  return cognitoResponse;
917
934
  }
918
935
  /**
@@ -932,8 +949,7 @@ var CognitoClient = class {
932
949
  AuthFlow: "USER_SRP_AUTH",
933
950
  AuthParameters: {
934
951
  USERNAME: username,
935
- SRP_A: A.toString(16),
936
- SECRET_HASH: this.clientSecret && await calculateSecretHash(this.clientSecret, this.userPoolClientId, username)
952
+ SRP_A: A.toString(16)
937
953
  },
938
954
  ClientMetadata: {}
939
955
  });
@@ -964,20 +980,10 @@ var CognitoClient = class {
964
980
  PASSWORD_CLAIM_SECRET_BLOCK: initUserSrpAuthResponse.ChallengeParameters.SECRET_BLOCK,
965
981
  PASSWORD_CLAIM_SIGNATURE: signature,
966
982
  USERNAME: initUserSrpAuthResponse.ChallengeParameters.USER_ID_FOR_SRP,
967
- TIMESTAMP: timeStamp,
968
- SECRET_HASH: this.clientSecret && await calculateSecretHash(
969
- this.clientSecret,
970
- this.userPoolClientId,
971
- initUserSrpAuthResponse.ChallengeParameters.USER_ID_FOR_SRP
972
- )
983
+ TIMESTAMP: timeStamp
973
984
  },
974
985
  ClientMetadata: {}
975
986
  });
976
- if (passwordAuthChallengeResponse.AuthenticationResult) {
977
- passwordAuthChallengeResponse.AuthenticationResult = adaptExpiresIn(
978
- passwordAuthChallengeResponse.AuthenticationResult
979
- );
980
- }
981
987
  return passwordAuthChallengeResponse;
982
988
  }
983
989
  /**
@@ -994,8 +1000,7 @@ var CognitoClient = class {
994
1000
  AuthFlow: "USER_PASSWORD_AUTH",
995
1001
  AuthParameters: {
996
1002
  USERNAME: username,
997
- PASSWORD: password,
998
- SECRET_HASH: this.clientSecret && await calculateSecretHash(this.clientSecret, this.userPoolClientId, username)
1003
+ PASSWORD: password
999
1004
  },
1000
1005
  ClientMetadata: {}
1001
1006
  };
@@ -1016,36 +1021,24 @@ var CognitoClient = class {
1016
1021
  PREFERRED_CHALLENGE: "WEB_AUTHN"
1017
1022
  }
1018
1023
  };
1019
- const authResponse = await this.initiateAuth(webAuthnPayload);
1020
- if (authResponse.ChallengeName !== "WEB_AUTHN") {
1024
+ const initWebAuthnReponse = await this.initiateAuth(webAuthnPayload);
1025
+ if (initWebAuthnReponse.ChallengeName !== "WEB_AUTHN") {
1021
1026
  throw new InitAuthError(
1022
- "Authentication failed, expected WEB_AUTHN challenge but received: " + authResponse.ChallengeName,
1027
+ "Authentication failed, expected WEB_AUTHN challenge but received: " + initWebAuthnReponse.ChallengeName,
1023
1028
  "InternalErrorException" /* InternalErrorException */
1024
1029
  );
1025
1030
  }
1026
- const credentialRequestOptions = JSON.parse(authResponse.ChallengeParameters.CREDENTIAL_REQUEST_OPTIONS);
1027
- credentialRequestOptions.challenge = base64UrlToUint8Array(credentialRequestOptions.challenge);
1028
- credentialRequestOptions.allowCredentials = (credentialRequestOptions.allowCredentials || []).map(
1029
- (allowCred) => ({
1030
- ...allowCred,
1031
- id: base64UrlToUint8Array(allowCred.id)
1032
- })
1033
- );
1034
1031
  const credentials = await navigator.credentials.get({
1035
- publicKey: credentialRequestOptions
1032
+ publicKey: createCredentialFromInitWebAuthResponse(initWebAuthnReponse)
1036
1033
  });
1037
1034
  const challengeResponse = await this.respondToAuthChallenge({
1038
1035
  ChallengeName: "WEB_AUTHN",
1039
1036
  ChallengeResponses: {
1040
1037
  USERNAME: username,
1041
- CREDENTIAL: JSON.stringify(publicKeyCredentialToJSON(credentials)),
1042
- SECRET_HASH: this.clientSecret && await calculateSecretHash(this.clientSecret, this.userPoolClientId, username)
1038
+ CREDENTIAL: JSON.stringify(publicKeyCredentialToJSON(credentials))
1043
1039
  },
1044
- Session: authResponse.Session
1040
+ Session: initWebAuthnReponse.Session
1045
1041
  });
1046
- if (challengeResponse.AuthenticationResult) {
1047
- challengeResponse.AuthenticationResult = adaptExpiresIn(challengeResponse.AuthenticationResult);
1048
- }
1049
1042
  return challengeResponse;
1050
1043
  }
1051
1044
  /**
@@ -1061,14 +1054,14 @@ var CognitoClient = class {
1061
1054
  AccessToken: accessToken
1062
1055
  });
1063
1056
  const credentials = await navigator.credentials.create({
1064
- publicKey: CredentialCreationOptions
1057
+ publicKey: credentialCreateOptionsToPublicKey(CredentialCreationOptions)
1065
1058
  });
1066
1059
  if (!(credentials instanceof PublicKeyCredential)) {
1067
1060
  throw new Error("Invalid credentials returned from WebAuthn API");
1068
1061
  }
1069
1062
  await this.completeWebAuthnRegistration({
1070
1063
  AccessToken: accessToken,
1071
- Credential: credentials
1064
+ Credential: publicKeyCredentialToJSON(credentials)
1072
1065
  });
1073
1066
  }
1074
1067
  /**
@@ -1202,7 +1195,7 @@ var CognitoClient = class {
1202
1195
  * @returns
1203
1196
  */
1204
1197
  async respondToAuthChallenge(params) {
1205
- if (this.clientSecret && !params.ChallengeResponses.SECRET_HASH) {
1198
+ if (this.clientSecret) {
1206
1199
  params.ChallengeResponses.SECRET_HASH = await calculateSecretHash(
1207
1200
  this.clientSecret,
1208
1201
  this.userPoolClientId,
@@ -1337,30 +1330,19 @@ var CognitoClient = class {
1337
1330
  await cognitoRequest(resendConfirmationCodeRequest, "ResendConfirmationCode" /* ResendConfirmationCode */, this.cognitoEndpoint);
1338
1331
  }
1339
1332
  async startWebAuthnRegistration(request) {
1340
- const response = await cognitoRequest(request, "StartWebAuthnRegistration" /* StartWebAuthnRegistration */, this.cognitoEndpoint);
1341
- response.CredentialCreationOptions.challenge = base64UrlToUint8Array(
1342
- response.CredentialCreationOptions.challenge
1343
- );
1344
- response.CredentialCreationOptions.user.id = base64UrlToUint8Array(
1345
- response.CredentialCreationOptions.user.id
1346
- );
1347
- response.CredentialCreationOptions.excludeCredentials = (response.CredentialCreationOptions.excludeCredentials || []).map((excludeCred) => ({
1348
- ...excludeCred,
1349
- id: base64UrlToUint8Array(excludeCred.id)
1350
- }));
1351
- return response;
1333
+ return cognitoRequest(request, "StartWebAuthnRegistration" /* StartWebAuthnRegistration */, this.cognitoEndpoint);
1352
1334
  }
1353
1335
  /**
1354
1336
  * Completes registration of a passkey authenticator for the currently signed-in user.
1355
1337
  * @param request Request to complete WebAuthn registration.
1356
1338
  * @param request.AccessToken Access token of the current user.
1357
- * @param request.Credential The credential object returned by the WebAuthn API.
1339
+ * @param request.Credential The credential object returned by the WebAuthn API. You have to use publicKeyCredentialToJSON to convert the credential to a JSON object before sending it to Cognito.
1358
1340
  */
1359
1341
  async completeWebAuthnRegistration(request) {
1360
1342
  await cognitoRequest(
1361
1343
  {
1362
1344
  AccessToken: request.AccessToken,
1363
- Credential: publicKeyCredentialToJSON(request.Credential)
1345
+ Credential: request.Credential
1364
1346
  },
1365
1347
  "CompleteWebAuthnRegistration" /* CompleteWebAuthnRegistration */,
1366
1348
  this.cognitoEndpoint
@@ -1398,24 +1380,25 @@ var CognitoClient = class {
1398
1380
  *
1399
1381
  * @throws {Error}
1400
1382
  */
1401
- async generateOAuthSignInUrl(identityProvider) {
1402
- if (this.oAuth === void 0) {
1403
- throw Error("You have to define oAuth options to use generateFederatedSignUrl");
1404
- }
1383
+ async generateOAuthSignInUrl({
1384
+ identityProvider,
1385
+ redirectUri,
1386
+ scope
1387
+ }) {
1405
1388
  const state = (await randomBytes(32)).toString("hex");
1406
1389
  const pkce = (await randomBytes(128)).toString("hex");
1407
1390
  const code_challenge = uint8ArrayToBase64String(await digest("SHA-256", uint8ArrayFromString(pkce))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1408
1391
  const queryParams = new URLSearchParams();
1409
- queryParams.append("redirect_uri", this.oAuth.redirectUrl);
1410
- queryParams.append("response_type", this.oAuth.responseType);
1392
+ queryParams.append("redirect_uri", redirectUri);
1393
+ queryParams.append("response_type", "code");
1411
1394
  queryParams.append("client_id", this.userPoolClientId);
1412
1395
  identityProvider && queryParams.append("identity_provider", identityProvider);
1413
- queryParams.append("scope", this.oAuth.scopes.join(" "));
1396
+ queryParams.append("scope", scope.join(" "));
1414
1397
  queryParams.append("state", state);
1415
1398
  queryParams.append("code_challenge", code_challenge);
1416
1399
  queryParams.append("code_challenge_method", "S256");
1417
1400
  return {
1418
- url: `${this.oAuth.cognitoDomain}/oauth2/authorize?${queryParams.toString()}`,
1401
+ url: `${this.cognitoDomain}/oauth2/authorize?${queryParams.toString()}`,
1419
1402
  state,
1420
1403
  pkce
1421
1404
  };
@@ -1431,15 +1414,20 @@ var CognitoClient = class {
1431
1414
  *
1432
1415
  * @throws {Error}
1433
1416
  */
1434
- async handleCodeFlow(returnUrl, pkce, state) {
1435
- if (this.oAuth === void 0) {
1436
- throw Error("You have to define oAuth options to use handleCodeFlow");
1437
- }
1417
+ async handleCodeFlow({
1418
+ pkce,
1419
+ redirectUri,
1420
+ returnUrl,
1421
+ state
1422
+ }) {
1438
1423
  const url = new URL(returnUrl);
1439
1424
  const code = url.searchParams.get("code");
1440
1425
  if (code === null) {
1441
1426
  throw Error("code parameter is missing from return url.");
1442
1427
  }
1428
+ if (!this.cognitoDomain) {
1429
+ throw Error("Cognito domain is not set. Please set cognitoDomain in the CognitoClient constructor.");
1430
+ }
1443
1431
  if (url.searchParams.get("state") !== state) {
1444
1432
  throw Error("State parameter does not match.");
1445
1433
  }
@@ -1447,26 +1435,31 @@ var CognitoClient = class {
1447
1435
  urlParams.append("grant_type", "authorization_code");
1448
1436
  urlParams.append("code", code);
1449
1437
  urlParams.append("client_id", this.userPoolClientId);
1450
- urlParams.append("redirect_uri", this.oAuth.redirectUrl);
1438
+ urlParams.append("redirect_uri", redirectUri);
1451
1439
  urlParams.append("code_verifier", pkce);
1452
- const tokenEndpoint = `${this.oAuth.cognitoDomain}/oauth2/token`;
1440
+ const tokenEndpoint = `${this.cognitoDomain}/oauth2/token`;
1441
+ const headers = {
1442
+ "Content-Type": "application/x-www-form-urlencoded"
1443
+ };
1444
+ if (this.clientSecret) {
1445
+ const basicAuth = btoa(`${this.userPoolClientId}:${this.clientSecret}`);
1446
+ headers["Authorization"] = `Basic ${basicAuth}`;
1447
+ }
1453
1448
  const response = await fetch(tokenEndpoint, {
1454
1449
  method: "POST",
1455
- headers: {
1456
- "Content-Type": "application/x-www-form-urlencoded"
1457
- },
1450
+ headers,
1458
1451
  body: urlParams.toString()
1459
1452
  });
1460
1453
  const { access_token, refresh_token, id_token, expires_in, error } = await response.json();
1461
1454
  if (error) {
1462
1455
  throw new Error(error);
1463
1456
  }
1464
- return adaptExpiresIn({
1457
+ return {
1465
1458
  AccessToken: access_token,
1466
1459
  RefreshToken: refresh_token,
1467
1460
  IdToken: id_token,
1468
1461
  ExpiresIn: expires_in
1469
- });
1462
+ };
1470
1463
  }
1471
1464
  /**
1472
1465
  * Invalidates the identity, access, and refresh tokens that Amazon Cognito issued to a user. Call this operation when your user signs out of your app. This results in the following behavior.
@@ -1529,7 +1522,6 @@ export {
1529
1522
  VerifySoftwareTokenException,
1530
1523
  VerifyUserAttributeError,
1531
1524
  VerifyUserAttributeException,
1532
- adaptExpiresIn,
1533
1525
  base64UrlToUint8Array,
1534
1526
  calculateHKDF,
1535
1527
  calculateS,
@@ -1537,6 +1529,8 @@ export {
1537
1529
  calculateSignature,
1538
1530
  calculateU,
1539
1531
  cognitoRequest,
1532
+ createCredentialFromInitWebAuthResponse,
1533
+ credentialCreateOptionsToPublicKey,
1540
1534
  decodeJwt,
1541
1535
  digest,
1542
1536
  formatTimestamp,
@@ -181,28 +181,6 @@ export interface ResendConfirmationCodeRequest extends CognitoBaseRequest {
181
181
  Username: string;
182
182
  SecretHash?: string;
183
183
  }
184
- /**
185
- * Cognito related OAuth props.
186
- */
187
- export interface OAuth2Props {
188
- /**
189
- * Cognito domain for OAuth2 token endpoints.
190
- */
191
- cognitoDomain: string;
192
- /**
193
- * Requested OAuth scopes
194
- * @example ['email', 'openid']
195
- */
196
- scopes: string[];
197
- /**
198
- * Redirect URL after a successful OAuth2 authentication.
199
- */
200
- redirectUrl: string;
201
- /**
202
- * Response type.
203
- */
204
- responseType: 'code';
205
- }
206
184
  export interface CognitoClientProps {
207
185
  /**
208
186
  * Cognito User Pool ID
@@ -213,15 +191,15 @@ export interface CognitoClientProps {
213
191
  * Cognito User Pool Client ID
214
192
  */
215
193
  userPoolClientId: string;
194
+ /**
195
+ * Cognito Domain. Required for OAuth2 flows.
196
+ */
197
+ cognitoDomain?: string;
216
198
  /**
217
199
  * Optional Cognito endpoint. Useful for local testing.
218
200
  * If not defined the endpoint will be determined by @see userPoolId .
219
201
  */
220
202
  endpoint?: string;
221
- /**
222
- * Cognito OAuth related options. See @see OAuthProps .
223
- */
224
- oAuth2?: OAuth2Props;
225
203
  /**
226
204
  * Optional Cognito User Pool Client Secret.
227
205
  */
@@ -455,7 +433,7 @@ export interface StartWebAuthnRegistrationResponse {
455
433
  }
456
434
  export interface CompleteWebAuthnRegistrationRequest {
457
435
  AccessToken: string;
458
- Credential: PublicKeyCredential;
436
+ Credential: any;
459
437
  }
460
438
  export interface DeleteWebAuthnCredentialRequest {
461
439
  AccessToken: string;
@@ -468,7 +446,7 @@ export interface ListWebAuthnCredentialsRequest {
468
446
  }
469
447
  export interface WebAuthnCredential {
470
448
  AuthenticatorTransports: string[];
471
- CreatedAt: string;
449
+ CreatedAt: number;
472
450
  CredentialId: string;
473
451
  FriendlyCredentialName: string;
474
452
  RelyingPartyId: string;
@@ -548,24 +526,17 @@ type CognitoRequestMap = {
548
526
  [ServiceTarget.DeleteWebAuthnCredential]: DeleteWebAuthnCredentialRequest;
549
527
  [ServiceTarget.ListWebAuthnCredentials]: ListWebAuthnCredentialsRequest;
550
528
  };
551
- export declare function adaptExpiresIn(auth: AuthenticationResult): {
552
- ExpiresIn: number;
553
- AccessToken: string;
554
- IdToken: string;
555
- RefreshToken: string;
556
- NewDeviceMetadata?: NewDeviceMetadata | undefined;
557
- };
558
529
  export declare function cognitoRequest<T extends ServiceTarget>(body: CognitoRequestMap[T], serviceTarget: T, cognitoEndpoint: string): Promise<CognitoResponseMap[T]>;
559
530
  /**
560
531
  * Lightweight AWS Cogito client without any AWS SDK dependencies.
561
532
  */
562
533
  export declare class CognitoClient {
563
534
  private readonly cognitoEndpoint;
535
+ private readonly cognitoDomain?;
564
536
  private readonly cognitoPoolName;
565
537
  private readonly userPoolClientId;
566
- private readonly oAuth?;
567
538
  private readonly clientSecret?;
568
- constructor({ userPoolId, userPoolClientId, endpoint, oAuth2: oAuth, clientSecret }: CognitoClientProps);
539
+ constructor({ userPoolId, userPoolClientId, endpoint, clientSecret, cognitoDomain }: CognitoClientProps);
569
540
  static getDecodedTokenFromSession(auth: AuthenticationResult): DecodedTokens;
570
541
  initiateAuth(request: InitiateAuthRequest): Promise<InitiateAuthResponse>;
571
542
  /**
@@ -755,7 +726,7 @@ export declare class CognitoClient {
755
726
  * Completes registration of a passkey authenticator for the currently signed-in user.
756
727
  * @param request Request to complete WebAuthn registration.
757
728
  * @param request.AccessToken Access token of the current user.
758
- * @param request.Credential The credential object returned by the WebAuthn API.
729
+ * @param request.Credential The credential object returned by the WebAuthn API. You have to use publicKeyCredentialToJSON to convert the credential to a JSON object before sending it to Cognito.
759
730
  */
760
731
  completeWebAuthnRegistration(request: CompleteWebAuthnRegistrationRequest): Promise<void>;
761
732
  /**
@@ -785,7 +756,11 @@ export declare class CognitoClient {
785
756
  *
786
757
  * @throws {Error}
787
758
  */
788
- generateOAuthSignInUrl(identityProvider?: string): Promise<{
759
+ generateOAuthSignInUrl({ identityProvider, redirectUri, scope }: {
760
+ identityProvider?: string;
761
+ redirectUri: string;
762
+ scope: string[];
763
+ }): Promise<{
789
764
  url: string;
790
765
  state: string;
791
766
  pkce: string;
@@ -801,7 +776,12 @@ export declare class CognitoClient {
801
776
  *
802
777
  * @throws {Error}
803
778
  */
804
- handleCodeFlow(returnUrl: string, pkce: string, state: string): Promise<AuthenticationResult>;
779
+ handleCodeFlow({ pkce, redirectUri, returnUrl, state }: {
780
+ returnUrl: string;
781
+ redirectUri: string;
782
+ pkce: string;
783
+ state: string;
784
+ }): Promise<AuthenticationResult>;
805
785
  /**
806
786
  * Invalidates the identity, access, and refresh tokens that Amazon Cognito issued to a user. Call this operation when your user signs out of your app. This results in the following behavior.
807
787
  * @param accessToken Access token of the current user.
@@ -1,5 +1,5 @@
1
1
  import { ChangePasswordError, ConfirmForgotPasswordError, ConfirmSignUpError, ForgotPasswordError, GlobalSignOutError, InitAuthError, ResendConfirmationCodeError, RespondToAuthChallengeError, RevokeTokenError, SignUpError, UpdateUserAttributesError, VerifyUserAttributeError, InitiateAuthException, COMMON_EXCEPTIONS, CommonError, VerifySoftwareTokenError, AssociateSoftwareTokenError, SetUserMFAPreferenceError, ListDevicesError, GetUserError } from './error.js';
2
- import { base64UrlToUint8Array, calculateSecretHash, calculateSignature, calculateU, decodeJwt, digest, generateA, generateSmallA, getPasswordAuthenticationKey, publicKeyCredentialToJSON, randomBytes, uint8ArrayFromString, uint8ArrayToBase64String } from './utils.js';
2
+ import { calculateSecretHash, calculateSignature, calculateU, createCredentialFromInitWebAuthResponse, credentialCreateOptionsToPublicKey, decodeJwt, digest, generateA, generateSmallA, getPasswordAuthenticationKey, publicKeyCredentialToJSON, randomBytes, uint8ArrayFromString, uint8ArrayToBase64String } from './utils.js';
3
3
  /**
4
4
  * List of used and supported Cognito API calls.
5
5
  * @see https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_Operations.html for more details
@@ -37,13 +37,6 @@ export const IdentityProvider = {
37
37
  Facebook: 'Facebook',
38
38
  Apple: 'SignInWithApple'
39
39
  };
40
- export function adaptExpiresIn(auth) {
41
- // Cognito returns expiresIn in seconds, but we want it in milliseconds from now
42
- return {
43
- ...auth,
44
- ExpiresIn: new Date().getTime() + auth.ExpiresIn * 1000
45
- };
46
- }
47
40
  export async function cognitoRequest(body, serviceTarget, cognitoEndpoint) {
48
41
  const cognitoResponse = await fetch(cognitoEndpoint, {
49
42
  headers: {
@@ -121,17 +114,17 @@ export async function cognitoRequest(body, serviceTarget, cognitoEndpoint) {
121
114
  */
122
115
  export class CognitoClient {
123
116
  cognitoEndpoint;
117
+ cognitoDomain;
124
118
  cognitoPoolName;
125
119
  userPoolClientId;
126
- oAuth;
127
120
  clientSecret;
128
- constructor({ userPoolId, userPoolClientId, endpoint, oAuth2: oAuth, clientSecret }) {
121
+ constructor({ userPoolId, userPoolClientId, endpoint, clientSecret, cognitoDomain }) {
129
122
  const [cognitoPoolRegion, cognitoPoolName] = userPoolId.split('_');
130
123
  this.cognitoEndpoint = (endpoint || `https://cognito-idp.${cognitoPoolRegion}.amazonaws.com`).replace(/\/$/, '');
131
124
  this.cognitoPoolName = cognitoPoolName;
132
125
  this.userPoolClientId = userPoolClientId;
133
- this.oAuth = oAuth;
134
126
  this.clientSecret = clientSecret;
127
+ this.cognitoDomain = cognitoDomain;
135
128
  }
136
129
  static getDecodedTokenFromSession(auth) {
137
130
  const { payload: idToken } = decodeJwt(auth.IdToken);
@@ -142,13 +135,14 @@ export class CognitoClient {
142
135
  };
143
136
  }
144
137
  async initiateAuth(request) {
145
- const cognitoResponse = await cognitoRequest({
138
+ const _request = {
146
139
  ...request,
147
140
  ClientId: this.userPoolClientId
148
- }, ServiceTarget.InitiateAuth, this.cognitoEndpoint);
149
- if (cognitoResponse.AuthenticationResult) {
150
- cognitoResponse.AuthenticationResult = adaptExpiresIn(cognitoResponse.AuthenticationResult);
141
+ };
142
+ if (this.clientSecret && request.AuthParameters.USERNAME) {
143
+ _request.AuthParameters.SECRET_HASH = await calculateSecretHash(this.clientSecret, this.userPoolClientId, request.AuthParameters.USERNAME);
151
144
  }
145
+ const cognitoResponse = await cognitoRequest(_request, ServiceTarget.InitiateAuth, this.cognitoEndpoint);
152
146
  return cognitoResponse;
153
147
  }
154
148
  /**
@@ -168,8 +162,7 @@ export class CognitoClient {
168
162
  AuthFlow: 'USER_SRP_AUTH',
169
163
  AuthParameters: {
170
164
  USERNAME: username,
171
- SRP_A: A.toString(16),
172
- SECRET_HASH: this.clientSecret && (await calculateSecretHash(this.clientSecret, this.userPoolClientId, username))
165
+ SRP_A: A.toString(16)
173
166
  },
174
167
  ClientMetadata: {}
175
168
  });
@@ -187,15 +180,10 @@ export class CognitoClient {
187
180
  PASSWORD_CLAIM_SECRET_BLOCK: initUserSrpAuthResponse.ChallengeParameters.SECRET_BLOCK,
188
181
  PASSWORD_CLAIM_SIGNATURE: signature,
189
182
  USERNAME: initUserSrpAuthResponse.ChallengeParameters.USER_ID_FOR_SRP,
190
- TIMESTAMP: timeStamp,
191
- SECRET_HASH: this.clientSecret &&
192
- (await calculateSecretHash(this.clientSecret, this.userPoolClientId, initUserSrpAuthResponse.ChallengeParameters.USER_ID_FOR_SRP))
183
+ TIMESTAMP: timeStamp
193
184
  },
194
185
  ClientMetadata: {}
195
186
  });
196
- if (passwordAuthChallengeResponse.AuthenticationResult) {
197
- passwordAuthChallengeResponse.AuthenticationResult = adaptExpiresIn(passwordAuthChallengeResponse.AuthenticationResult);
198
- }
199
187
  return passwordAuthChallengeResponse;
200
188
  }
201
189
  /**
@@ -212,8 +200,7 @@ export class CognitoClient {
212
200
  AuthFlow: 'USER_PASSWORD_AUTH',
213
201
  AuthParameters: {
214
202
  USERNAME: username,
215
- PASSWORD: password,
216
- SECRET_HASH: this.clientSecret && (await calculateSecretHash(this.clientSecret, this.userPoolClientId, username))
203
+ PASSWORD: password
217
204
  },
218
205
  ClientMetadata: {}
219
206
  };
@@ -234,31 +221,21 @@ export class CognitoClient {
234
221
  PREFERRED_CHALLENGE: 'WEB_AUTHN'
235
222
  }
236
223
  };
237
- const authResponse = await this.initiateAuth(webAuthnPayload);
238
- if (authResponse.ChallengeName !== 'WEB_AUTHN') {
239
- throw new InitAuthError('Authentication failed, expected WEB_AUTHN challenge but received: ' + authResponse.ChallengeName, InitiateAuthException.InternalErrorException);
224
+ const initWebAuthnReponse = await this.initiateAuth(webAuthnPayload);
225
+ if (initWebAuthnReponse.ChallengeName !== 'WEB_AUTHN') {
226
+ throw new InitAuthError('Authentication failed, expected WEB_AUTHN challenge but received: ' + initWebAuthnReponse.ChallengeName, InitiateAuthException.InternalErrorException);
240
227
  }
241
- const credentialRequestOptions = JSON.parse(authResponse.ChallengeParameters.CREDENTIAL_REQUEST_OPTIONS);
242
- credentialRequestOptions.challenge = base64UrlToUint8Array(credentialRequestOptions.challenge);
243
- credentialRequestOptions.allowCredentials = (credentialRequestOptions.allowCredentials || []).map((allowCred) => ({
244
- ...allowCred,
245
- id: base64UrlToUint8Array(allowCred.id)
246
- }));
247
228
  const credentials = await navigator.credentials.get({
248
- publicKey: credentialRequestOptions
229
+ publicKey: createCredentialFromInitWebAuthResponse(initWebAuthnReponse)
249
230
  });
250
231
  const challengeResponse = await this.respondToAuthChallenge({
251
232
  ChallengeName: 'WEB_AUTHN',
252
233
  ChallengeResponses: {
253
234
  USERNAME: username,
254
- CREDENTIAL: JSON.stringify(publicKeyCredentialToJSON(credentials)),
255
- SECRET_HASH: this.clientSecret && (await calculateSecretHash(this.clientSecret, this.userPoolClientId, username))
235
+ CREDENTIAL: JSON.stringify(publicKeyCredentialToJSON(credentials))
256
236
  },
257
- Session: authResponse.Session
237
+ Session: initWebAuthnReponse.Session
258
238
  });
259
- if (challengeResponse.AuthenticationResult) {
260
- challengeResponse.AuthenticationResult = adaptExpiresIn(challengeResponse.AuthenticationResult);
261
- }
262
239
  return challengeResponse;
263
240
  }
264
241
  /**
@@ -274,14 +251,14 @@ export class CognitoClient {
274
251
  AccessToken: accessToken
275
252
  });
276
253
  const credentials = await navigator.credentials.create({
277
- publicKey: CredentialCreationOptions
254
+ publicKey: credentialCreateOptionsToPublicKey(CredentialCreationOptions)
278
255
  });
279
256
  if (!(credentials instanceof PublicKeyCredential)) {
280
257
  throw new Error('Invalid credentials returned from WebAuthn API');
281
258
  }
282
259
  await this.completeWebAuthnRegistration({
283
260
  AccessToken: accessToken,
284
- Credential: credentials
261
+ Credential: publicKeyCredentialToJSON(credentials)
285
262
  });
286
263
  }
287
264
  /**
@@ -414,7 +391,7 @@ export class CognitoClient {
414
391
  * @returns
415
392
  */
416
393
  async respondToAuthChallenge(params) {
417
- if (this.clientSecret && !params.ChallengeResponses.SECRET_HASH) {
394
+ if (this.clientSecret) {
418
395
  params.ChallengeResponses.SECRET_HASH = await calculateSecretHash(this.clientSecret, this.userPoolClientId, params.ChallengeResponses.USERNAME);
419
396
  }
420
397
  return cognitoRequest({
@@ -541,25 +518,18 @@ export class CognitoClient {
541
518
  await cognitoRequest(resendConfirmationCodeRequest, ServiceTarget.ResendConfirmationCode, this.cognitoEndpoint);
542
519
  }
543
520
  async startWebAuthnRegistration(request) {
544
- const response = await cognitoRequest(request, ServiceTarget.StartWebAuthnRegistration, this.cognitoEndpoint);
545
- response.CredentialCreationOptions.challenge = base64UrlToUint8Array(response.CredentialCreationOptions.challenge);
546
- response.CredentialCreationOptions.user.id = base64UrlToUint8Array(response.CredentialCreationOptions.user.id);
547
- response.CredentialCreationOptions.excludeCredentials = (response.CredentialCreationOptions.excludeCredentials || []).map((excludeCred) => ({
548
- ...excludeCred,
549
- id: base64UrlToUint8Array(excludeCred.id)
550
- }));
551
- return response;
521
+ return cognitoRequest(request, ServiceTarget.StartWebAuthnRegistration, this.cognitoEndpoint);
552
522
  }
553
523
  /**
554
524
  * Completes registration of a passkey authenticator for the currently signed-in user.
555
525
  * @param request Request to complete WebAuthn registration.
556
526
  * @param request.AccessToken Access token of the current user.
557
- * @param request.Credential The credential object returned by the WebAuthn API.
527
+ * @param request.Credential The credential object returned by the WebAuthn API. You have to use publicKeyCredentialToJSON to convert the credential to a JSON object before sending it to Cognito.
558
528
  */
559
529
  async completeWebAuthnRegistration(request) {
560
530
  await cognitoRequest({
561
531
  AccessToken: request.AccessToken,
562
- Credential: publicKeyCredentialToJSON(request.Credential)
532
+ Credential: request.Credential
563
533
  }, ServiceTarget.CompleteWebAuthnRegistration, this.cognitoEndpoint);
564
534
  }
565
535
  /**
@@ -594,10 +564,7 @@ export class CognitoClient {
594
564
  *
595
565
  * @throws {Error}
596
566
  */
597
- async generateOAuthSignInUrl(identityProvider) {
598
- if (this.oAuth === undefined) {
599
- throw Error('You have to define oAuth options to use generateFederatedSignUrl');
600
- }
567
+ async generateOAuthSignInUrl({ identityProvider, redirectUri, scope }) {
601
568
  const state = (await randomBytes(32)).toString('hex');
602
569
  const pkce = (await randomBytes(128)).toString('hex');
603
570
  const code_challenge = uint8ArrayToBase64String(await digest('SHA-256', uint8ArrayFromString(pkce)))
@@ -605,16 +572,16 @@ export class CognitoClient {
605
572
  .replace(/\//g, '_')
606
573
  .replace(/=+$/, '');
607
574
  const queryParams = new URLSearchParams();
608
- queryParams.append('redirect_uri', this.oAuth.redirectUrl);
609
- queryParams.append('response_type', this.oAuth.responseType);
575
+ queryParams.append('redirect_uri', redirectUri);
576
+ queryParams.append('response_type', 'code');
610
577
  queryParams.append('client_id', this.userPoolClientId);
611
578
  identityProvider && queryParams.append('identity_provider', identityProvider);
612
- queryParams.append('scope', this.oAuth.scopes.join(' '));
579
+ queryParams.append('scope', scope.join(' '));
613
580
  queryParams.append('state', state);
614
581
  queryParams.append('code_challenge', code_challenge);
615
582
  queryParams.append('code_challenge_method', 'S256');
616
583
  return {
617
- url: `${this.oAuth.cognitoDomain}/oauth2/authorize?${queryParams.toString()}`,
584
+ url: `${this.cognitoDomain}/oauth2/authorize?${queryParams.toString()}`,
618
585
  state,
619
586
  pkce
620
587
  };
@@ -630,15 +597,15 @@ export class CognitoClient {
630
597
  *
631
598
  * @throws {Error}
632
599
  */
633
- async handleCodeFlow(returnUrl, pkce, state) {
634
- if (this.oAuth === undefined) {
635
- throw Error('You have to define oAuth options to use handleCodeFlow');
636
- }
600
+ async handleCodeFlow({ pkce, redirectUri, returnUrl, state }) {
637
601
  const url = new URL(returnUrl);
638
602
  const code = url.searchParams.get('code');
639
603
  if (code === null) {
640
604
  throw Error('code parameter is missing from return url.');
641
605
  }
606
+ if (!this.cognitoDomain) {
607
+ throw Error('Cognito domain is not set. Please set cognitoDomain in the CognitoClient constructor.');
608
+ }
642
609
  if (url.searchParams.get('state') !== state) {
643
610
  throw Error('State parameter does not match.');
644
611
  }
@@ -646,26 +613,31 @@ export class CognitoClient {
646
613
  urlParams.append('grant_type', 'authorization_code');
647
614
  urlParams.append('code', code);
648
615
  urlParams.append('client_id', this.userPoolClientId);
649
- urlParams.append('redirect_uri', this.oAuth.redirectUrl);
616
+ urlParams.append('redirect_uri', redirectUri);
650
617
  urlParams.append('code_verifier', pkce);
651
- const tokenEndpoint = `${this.oAuth.cognitoDomain}/oauth2/token`;
618
+ const tokenEndpoint = `${this.cognitoDomain}/oauth2/token`;
619
+ const headers = {
620
+ 'Content-Type': 'application/x-www-form-urlencoded'
621
+ };
622
+ if (this.clientSecret) {
623
+ const basicAuth = btoa(`${this.userPoolClientId}:${this.clientSecret}`);
624
+ headers['Authorization'] = `Basic ${basicAuth}`;
625
+ }
652
626
  const response = await fetch(tokenEndpoint, {
653
627
  method: 'POST',
654
- headers: {
655
- 'Content-Type': 'application/x-www-form-urlencoded'
656
- },
628
+ headers,
657
629
  body: urlParams.toString()
658
630
  });
659
631
  const { access_token, refresh_token, id_token, expires_in, error } = await response.json();
660
632
  if (error) {
661
633
  throw new Error(error);
662
634
  }
663
- return adaptExpiresIn({
635
+ return {
664
636
  AccessToken: access_token,
665
637
  RefreshToken: refresh_token,
666
638
  IdToken: id_token,
667
639
  ExpiresIn: expires_in
668
- });
640
+ };
669
641
  }
670
642
  /**
671
643
  * Invalidates the identity, access, and refresh tokens that Amazon Cognito issued to a user. Call this operation when your user signs out of your app. This results in the following behavior.
package/lib/utils.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  /// <reference types="node" resolution-mode="require"/>
3
+ import { InitiateAuthWebAuthResponse } from './cognito-client.js';
3
4
  export declare function uint8ArrayFromHexString(hexString: string): Uint8Array;
4
5
  export declare function uint8ArrayFromString(str: string): Uint8Array;
5
6
  export declare function uint8ArrayFromBase64String(str: string): Uint8Array;
@@ -8,6 +9,8 @@ export declare function uint8ArrayToBase64String(bytes: Uint8Array | ArrayBuffer
8
9
  export declare function uint8ArrayToBase64UrlString(bytes: Uint8Array | ArrayBuffer | undefined): string | undefined;
9
10
  export declare function base64UrlToUint8Array(base64: string): Uint8Array;
10
11
  export declare function publicKeyCredentialToJSON(cred: any): any;
12
+ export declare function credentialCreateOptionsToPublicKey(credentialCreateOptions: any): PublicKeyCredentialCreationOptions;
13
+ export declare function createCredentialFromInitWebAuthResponse(reposne: InitiateAuthWebAuthResponse): PublicKeyCredentialCreationOptions;
11
14
  export declare function padHex(bigInt: bigint): string;
12
15
  export declare function hashHexString(str: string): Promise<string>;
13
16
  export declare function hashBuffer(buffer: Uint8Array): Promise<string>;
package/lib/utils.js CHANGED
@@ -63,6 +63,24 @@ export function publicKeyCredentialToJSON(cred) {
63
63
  type: cred.type
64
64
  });
65
65
  }
66
+ export function credentialCreateOptionsToPublicKey(credentialCreateOptions) {
67
+ credentialCreateOptions.challenge = base64UrlToUint8Array(credentialCreateOptions.challenge);
68
+ credentialCreateOptions.user.id = base64UrlToUint8Array(credentialCreateOptions.user.id);
69
+ credentialCreateOptions.excludeCredentials = (credentialCreateOptions.excludeCredentials || []).map((excludeCred) => ({
70
+ ...excludeCred,
71
+ id: base64UrlToUint8Array(excludeCred.id)
72
+ }));
73
+ return credentialCreateOptions;
74
+ }
75
+ export function createCredentialFromInitWebAuthResponse(reposne) {
76
+ const credentialRequestOptions = JSON.parse(reposne.ChallengeParameters.CREDENTIAL_REQUEST_OPTIONS);
77
+ credentialRequestOptions.challenge = base64UrlToUint8Array(credentialRequestOptions.challenge);
78
+ credentialRequestOptions.allowCredentials = (credentialRequestOptions.allowCredentials || []).map((allowCred) => ({
79
+ ...allowCred,
80
+ id: base64UrlToUint8Array(allowCred.id)
81
+ }));
82
+ return credentialRequestOptions;
83
+ }
66
84
  const N = BigInt('0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1' +
67
85
  '29024E088A67CC74020BBEA63B139B22514A08798E3404DD' +
68
86
  'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vardario/cognito-client",
3
- "version": "5.3.0",
3
+ "version": "6.0.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "author": "Sahin Vardar",