@prove-identity/prove-auth 2.8.2 → 2.9.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.
Files changed (32) hide show
  1. package/README.md +8 -9
  2. package/build/bundle/release/prove-auth.js +1 -1
  3. package/build/lib/index.d.ts +2 -2
  4. package/build/lib/proveauth/authenticator-builder.d.ts +3 -0
  5. package/build/lib/proveauth/authenticator-builder.js +7 -3
  6. package/build/lib/proveauth/internal/auth-request.d.ts +1 -0
  7. package/build/lib/proveauth/internal/auth-response.d.ts +5 -1
  8. package/build/lib/proveauth/internal/auth-session.d.ts +3 -1
  9. package/build/lib/proveauth/internal/auth-session.js +50 -9
  10. package/build/lib/proveauth/internal/auth-status-actions.js +3 -3
  11. package/build/lib/proveauth/internal/device-passive-register-step.d.ts +1 -0
  12. package/build/lib/proveauth/internal/device-passive-register-step.js +55 -39
  13. package/build/lib/proveauth/internal/device-passive-silent-step.js +4 -0
  14. package/build/lib/proveauth/internal/device-passive-step.d.ts +12 -4
  15. package/build/lib/proveauth/internal/device-passive-step.js +172 -52
  16. package/build/lib/proveauth/internal/device-passive-stepup-step.d.ts +2 -1
  17. package/build/lib/proveauth/internal/device-passive-stepup-step.js +25 -3
  18. package/build/lib/proveauth/internal/device-passive-verify-step.d.ts +3 -2
  19. package/build/lib/proveauth/internal/device-passive-verify-step.js +29 -11
  20. package/build/lib/proveauth/internal/fido-options-error.d.ts +30 -0
  21. package/build/lib/proveauth/internal/fido-options-error.js +161 -0
  22. package/build/lib/proveauth/internal/main-authenticator.js +1 -1
  23. package/build/lib/proveauth/internal/mobile-instantlink-step.js +36 -29
  24. package/build/lib/proveauth/internal/mobile-otp-step.d.ts +3 -0
  25. package/build/lib/proveauth/internal/mobile-otp-step.js +115 -67
  26. package/build/lib/proveauth/internal/scan-message-step.js +1 -1
  27. package/build/lib/proveauth/internal/settings.js +1 -0
  28. package/build/lib/proveauth/internal/web-socket-close-reasons.d.ts +15 -0
  29. package/build/lib/proveauth/internal/web-socket-close-reasons.js +19 -0
  30. package/build/lib/proveauth/version.d.ts +1 -1
  31. package/build/lib/proveauth/version.js +1 -1
  32. package/package.json +1 -1
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const logger_1 = require("../common/logger");
4
4
  const device_passive_step_1 = require("./device-passive-step");
5
5
  class DevicePassiveStepupStep extends device_passive_step_1.DevicePassiveActions {
6
- constructor(getDisplayName) {
7
- super(getDisplayName);
6
+ constructor(getDisplayName, handler) {
7
+ super(getDisplayName, handler);
8
8
  this.name = DevicePassiveStepupStep.NAME;
9
9
  this.log = logger_1.LoggerFactory.getLogger('device-passive-stepup-step');
10
10
  }
@@ -18,7 +18,29 @@ class DevicePassiveStepupStep extends device_passive_step_1.DevicePassiveActions
18
18
  if (session.settings.fidoPasskeyRegistered) {
19
19
  return Promise.reject(new Error('FIDO2 Passkey is already registered'));
20
20
  }
21
- return this.register(session);
21
+ return new Promise((resolve, reject) => {
22
+ session
23
+ .getFingerprintData()
24
+ .then((signal) => {
25
+ const signals = {
26
+ fingerprint: signal,
27
+ };
28
+ session.embedDarwiniumSignal(signals);
29
+ this.register(session, signals).then(resolve).catch(reject);
30
+ })
31
+ .catch((error) => {
32
+ const errorMsg = `Unexpected error happened during Fingerprint data collection: ${error.message}`;
33
+ this.log.warn(errorMsg);
34
+ this.log.warn(error);
35
+ const signals = {
36
+ fingerprint: {
37
+ error: errorMsg,
38
+ },
39
+ };
40
+ session.embedDarwiniumSignal(signals);
41
+ this.register(session, signals).then(resolve).catch(reject);
42
+ });
43
+ });
22
44
  }
23
45
  }
24
46
  DevicePassiveStepupStep.NAME = 'device/passive/stepup';
@@ -1,10 +1,11 @@
1
1
  import AuthSession from './auth-session';
2
2
  import AuthStep from './auth-step';
3
- import { Signals } from './auth-request';
3
+ import { Logger } from '../common/logger';
4
4
  export default class DevicePassiveVerifyStep implements AuthStep {
5
5
  static readonly NAME = "device/passive/verify";
6
6
  private readonly log;
7
7
  readonly name = "device/passive/verify";
8
8
  execute(session: AuthSession): Promise<string>;
9
- runFidoVerifyFinish(session: AuthSession, signals?: Signals): Promise<string>;
9
+ static runFidoVerify(log: Logger, session: AuthSession): Promise<string>;
10
+ private static makeFidoVerifyFinishRequest;
10
11
  }
@@ -12,24 +12,33 @@ class DevicePassiveVerifyStep {
12
12
  this.name = DevicePassiveVerifyStep.NAME;
13
13
  }
14
14
  execute(session) {
15
+ return new Promise((resolve, reject) => {
16
+ DevicePassiveVerifyStep.runFidoVerify(this.log, session).then(resolve).catch(reject);
17
+ });
18
+ }
19
+ static runFidoVerify(log, session) {
15
20
  return new Promise((resolve, reject) => {
16
21
  session
17
22
  .getFingerprintData()
18
23
  .then((signal) => {
19
- let signals = { fingerprint: signal };
24
+ const signals = { fingerprint: signal };
20
25
  session.embedDarwiniumSignal(signals);
21
- this.runFidoVerifyFinish(session, signals).then(resolve).catch(reject);
26
+ DevicePassiveVerifyStep.makeFidoVerifyFinishRequest(log, session, signals)
27
+ .then(resolve)
28
+ .catch(reject);
22
29
  })
23
30
  .catch((error) => {
24
- var errorMsg = `Unexpected error happened during Fingerprint data collection ${error.toString}`;
25
- this.log.warn(errorMsg);
26
- let signals = { fingerprint: { error: errorMsg } };
31
+ const errorMsg = `Unexpected error happened during Fingerprint data collection ${error.toString}`;
32
+ log.warn(errorMsg);
33
+ const signals = { fingerprint: { error: errorMsg } };
27
34
  session.embedDarwiniumSignal(signals);
28
- this.runFidoVerifyFinish(session).then(resolve).catch(reject);
35
+ DevicePassiveVerifyStep.makeFidoVerifyFinishRequest(log, session, signals)
36
+ .then(resolve)
37
+ .catch(reject);
29
38
  });
30
39
  });
31
40
  }
32
- runFidoVerifyFinish(session, signals) {
41
+ static makeFidoVerifyFinishRequest(log, session, signals) {
33
42
  return new Promise((resolve, reject) => {
34
43
  const credential = session.credential;
35
44
  const assertion = credential.response;
@@ -52,16 +61,25 @@ class DevicePassiveVerifyStep {
52
61
  })
53
62
  .then((response) => {
54
63
  if (response.error) {
55
- reject(new auth_error_1.default(response.error.message, response.error.code, response.next));
64
+ reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
56
65
  }
57
66
  else {
58
67
  const data = response.data;
59
- if (data && data.scanMessage) {
60
- session.authMessage = data.scanMessage;
68
+ if (data) {
69
+ if (data.deviceId) {
70
+ session.settings.deviceId = data.deviceId;
71
+ }
72
+ if (data.passkey) {
73
+ session.settings.fidoPasskeyRegistered = true;
74
+ }
75
+ if (data.scanMessage) {
76
+ session.authMessage = data.scanMessage;
77
+ }
61
78
  }
62
79
  else {
63
- this.log.warn('No data was received in the response');
80
+ log.warn('No data was received in the response');
64
81
  }
82
+ session.settings.fidoPasskeyRegistered = true;
65
83
  resolve(response.next);
66
84
  }
67
85
  })
@@ -0,0 +1,30 @@
1
+ import Platform from './platform';
2
+ export declare class FidoOptionsError extends Error {
3
+ static readonly MISSING_PUBLIC_KEY_PROPERTY = "options missing publicKey property";
4
+ static readonly ABORT_SIGNAL = "Authentication was sent an abort signal";
5
+ static readonly INVALID_STATE_ERROR = "The authenticator was already registered";
6
+ static readonly UNKNOWN_ERROR = "Unknown error: the authenticator was unable to process the predefined options, or unable to generate a new credential";
7
+ static readonly SECURITY_ERROR_FOUND = "Security error found";
8
+ static readonly INVALID_RP_ID = "The rp.id is not valid for the current domain";
9
+ static readonly CONSTRAINT_ERROR = "Discoverable credentials is required but found no matching supported authenticator";
10
+ static readonly USER_VERIFICATION_NOT_POSSILE = "User verification is required during automatic registration but this could not be performed";
11
+ static readonly NO_MATCHING_AUTHENTICATOR = "User verification is required but found no matching supported authenticator";
12
+ static readonly INVALID_CRED_PARAMS = "No entry in pubKeyCredParams having the type of public-key";
13
+ static readonly NO_MATCHING_AUTHENTICATOR_FOR_PARAMS_ALGO = "No available authenticator supported any of the specified pubKeyCredParams algorithms";
14
+ static readonly INVALID_USER_ID_LENGTH = "User ID has invalid length";
15
+ constructor({ message, cause, name }: {
16
+ message: string;
17
+ cause: Error;
18
+ name?: string;
19
+ });
20
+ static identifyAuthenticationError({ error, options, platform, }: {
21
+ error: Error;
22
+ options: CredentialRequestOptions;
23
+ platform: Platform;
24
+ }): FidoOptionsError | Error;
25
+ static identifyRegistrationError({ error, options, platform, }: {
26
+ error: Error;
27
+ options: CredentialCreationOptions;
28
+ platform: Platform;
29
+ }): FidoOptionsError | Error;
30
+ }
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FidoOptionsError = void 0;
4
+ class FidoOptionsError extends Error {
5
+ constructor({ message, cause, name }) {
6
+ super(message, { cause });
7
+ this.name = name !== null && name !== void 0 ? name : cause.name;
8
+ }
9
+ static identifyAuthenticationError({ error, options, platform, }) {
10
+ const { publicKey } = options;
11
+ if (!publicKey) {
12
+ return new FidoOptionsError({
13
+ message: FidoOptionsError.MISSING_PUBLIC_KEY_PROPERTY,
14
+ cause: new Error(FidoOptionsError.MISSING_PUBLIC_KEY_PROPERTY),
15
+ });
16
+ }
17
+ if (error.name === 'AbortError') {
18
+ if (options.signal instanceof AbortSignal) {
19
+ return new FidoOptionsError({
20
+ message: FidoOptionsError.ABORT_SIGNAL,
21
+ cause: error,
22
+ });
23
+ }
24
+ }
25
+ else if (error.name === 'NotAllowedError') {
26
+ return new FidoOptionsError({
27
+ message: error.message,
28
+ cause: error,
29
+ });
30
+ }
31
+ else if (error.name === 'SecurityError') {
32
+ const currentDomain = platform.getOrigin();
33
+ if (publicKey.rpId !== currentDomain) {
34
+ return new FidoOptionsError({
35
+ message: `${FidoOptionsError.INVALID_RP_ID}: ${publicKey.rpId}`,
36
+ cause: error,
37
+ });
38
+ }
39
+ else {
40
+ return new FidoOptionsError({
41
+ message: `${FidoOptionsError.SECURITY_ERROR_FOUND}: ${error.message}`,
42
+ cause: error,
43
+ });
44
+ }
45
+ }
46
+ else if (error.name === 'UnknownError') {
47
+ return new FidoOptionsError({
48
+ message: FidoOptionsError.UNKNOWN_ERROR,
49
+ cause: error,
50
+ });
51
+ }
52
+ return error;
53
+ }
54
+ static identifyRegistrationError({ error, options, platform, }) {
55
+ var _a, _b, _c;
56
+ const { publicKey } = options;
57
+ if (!publicKey) {
58
+ return new FidoOptionsError({
59
+ message: FidoOptionsError.MISSING_PUBLIC_KEY_PROPERTY,
60
+ cause: new Error(FidoOptionsError.MISSING_PUBLIC_KEY_PROPERTY),
61
+ });
62
+ }
63
+ if (error.name === 'InvalidStateError') {
64
+ return new FidoOptionsError({
65
+ message: FidoOptionsError.INVALID_STATE_ERROR,
66
+ cause: error,
67
+ });
68
+ }
69
+ else if (error.name === 'AbortError') {
70
+ if (options.signal instanceof AbortSignal) {
71
+ return new FidoOptionsError({
72
+ message: this.ABORT_SIGNAL,
73
+ cause: error,
74
+ });
75
+ }
76
+ }
77
+ else if (error.name === 'ConstraintError') {
78
+ if (((_a = publicKey.authenticatorSelection) === null || _a === void 0 ? void 0 : _a.requireResidentKey) === true) {
79
+ return new FidoOptionsError({
80
+ message: this.CONSTRAINT_ERROR,
81
+ cause: error,
82
+ });
83
+ }
84
+ else if (options.mediation === 'conditional' &&
85
+ ((_b = publicKey.authenticatorSelection) === null || _b === void 0 ? void 0 : _b.userVerification) === 'required') {
86
+ return new FidoOptionsError({
87
+ message: this.USER_VERIFICATION_NOT_POSSILE,
88
+ cause: error,
89
+ });
90
+ }
91
+ else if (((_c = publicKey.authenticatorSelection) === null || _c === void 0 ? void 0 : _c.userVerification) === 'required') {
92
+ return new FidoOptionsError({
93
+ message: this.NO_MATCHING_AUTHENTICATOR,
94
+ cause: error,
95
+ });
96
+ }
97
+ }
98
+ else if (error.name === 'NotAllowedError') {
99
+ return new FidoOptionsError({
100
+ message: error.message,
101
+ cause: error,
102
+ });
103
+ }
104
+ else if (error.name === 'NotSupportedError') {
105
+ const validPubKeyCredParams = publicKey.pubKeyCredParams.filter((param) => param.type === 'public-key');
106
+ if (validPubKeyCredParams.length === 0) {
107
+ return new FidoOptionsError({
108
+ message: this.INVALID_CRED_PARAMS,
109
+ cause: error,
110
+ });
111
+ }
112
+ return new FidoOptionsError({
113
+ message: FidoOptionsError.NO_MATCHING_AUTHENTICATOR_FOR_PARAMS_ALGO,
114
+ cause: error,
115
+ });
116
+ }
117
+ else if (error.name === 'SecurityError') {
118
+ const currentDomain = platform.getOrigin();
119
+ if (publicKey.rp.id !== currentDomain) {
120
+ return new FidoOptionsError({
121
+ message: `${FidoOptionsError.INVALID_RP_ID}: ${publicKey.rp.id}`,
122
+ cause: error,
123
+ });
124
+ }
125
+ else {
126
+ return new FidoOptionsError({
127
+ message: `${FidoOptionsError.SECURITY_ERROR_FOUND}: ${error.message}`,
128
+ cause: error,
129
+ });
130
+ }
131
+ }
132
+ else if (error.name === 'TypeError') {
133
+ if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {
134
+ return new FidoOptionsError({
135
+ message: FidoOptionsError.INVALID_USER_ID_LENGTH,
136
+ cause: error,
137
+ });
138
+ }
139
+ }
140
+ else if (error.name === 'UnknownError') {
141
+ return new FidoOptionsError({
142
+ message: FidoOptionsError.UNKNOWN_ERROR,
143
+ cause: error,
144
+ });
145
+ }
146
+ return error;
147
+ }
148
+ }
149
+ FidoOptionsError.MISSING_PUBLIC_KEY_PROPERTY = 'options missing publicKey property';
150
+ FidoOptionsError.ABORT_SIGNAL = 'Authentication was sent an abort signal';
151
+ FidoOptionsError.INVALID_STATE_ERROR = 'The authenticator was already registered';
152
+ FidoOptionsError.UNKNOWN_ERROR = 'Unknown error: the authenticator was unable to process the predefined options, or unable to generate a new credential';
153
+ FidoOptionsError.SECURITY_ERROR_FOUND = 'Security error found';
154
+ FidoOptionsError.INVALID_RP_ID = 'The rp.id is not valid for the current domain';
155
+ FidoOptionsError.CONSTRAINT_ERROR = 'Discoverable credentials is required but found no matching supported authenticator';
156
+ FidoOptionsError.USER_VERIFICATION_NOT_POSSILE = 'User verification is required during automatic registration but this could not be performed';
157
+ FidoOptionsError.NO_MATCHING_AUTHENTICATOR = 'User verification is required but found no matching supported authenticator';
158
+ FidoOptionsError.INVALID_CRED_PARAMS = 'No entry in pubKeyCredParams having the type of public-key';
159
+ FidoOptionsError.NO_MATCHING_AUTHENTICATOR_FOR_PARAMS_ALGO = 'No available authenticator supported any of the specified pubKeyCredParams algorithms';
160
+ FidoOptionsError.INVALID_USER_ID_LENGTH = 'User ID has invalid length';
161
+ exports.FidoOptionsError = FidoOptionsError;
@@ -110,7 +110,7 @@ class MainAuthenticator {
110
110
  })
111
111
  .then((response) => {
112
112
  if (response.error) {
113
- reject(new auth_error_1.default(response.error.message, response.error.code, response.next));
113
+ reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
114
114
  }
115
115
  else {
116
116
  resolve();
@@ -7,6 +7,7 @@ const logger_1 = require("../common/logger");
7
7
  const phone_number_input_1 = require("./phone-number-input");
8
8
  const auth_error_1 = __importDefault(require("./auth-error"));
9
9
  const auth_status_actions_1 = require("./auth-status-actions");
10
+ const mobile_otp_step_1 = __importDefault(require("./mobile-otp-step"));
10
11
  const SIMULATED_LINK_CLICK_DELAY = 100;
11
12
  class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
12
13
  constructor(startStep, getDeviceIp) {
@@ -44,39 +45,45 @@ class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
44
45
  this.startStep
45
46
  .execute(phoneNumberNeeded, phoneValidationError)
46
47
  .then((input) => {
47
- session
48
- .fetchFromBackend('/v1/client/mobile/instantlink/start', {
49
- sourceIp: this.getDeviceIp(),
50
- mobileNumber: input === null || input === void 0 ? void 0 : input.phoneNumber,
51
- })
52
- .then((response) => {
53
- var _a, _b, _c;
54
- const authResponse = response;
55
- if (authResponse.error) {
56
- reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
57
- }
58
- else if (authResponse.data) {
59
- var errorMessage = '';
60
- if ((_a = authResponse.data) === null || _a === void 0 ? void 0 : _a.code) {
61
- errorMessage += `Error Code: ${authResponse.data.code}, `;
48
+ const inputError = mobile_otp_step_1.default.validatePhoneNumberInput(input);
49
+ if (inputError) {
50
+ reject(inputError);
51
+ }
52
+ else {
53
+ session
54
+ .fetchFromBackend('/v1/client/mobile/instantlink/start', {
55
+ sourceIp: this.getDeviceIp(),
56
+ mobileNumber: input === null || input === void 0 ? void 0 : input.phoneNumber,
57
+ })
58
+ .then((response) => {
59
+ var _a, _b, _c;
60
+ const authResponse = response;
61
+ if (authResponse.error) {
62
+ reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
62
63
  }
63
- if ((_b = authResponse.data) === null || _b === void 0 ? void 0 : _b.message) {
64
- errorMessage += `${authResponse.data.message}`;
64
+ else if (authResponse.data) {
65
+ var errorMessage = '';
66
+ if ((_a = authResponse.data) === null || _a === void 0 ? void 0 : _a.code) {
67
+ errorMessage += `Error Code: ${authResponse.data.code}, `;
68
+ }
69
+ if ((_b = authResponse.data) === null || _b === void 0 ? void 0 : _b.message) {
70
+ errorMessage += `${authResponse.data.message}`;
71
+ }
72
+ else {
73
+ errorMessage += `Error validating phone number`;
74
+ }
75
+ let phoneNumberValidationError = new phone_number_input_1.PhoneValidationError(errorMessage, (_c = authResponse.data) === null || _c === void 0 ? void 0 : _c.code);
76
+ this.log.error(`Server reports invalid phone number: ${errorMessage}`);
77
+ this.runStartStep(session, phoneNumberNeeded, phoneNumberValidationError)
78
+ .then(resolve)
79
+ .catch(reject);
65
80
  }
66
81
  else {
67
- errorMessage += `Error validating phone number`;
82
+ resolve(authResponse.next);
68
83
  }
69
- let phoneNumberValidationError = new phone_number_input_1.PhoneValidationError(errorMessage, (_c = authResponse.data) === null || _c === void 0 ? void 0 : _c.code);
70
- this.log.error(`Server reports invalid phone number: ${errorMessage}`);
71
- this.runStartStep(session, phoneNumberNeeded, phoneNumberValidationError)
72
- .then(resolve)
73
- .catch(reject);
74
- }
75
- else {
76
- resolve(authResponse.next);
77
- }
78
- })
79
- .catch(reject);
84
+ })
85
+ .catch(reject);
86
+ }
80
87
  })
81
88
  .catch(reject);
82
89
  }
@@ -1,5 +1,6 @@
1
1
  import AuthSession from './auth-session';
2
2
  import AuthStep from './auth-step';
3
+ import AuthError from './auth-error';
3
4
  import { OtpStartStep, OtpFinishStep } from '../otp';
4
5
  export default class MobileOtpStep implements AuthStep {
5
6
  static readonly NAME = "mobile/otp";
@@ -9,6 +10,8 @@ export default class MobileOtpStep implements AuthStep {
9
10
  private otpFinishStep?;
10
11
  constructor(otpStartStep?: OtpStartStep, otpFinishStep?: OtpFinishStep);
11
12
  execute(session: AuthSession): Promise<string>;
13
+ static validatePhoneNumberInput(input: any): AuthError | undefined;
12
14
  private runOtpStartStep;
15
+ static validateFinishResult(result: any): AuthError | undefined;
13
16
  private runOtpFinishStep;
14
17
  }
@@ -34,45 +34,66 @@ class MobileOtpStep {
34
34
  .catch(reject);
35
35
  });
36
36
  }
37
+ static validatePhoneNumberInput(input) {
38
+ if (input === null || input === undefined) {
39
+ return;
40
+ }
41
+ if (typeof input !== 'object') {
42
+ return new auth_error_1.default('Input must be an object');
43
+ }
44
+ if (!('phoneNumber' in input)) {
45
+ return new auth_error_1.default('phoneNumber field in the input is missing');
46
+ }
47
+ if (typeof input.phoneNumber !== 'string') {
48
+ return new auth_error_1.default('phoneNumber field in the input must be a string');
49
+ }
50
+ return;
51
+ }
37
52
  runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, phoneValidationError) {
38
53
  return new Promise((resolve, reject) => {
39
54
  otpStartStep
40
55
  .execute(phoneNumberNeeded, phoneValidationError)
41
56
  .then((input) => {
42
- session
43
- .fetchFromBackend('/v1/client/mobile/otp/start', {
44
- mobileNumber: input === null || input === void 0 ? void 0 : input.phoneNumber,
45
- })
46
- .then((response) => {
47
- const authResponse = response;
48
- if (authResponse.error) {
49
- reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
50
- }
51
- else if (authResponse.data) {
52
- let data = authResponse.data;
53
- var errorMessage = '';
54
- if (data === null || data === void 0 ? void 0 : data.code) {
55
- errorMessage += `Error Code: ${data.code}, `;
57
+ const inputError = MobileOtpStep.validatePhoneNumberInput(input);
58
+ if (inputError) {
59
+ reject(inputError);
60
+ }
61
+ else {
62
+ session
63
+ .fetchFromBackend('/v1/client/mobile/otp/start', {
64
+ mobileNumber: input === null || input === void 0 ? void 0 : input.phoneNumber,
65
+ })
66
+ .then((response) => {
67
+ const authResponse = response;
68
+ if (authResponse.error) {
69
+ reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
56
70
  }
57
- if (data === null || data === void 0 ? void 0 : data.message) {
58
- errorMessage += `${data.message}`;
71
+ else if (authResponse.data) {
72
+ let data = authResponse.data;
73
+ var errorMessage = '';
74
+ if (data === null || data === void 0 ? void 0 : data.code) {
75
+ errorMessage += `Error Code: ${data.code}, `;
76
+ }
77
+ if (data === null || data === void 0 ? void 0 : data.message) {
78
+ errorMessage += `${data.message}`;
79
+ }
80
+ else {
81
+ errorMessage += `Error validating phone number`;
82
+ }
83
+ let phoneNumberValidationError = new phone_number_input_1.PhoneValidationError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
84
+ this.log.error(`Server reports invalid phone number: ${errorMessage}`);
85
+ this.runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, phoneNumberValidationError)
86
+ .then(resolve)
87
+ .catch(reject);
59
88
  }
60
89
  else {
61
- errorMessage += `Error validating phone number`;
90
+ this.runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded)
91
+ .then(resolve)
92
+ .catch(reject);
62
93
  }
63
- let phoneNumberValidationError = new phone_number_input_1.PhoneValidationError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
64
- this.log.error(`Server reports invalid phone number: ${errorMessage}`);
65
- this.runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, phoneNumberValidationError)
66
- .then(resolve)
67
- .catch(reject);
68
- }
69
- else {
70
- this.runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded)
71
- .then(resolve)
72
- .catch(reject);
73
- }
74
- })
75
- .catch(reject);
94
+ })
95
+ .catch(reject);
96
+ }
76
97
  })
77
98
  .catch((error) => {
78
99
  const message = auth_error_1.default.extractMessage(error);
@@ -80,6 +101,27 @@ class MobileOtpStep {
80
101
  });
81
102
  });
82
103
  }
104
+ static validateFinishResult(result) {
105
+ if (result === null || result === undefined || typeof result !== 'object') {
106
+ return new auth_error_1.default('result should be a valid object');
107
+ }
108
+ else if (!('resultType' in result)) {
109
+ return new auth_error_1.default('resultType field in the result is missing');
110
+ }
111
+ else if (result.resultType === otp_1.OtpFinishResultType.OnSuccess) {
112
+ const input = result.input;
113
+ if (input === null || input === undefined || typeof input !== 'object') {
114
+ return new auth_error_1.default('input should be a valid object when resultType field is set with OnSuccess value');
115
+ }
116
+ if (!('otp' in input)) {
117
+ return new auth_error_1.default('otp field in the input is missing');
118
+ }
119
+ if (typeof input.otp !== 'string') {
120
+ return new auth_error_1.default('otp field in the input must be a string');
121
+ }
122
+ }
123
+ return;
124
+ }
83
125
  runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, otpError) {
84
126
  return new Promise((resolve, reject) => {
85
127
  otpFinishStep
@@ -87,47 +129,53 @@ class MobileOtpStep {
87
129
  .then((otpFinishResult) => {
88
130
  var _a;
89
131
  let result = otpFinishResult;
90
- switch (result.resultType) {
91
- case otp_1.OtpFinishResultType.OnResendOtp:
92
- this.runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded)
93
- .then(resolve)
94
- .catch(reject);
95
- break;
96
- case otp_1.OtpFinishResultType.OnSuccess:
97
- let input = result.input;
98
- session
99
- .fetchFromBackend('/v1/client/mobile/otp/finish', {
100
- otp: (_a = input === null || input === void 0 ? void 0 : input.otp) !== null && _a !== void 0 ? _a : '',
101
- })
102
- .then((response) => {
103
- const authResponse = response;
104
- if (authResponse.error) {
105
- reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
106
- }
107
- else if (authResponse.data) {
108
- let data = authResponse.data;
109
- var errorMessage = '';
110
- if (data === null || data === void 0 ? void 0 : data.code) {
111
- errorMessage += `Error Code: ${data.code}, `;
132
+ const resultError = MobileOtpStep.validateFinishResult(result);
133
+ if (resultError) {
134
+ reject(resultError);
135
+ }
136
+ else {
137
+ switch (result.resultType) {
138
+ case otp_1.OtpFinishResultType.OnResendOtp:
139
+ this.runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded)
140
+ .then(resolve)
141
+ .catch(reject);
142
+ break;
143
+ case otp_1.OtpFinishResultType.OnSuccess:
144
+ let input = result.input;
145
+ session
146
+ .fetchFromBackend('/v1/client/mobile/otp/finish', {
147
+ otp: (_a = input === null || input === void 0 ? void 0 : input.otp) !== null && _a !== void 0 ? _a : '',
148
+ })
149
+ .then((response) => {
150
+ const authResponse = response;
151
+ if (authResponse.error) {
152
+ reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
112
153
  }
113
- if (data === null || data === void 0 ? void 0 : data.message) {
114
- errorMessage += `${data.message}`;
154
+ else if (authResponse.data) {
155
+ let data = authResponse.data;
156
+ var errorMessage = '';
157
+ if (data === null || data === void 0 ? void 0 : data.code) {
158
+ errorMessage += `Error Code: ${data.code}, `;
159
+ }
160
+ if (data === null || data === void 0 ? void 0 : data.message) {
161
+ errorMessage += `${data.message}`;
162
+ }
163
+ else {
164
+ errorMessage += `Error validating OTP`;
165
+ }
166
+ let otpError = new otp_1.OtpError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
167
+ this.log.error(`Server reports invalid OTP: ${errorMessage}`);
168
+ this.runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, otpError)
169
+ .then(resolve)
170
+ .catch(reject);
115
171
  }
116
172
  else {
117
- errorMessage += `Error validating OTP`;
173
+ resolve(response.next);
118
174
  }
119
- let otpError = new otp_1.OtpError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
120
- this.log.error(`Server reports invalid OTP: ${errorMessage}`);
121
- this.runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, otpError)
122
- .then(resolve)
123
- .catch(reject);
124
- }
125
- else {
126
- resolve(response.next);
127
- }
128
- })
129
- .catch(reject);
130
- break;
175
+ })
176
+ .catch(reject);
177
+ break;
178
+ }
131
179
  }
132
180
  })
133
181
  .catch((error) => {