@prove-identity/prove-auth 2.13.1 → 2.15.1

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 (39) hide show
  1. package/build/bundle/release/prove-auth.js +1 -1
  2. package/build/lib/index.d.ts +3 -2
  3. package/build/lib/index.js +1 -2
  4. package/build/lib/proveauth/authenticator-builder.d.ts +5 -0
  5. package/build/lib/proveauth/authenticator-builder.js +25 -2
  6. package/build/lib/proveauth/external/@authid/web-component/authid-web-component.d.ts +3 -0
  7. package/build/lib/proveauth/external/@authid/web-component/authid-web-component.js +55 -0
  8. package/build/lib/proveauth/instantlink.d.ts +2 -6
  9. package/build/lib/proveauth/instantlink.js +1 -11
  10. package/build/lib/proveauth/internal/auth-request.d.ts +5 -3
  11. package/build/lib/proveauth/internal/auth-response.d.ts +24 -28
  12. package/build/lib/proveauth/internal/auth-session.d.ts +6 -1
  13. package/build/lib/proveauth/internal/auth-session.js +34 -7
  14. package/build/lib/proveauth/internal/auth-token-claims.d.ts +22 -3
  15. package/build/lib/proveauth/internal/device-passive-register-step.js +8 -9
  16. package/build/lib/proveauth/internal/device-passive-silent-step.js +13 -6
  17. package/build/lib/proveauth/internal/device-passive-step.js +10 -5
  18. package/build/lib/proveauth/internal/device-passive-stepup-step.js +1 -19
  19. package/build/lib/proveauth/internal/device-passive-verify-step.js +2 -18
  20. package/build/lib/proveauth/internal/main-authenticator.js +3 -0
  21. package/build/lib/proveauth/internal/mobile-instant-step.js +2 -2
  22. package/build/lib/proveauth/internal/mobile-instantlink-step.d.ts +0 -3
  23. package/build/lib/proveauth/internal/mobile-instantlink-step.js +22 -122
  24. package/build/lib/proveauth/internal/mobile-otp-step.js +3 -3
  25. package/build/lib/proveauth/internal/platform.d.ts +11 -0
  26. package/build/lib/proveauth/internal/report-error-step.js +5 -2
  27. package/build/lib/proveauth/internal/settings.d.ts +3 -0
  28. package/build/lib/proveauth/internal/settings.js +14 -0
  29. package/build/lib/proveauth/internal/user-mobileactive-step.js +1 -3
  30. package/build/lib/proveauth/internal/user-ppb-steps.d.ts +24 -0
  31. package/build/lib/proveauth/internal/user-ppb-steps.js +103 -0
  32. package/build/lib/proveauth/internal/user-present-step.js +1 -3
  33. package/build/lib/proveauth/internal/web-platform.d.ts +3 -1
  34. package/build/lib/proveauth/internal/web-platform.js +101 -0
  35. package/build/lib/proveauth/ppb.d.ts +9 -0
  36. package/build/lib/proveauth/ppb.js +2 -0
  37. package/build/lib/proveauth/version.d.ts +2 -2
  38. package/build/lib/proveauth/version.js +2 -2
  39. package/package.json +1 -1
@@ -18,25 +18,10 @@ class DevicePassiveVerifyStep {
18
18
  }
19
19
  static runFidoVerify(log, session) {
20
20
  return new Promise((resolve, reject) => {
21
- session
22
- .getFingerprintData()
23
- .then((signal) => {
24
- const signals = { fingerprint: signal };
25
- DevicePassiveVerifyStep.makeFidoVerifyFinishRequest(log, session, signals)
26
- .then(resolve)
27
- .catch(reject);
28
- })
29
- .catch((error) => {
30
- const errorMsg = `Unexpected error happened during Fingerprint data collection ${error.toString}`;
31
- log.warn(errorMsg);
32
- const signals = { fingerprint: { error: errorMsg } };
33
- DevicePassiveVerifyStep.makeFidoVerifyFinishRequest(log, session, signals)
34
- .then(resolve)
35
- .catch(reject);
36
- });
21
+ DevicePassiveVerifyStep.makeFidoVerifyFinishRequest(log, session).then(resolve).catch(reject);
37
22
  });
38
23
  }
39
- static makeFidoVerifyFinishRequest(log, session, signals) {
24
+ static makeFidoVerifyFinishRequest(log, session) {
40
25
  return new Promise((resolve, reject) => {
41
26
  const credential = session.credential;
42
27
  const assertion = credential.response;
@@ -55,7 +40,6 @@ class DevicePassiveVerifyStep {
55
40
  : undefined,
56
41
  },
57
42
  },
58
- signals: signals,
59
43
  })
60
44
  .then((response) => {
61
45
  if (response.error) {
@@ -138,6 +138,9 @@ class MainAuthenticator {
138
138
  session.lastStep = step;
139
139
  return new Promise((resolve, reject) => {
140
140
  if ([MainAuthenticator.AUTH_DONE, MainAuthenticator.AUTH_EMPTY].includes(step)) {
141
+ if (!session.settings.deviceId && session.settings.fingerPrintTimestamp) {
142
+ session.resetFptts();
143
+ }
141
144
  resolve();
142
145
  }
143
146
  else if (attempt > MainAuthenticator.MAX_ATTEMPTS) {
@@ -56,15 +56,15 @@ class MobileInstantStep {
56
56
  implementation: this.implementation,
57
57
  })
58
58
  .then((response) => {
59
- var _a;
60
59
  if (response.error) {
61
60
  this.nextBak = response.next;
62
61
  this.errorCodeBak = response.error.code;
63
62
  reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
64
63
  }
65
64
  else {
65
+ const data = response.data;
66
66
  resolve({
67
- authUrl: (_a = response.data) === null || _a === void 0 ? void 0 : _a.redirectUrl,
67
+ authUrl: data ? data.redirectUrl : undefined,
68
68
  });
69
69
  }
70
70
  })
@@ -10,10 +10,7 @@ export default class MobileInstantLinkStep extends AuthStatusActions implements
10
10
  private readonly retryStep?;
11
11
  private readonly getDeviceIp;
12
12
  constructor(startStep?: InstantLinkStartStep, retryStep?: InstantLinkRetryStep, getDeviceIp?: () => string | null);
13
- private isTestMode;
14
13
  execute(session: AuthSession): Promise<string>;
15
- private getInstantLinkError;
16
14
  private runStartStep;
17
15
  private runRetryStep;
18
- private handleTestMode;
19
16
  }
@@ -9,7 +9,6 @@ const phone_number_input_1 = require("./phone-number-input");
9
9
  const auth_error_1 = __importDefault(require("./auth-error"));
10
10
  const auth_status_actions_1 = require("./auth-status-actions");
11
11
  const mobile_otp_step_1 = __importDefault(require("./mobile-otp-step"));
12
- const SIMULATED_LINK_CLICK_DELAY = 100;
13
12
  class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
14
13
  constructor(startStep, retryStep, getDeviceIp) {
15
14
  super();
@@ -19,16 +18,8 @@ class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
19
18
  this.retryStep = retryStep;
20
19
  this.getDeviceIp = getDeviceIp !== null && getDeviceIp !== void 0 ? getDeviceIp : (() => null);
21
20
  }
22
- isTestMode(session) {
23
- var _a, _b, _c;
24
- var testMode = false;
25
- if ((_c = (_b = (_a = session.claims) === null || _a === void 0 ? void 0 : _a.auth.subs.mob) === null || _b === void 0 ? void 0 : _b.auths.inln) === null || _c === void 0 ? void 0 : _c.tme) {
26
- testMode = true;
27
- }
28
- return testMode;
29
- }
30
21
  execute(session) {
31
- this.log.trace('Executing');
22
+ this.log.debug('Executing');
32
23
  return new Promise((resolve, reject) => {
33
24
  var _a, _b, _c;
34
25
  var phoneNumberNeeded = true;
@@ -40,34 +31,6 @@ class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
40
31
  this.waitForStatus(session).then(resolve).catch(reject);
41
32
  });
42
33
  }
43
- getInstantLinkError(responseData) {
44
- const errorCode = responseData.code;
45
- var errorMessage = '';
46
- if (errorCode) {
47
- errorMessage += `Error Code: ${responseData.code}, `;
48
- }
49
- let instantLinkError;
50
- if (errorCode === 10005) {
51
- if (responseData.message) {
52
- errorMessage += `${responseData.message}`;
53
- }
54
- else {
55
- errorMessage += `Max number of retires reached.`;
56
- }
57
- instantLinkError = new instantlink_1.InstantLinkMaxRetryError(errorMessage, responseData.code);
58
- }
59
- else {
60
- if (responseData.message) {
61
- errorMessage += `${responseData.message}`;
62
- }
63
- else {
64
- errorMessage += `Error validating phone number`;
65
- }
66
- instantLinkError = new phone_number_input_1.PhoneValidationError(errorMessage, responseData.code);
67
- }
68
- this.log.error(`Server reports instant link error: ${errorMessage}`);
69
- return instantLinkError;
70
- }
71
34
  runStartStep(session, phoneNumberNeeded, instantLinkError) {
72
35
  return new Promise((resolve, reject) => {
73
36
  if (this.startStep) {
@@ -90,50 +53,30 @@ class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
90
53
  reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
91
54
  }
92
55
  else if (authResponse.data) {
93
- const errorCode = authResponse.data.code;
56
+ const data = authResponse.data;
57
+ const errorCode = data.code;
94
58
  var errorMessage = '';
95
59
  if (errorCode) {
96
- errorMessage += `Error Code: ${authResponse.data.code}, `;
60
+ errorMessage += `Error Code: ${errorCode}, `;
97
61
  }
98
- if (errorCode === 10005) {
99
- if (authResponse.data.message) {
100
- errorMessage += `${authResponse.data.message}`;
101
- }
102
- else {
103
- errorMessage += `Max number of retires reached.`;
104
- }
105
- let maxRetryError = new instantlink_1.InstantLinkMaxRetryError(errorMessage, authResponse.data.code);
106
- if (this.retryStep) {
107
- this.runRetryStep(session, maxRetryError).then(resolve).catch(reject);
108
- }
109
- else {
110
- this.log.error('Max number of retires reached but retry step is undefined.');
111
- }
62
+ if (data.message) {
63
+ errorMessage += `${data.message}`;
112
64
  }
113
65
  else {
114
- if (authResponse.data.message) {
115
- errorMessage += `${authResponse.data.message}`;
116
- }
117
- else {
118
- errorMessage += `Error validating phone number.`;
119
- }
120
- let invalidPhoneError = new phone_number_input_1.PhoneValidationError(errorMessage, authResponse.data.code);
121
- this.runStartStep(session, phoneNumberNeeded, invalidPhoneError)
122
- .then(resolve)
123
- .catch(reject);
66
+ errorMessage += `Error validating phone number.`;
124
67
  }
68
+ let invalidPhoneError = new phone_number_input_1.PhoneValidationError(errorMessage, data.code);
69
+ this.runStartStep(session, phoneNumberNeeded, invalidPhoneError)
70
+ .then(resolve)
71
+ .catch(reject);
125
72
  }
126
73
  else {
127
- this.handleTestMode(session)
128
- .then(() => {
129
- if (this.retryStep) {
130
- this.runRetryStep(session).then(resolve).catch(reject);
131
- }
132
- else {
133
- resolve(authResponse.next);
134
- }
135
- })
136
- .catch(reject);
74
+ if (this.retryStep) {
75
+ this.runRetryStep(session).then(resolve).catch(reject);
76
+ }
77
+ else {
78
+ resolve(authResponse.next);
79
+ }
137
80
  }
138
81
  })
139
82
  .catch(reject);
@@ -146,11 +89,11 @@ class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
146
89
  }
147
90
  });
148
91
  }
149
- runRetryStep(session, instantLinkError) {
92
+ runRetryStep(session) {
150
93
  return new Promise((resolve, reject) => {
151
94
  if (this.retryStep) {
152
95
  this.retryStep
153
- .execute(instantLinkError)
96
+ .execute()
154
97
  .then((resultType) => {
155
98
  if (resultType === instantlink_1.InstantLinkResultType.OnResend) {
156
99
  session
@@ -163,26 +106,8 @@ class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
163
106
  if (authResponse.error) {
164
107
  reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
165
108
  }
166
- else if (authResponse.data) {
167
- const errorCode = authResponse.data.code;
168
- var errorMessage = '';
169
- if (errorCode) {
170
- errorMessage += `Error Code: ${authResponse.data.code}, `;
171
- }
172
- if (authResponse.data.message) {
173
- errorMessage += `${authResponse.data.message}`;
174
- }
175
- else {
176
- errorMessage += `Max number of retires reached.`;
177
- }
178
- let maxRetryError = new instantlink_1.InstantLinkMaxRetryError(errorMessage, authResponse.data.code);
179
- this.runRetryStep(session, maxRetryError).then(resolve).catch(reject);
180
- }
181
109
  else {
182
- this.handleTestMode(session)
183
- .then(() => this.runRetryStep(session))
184
- .then(resolve)
185
- .catch(reject);
110
+ this.runRetryStep(session);
186
111
  }
187
112
  })
188
113
  .catch(reject);
@@ -191,42 +116,17 @@ class MobileInstantLinkStep extends auth_status_actions_1.AuthStatusActions {
191
116
  this.runStartStep(session, true).then(resolve).catch(reject);
192
117
  }
193
118
  else {
194
- this.log.warn('Unkown enum of ', resultType);
119
+ this.log.warn('Unknown enum of ', resultType);
195
120
  }
196
121
  })
197
122
  .catch(reject);
198
123
  }
199
124
  else {
200
- this.log.debug("Retry step doesn't exsist, skip.");
125
+ this.log.debug("Retry step doesn't exist, skip.");
201
126
  resolve('');
202
127
  }
203
128
  });
204
129
  }
205
- handleTestMode(session) {
206
- return new Promise((resolve, reject) => {
207
- if (this.isTestMode(session)) {
208
- this.log.info('Simulating user clicking the instant link');
209
- setTimeout(() => {
210
- session.platform
211
- .fetch(session.backendOrigin +
212
- '/v1/client/mobile/instantlink/finish?token=' +
213
- encodeURIComponent(session.authToken) +
214
- '&vfp=test-vfp', {
215
- mode: 'no-cors',
216
- method: 'GET',
217
- })
218
- .then(() => resolve)
219
- .catch((e) => {
220
- this.log.error('Calling AuthFinish in test mode has failed: ', auth_error_1.default.extractMessage(e));
221
- reject(e);
222
- });
223
- }, SIMULATED_LINK_CLICK_DELAY);
224
- }
225
- else {
226
- resolve();
227
- }
228
- });
229
- }
230
130
  }
231
131
  MobileInstantLinkStep.NAME = 'mobile/instantlink';
232
132
  exports.default = MobileInstantLinkStep;
@@ -69,7 +69,7 @@ class MobileOtpStep {
69
69
  reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
70
70
  }
71
71
  else if (authResponse.data) {
72
- let data = authResponse.data;
72
+ const data = authResponse.data;
73
73
  var errorMessage = '';
74
74
  if (data === null || data === void 0 ? void 0 : data.code) {
75
75
  errorMessage += `Error Code: ${data.code}, `;
@@ -170,7 +170,7 @@ class MobileOtpStep {
170
170
  reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
171
171
  }
172
172
  else if (authResponse.data) {
173
- let data = authResponse.data;
173
+ const data = authResponse.data;
174
174
  var errorMessage = '';
175
175
  if (data === null || data === void 0 ? void 0 : data.code) {
176
176
  errorMessage += `Error Code: ${data.code}, `;
@@ -181,7 +181,7 @@ class MobileOtpStep {
181
181
  else {
182
182
  errorMessage += `Error validating OTP`;
183
183
  }
184
- let otpError = new otp_1.OtpError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
184
+ const otpError = new otp_1.OtpError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
185
185
  this.log.error(`Server reports invalid OTP: ${errorMessage}`);
186
186
  this.runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, otpError)
187
187
  .then(resolve)
@@ -4,6 +4,7 @@ import { AuthRequest } from './auth-request';
4
4
  import AuthResponse from './auth-response';
5
5
  import DeviceAuth, { DeviceRegistration } from './device-auth';
6
6
  import { Agent } from '@fingerprintjs/fingerprintjs-pro';
7
+ import { PpbOperation } from '../ppb';
7
8
  export declare const DEVICE_CAPABILITY_WEBAUTHN = "webauthn";
8
9
  export interface MessageChannel {
9
10
  addEventListener: (type: string, listener: (event: any) => void) => void;
@@ -27,6 +28,15 @@ export interface AuthSessionIntegration {
27
28
  getDeviceRegistration: () => Promise<DeviceRegistration | null>;
28
29
  fetchFromBackend: (query: string, body: AuthRequest) => Promise<AuthResponse>;
29
30
  }
31
+ export interface PpbAuthResult {
32
+ authIdSuccess?: boolean;
33
+ }
34
+ export interface PpbAuthOptions {
35
+ authIdEndpointUrl?: string;
36
+ authIdOperation?: PpbOperation;
37
+ authIdOperationId?: string;
38
+ authIdOneTimeSecret?: string;
39
+ }
30
40
  export default interface Platform {
31
41
  readonly webauthn: WebAuthN;
32
42
  readonly deviceAuth: DeviceAuth;
@@ -43,6 +53,7 @@ export default interface Platform {
43
53
  getFpPromise: () => Promise<Agent> | undefined;
44
54
  setFpPromise: (fpPromise: Promise<Agent>) => void;
45
55
  getOrigin: () => string;
56
+ ppbAuthenticate: (options: PpbAuthOptions) => Promise<PpbAuthResult>;
46
57
  }
47
58
  export declare function stringToArrayBuffer(input: string): ArrayBuffer;
48
59
  export declare function arrayBufferToString(input: ArrayBuffer): string;
@@ -16,6 +16,7 @@ const mobile_otp_step_1 = __importDefault(require("./mobile-otp-step"));
16
16
  const user_present_step_1 = __importDefault(require("./user-present-step"));
17
17
  const device_passive_stepup_step_1 = __importDefault(require("./device-passive-stepup-step"));
18
18
  const device_universal_redirect_steps_1 = require("./device-universal-redirect-steps");
19
+ const user_ppb_steps_1 = require("./user-ppb-steps");
19
20
  class ReportErrorStep {
20
21
  constructor(error) {
21
22
  this.logger = logger_1.LoggerFactory.getLogger('report-error-step');
@@ -82,11 +83,13 @@ ReportErrorStep.endpointMap = new Map([
82
83
  [device_passive_register_step_1.default.NAME, 'device/fido2'],
83
84
  [device_passive_verify_step_1.default.NAME, 'device/fido2'],
84
85
  [device_passive_stepup_step_1.default.NAME, 'device/fido2'],
86
+ [device_universal_redirect_steps_1.DeviceUniversalRedirectExchangeStep.NAME, 'device/universal'],
87
+ [device_universal_redirect_steps_1.DeviceUniversalRedirectFinishStep.NAME, 'device/universal'],
85
88
  [mobile_instant_step_1.default.NAME, 'mobile/instant'],
86
89
  [mobile_instantlink_step_1.default.NAME, 'mobile/instantlink'],
87
90
  [mobile_otp_step_1.default.NAME, 'mobile/otp'],
88
91
  [user_present_step_1.default.NAME, 'user/mobileactive'],
89
- [device_universal_redirect_steps_1.DeviceUniversalRedirectExchangeStep.NAME, 'device/universal'],
90
- [device_universal_redirect_steps_1.DeviceUniversalRedirectFinishStep.NAME, 'device/universal'],
92
+ [user_ppb_steps_1.UserPpbEnrollStep.NAME, 'user/ppb'],
93
+ [user_ppb_steps_1.UserPpbVerifyStep.NAME, 'user/ppb'],
91
94
  ]);
92
95
  exports.default = ReportErrorStep;
@@ -3,6 +3,7 @@ export default class Settings {
3
3
  static readonly DEVICE_ID_KEY = "DeviceId";
4
4
  static readonly NAMESPACE_KEY = "namespace";
5
5
  static readonly FIDO_PASSKEY_REGISTERED_KEY = "fidoPasskeyRegistered";
6
+ static readonly FP_TIMESTAMPT = "fingerPrintTimestamp";
6
7
  private readonly log;
7
8
  private storage;
8
9
  upkEnabled: boolean;
@@ -11,6 +12,8 @@ export default class Settings {
11
12
  get deviceId(): string | null;
12
13
  set deviceId(val: string | null);
13
14
  get fidoPasskeyRegistered(): boolean;
15
+ set fingerPrintTimestamp(val: number | null);
16
+ get fingerPrintTimestamp(): number | null;
14
17
  set fidoPasskeyRegistered(val: boolean);
15
18
  get namespace(): string | null;
16
19
  set namespace(val: string | null);
@@ -12,6 +12,7 @@ class Settings {
12
12
  this.deviceId = null;
13
13
  this.namespace = null;
14
14
  this.fidoPasskeyRegistered = false;
15
+ this.fingerPrintTimestamp = null;
15
16
  }
16
17
  get deviceId() {
17
18
  return this.storage.getItem(this.getKey(Settings.DEVICE_ID_KEY));
@@ -22,6 +23,18 @@ class Settings {
22
23
  get fidoPasskeyRegistered() {
23
24
  return this.storage.getItem(this.getKey(Settings.FIDO_PASSKEY_REGISTERED_KEY)) === 'true';
24
25
  }
26
+ set fingerPrintTimestamp(val) {
27
+ const assignedValue = val !== null ? val.toString() : null;
28
+ this.setOrRemove(Settings.FP_TIMESTAMPT, assignedValue);
29
+ }
30
+ get fingerPrintTimestamp() {
31
+ const storedTimestampString = this.storage.getItem(this.getKey(Settings.FP_TIMESTAMPT));
32
+ if (!storedTimestampString) {
33
+ return null;
34
+ }
35
+ let fingerprintTimestamp = parseInt(storedTimestampString);
36
+ return isNaN(fingerprintTimestamp) ? null : fingerprintTimestamp;
37
+ }
25
38
  set fidoPasskeyRegistered(val) {
26
39
  this.setOrRemove(Settings.FIDO_PASSKEY_REGISTERED_KEY, val ? 'true' : null);
27
40
  }
@@ -48,4 +61,5 @@ Settings.KEY_PREFIX = 'ProveAuth';
48
61
  Settings.DEVICE_ID_KEY = 'DeviceId';
49
62
  Settings.NAMESPACE_KEY = 'namespace';
50
63
  Settings.FIDO_PASSKEY_REGISTERED_KEY = 'fidoPasskeyRegistered';
64
+ Settings.FP_TIMESTAMPT = 'fingerPrintTimestamp';
51
65
  exports.default = Settings;
@@ -9,9 +9,7 @@ class UserMobileActiveStep {
9
9
  this.name = UserMobileActiveStep.NAME;
10
10
  }
11
11
  execute(session) {
12
- return new Promise((resolve, reject) => {
13
- reject(new auth_error_1.default(`Step ${this.name} is not supported yet`));
14
- });
12
+ return Promise.reject(new auth_error_1.default(`Step ${this.name} is not supported`));
15
13
  }
16
14
  }
17
15
  UserMobileActiveStep.NAME = 'user/mobileactive';
@@ -0,0 +1,24 @@
1
+ import AuthStep from './auth-step';
2
+ import AuthSession from './auth-session';
3
+ import { PpbFinishStep, PpbOperation, PpbStartStep } from '../ppb';
4
+ declare abstract class UserPpbBaseStep implements AuthStep {
5
+ readonly name: string;
6
+ private readonly log;
7
+ private readonly enabled;
8
+ private readonly operation;
9
+ private readonly startStep;
10
+ private readonly finishStep;
11
+ constructor(enabled: boolean, operation: PpbOperation, startStep?: PpbStartStep, finishStep?: PpbFinishStep);
12
+ execute(session: AuthSession): Promise<string>;
13
+ }
14
+ export declare class UserPpbEnrollStep extends UserPpbBaseStep {
15
+ static readonly NAME = "user/ppb/register";
16
+ readonly name = "user/ppb/register";
17
+ constructor(enabled: boolean, startStep?: PpbStartStep, finishStep?: PpbFinishStep);
18
+ }
19
+ export declare class UserPpbVerifyStep extends UserPpbBaseStep {
20
+ static readonly NAME = "user/ppb/verify";
21
+ readonly name = "user/ppb/verify";
22
+ constructor(enabled: boolean, startStep?: PpbStartStep, finishStep?: PpbFinishStep);
23
+ }
24
+ export {};
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.UserPpbVerifyStep = exports.UserPpbEnrollStep = void 0;
7
+ const logger_1 = require("../common/logger");
8
+ const auth_error_1 = __importDefault(require("./auth-error"));
9
+ class UserPpbBaseStep {
10
+ constructor(enabled, operation, startStep, finishStep) {
11
+ this.log = logger_1.LoggerFactory.getLogger('user-ppb-base-step');
12
+ this.enabled = enabled;
13
+ this.operation = operation;
14
+ this.startStep = startStep;
15
+ this.finishStep = finishStep;
16
+ }
17
+ execute(session) {
18
+ if (!this.enabled) {
19
+ return Promise.reject(new auth_error_1.default('PPB is not enabled'));
20
+ }
21
+ const data = session.lastData;
22
+ if (!data || !data.ppb) {
23
+ return Promise.reject(new auth_error_1.default('PPB session is not initialized'));
24
+ }
25
+ return new Promise((resolve, reject) => {
26
+ const callStart = () => {
27
+ try {
28
+ if (this.startStep) {
29
+ return this.startStep.execute(this.operation);
30
+ }
31
+ else {
32
+ return Promise.resolve();
33
+ }
34
+ }
35
+ catch (e) {
36
+ this.log.warn('PPB start step has failed:', e);
37
+ return Promise.reject(e);
38
+ }
39
+ };
40
+ const callFinish = (error) => {
41
+ try {
42
+ if (this.finishStep) {
43
+ return this.finishStep.execute(this.operation, error);
44
+ }
45
+ else {
46
+ return Promise.resolve();
47
+ }
48
+ }
49
+ catch (e) {
50
+ this.log.warn('PPB finish step has failed:', e);
51
+ return Promise.reject(e);
52
+ }
53
+ };
54
+ callStart()
55
+ .then(() => {
56
+ var _a, _b, _c, _d, _e;
57
+ return session.platform.ppbAuthenticate({
58
+ authIdOperation: this.operation,
59
+ authIdEndpointUrl: (_c = (_b = (_a = session.claims) === null || _a === void 0 ? void 0 : _a.auth.subs.usr) === null || _b === void 0 ? void 0 : _b.auths.ppb) === null || _c === void 0 ? void 0 : _c.endp,
60
+ authIdOperationId: (_d = data.ppb) === null || _d === void 0 ? void 0 : _d.operationId,
61
+ authIdOneTimeSecret: (_e = data.ppb) === null || _e === void 0 ? void 0 : _e.oneTimeSecret,
62
+ });
63
+ })
64
+ .catch(reject)
65
+ .then((result) => {
66
+ var _a;
67
+ this.log.info('PPB authentication result', result);
68
+ return session.fetchFromBackend('/v1/client/user/ppb/finish', {
69
+ requestId: crypto.randomUUID(),
70
+ operationId: (_a = data.ppb) === null || _a === void 0 ? void 0 : _a.operationId,
71
+ });
72
+ })
73
+ .then((response) => {
74
+ var _a, _b;
75
+ const ppbResponse = response;
76
+ if (ppbResponse.error) {
77
+ const message = (_b = (_a = response.error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'PPB authentication failed';
78
+ callFinish(new Error(message)).then(() => reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false)));
79
+ }
80
+ else {
81
+ callFinish().then(() => resolve(ppbResponse.next));
82
+ }
83
+ })
84
+ .catch(reject);
85
+ });
86
+ }
87
+ }
88
+ class UserPpbEnrollStep extends UserPpbBaseStep {
89
+ constructor(enabled, startStep, finishStep) {
90
+ super(enabled, 'enroll', startStep, finishStep);
91
+ this.name = UserPpbEnrollStep.NAME;
92
+ }
93
+ }
94
+ UserPpbEnrollStep.NAME = 'user/ppb/register';
95
+ exports.UserPpbEnrollStep = UserPpbEnrollStep;
96
+ class UserPpbVerifyStep extends UserPpbBaseStep {
97
+ constructor(enabled, startStep, finishStep) {
98
+ super(enabled, 'verify', startStep, finishStep);
99
+ this.name = UserPpbVerifyStep.NAME;
100
+ }
101
+ }
102
+ UserPpbVerifyStep.NAME = 'user/ppb/verify';
103
+ exports.UserPpbVerifyStep = UserPpbVerifyStep;
@@ -9,9 +9,7 @@ class UserPresentStep {
9
9
  this.name = UserPresentStep.NAME;
10
10
  }
11
11
  execute(session) {
12
- return new Promise((resolve, reject) => {
13
- reject(new auth_error_1.default(`Step ${this.name} is not supported yet`));
14
- });
12
+ return Promise.reject(new auth_error_1.default(`Step ${this.name} is not supported`));
15
13
  }
16
14
  }
17
15
  UserPresentStep.NAME = 'user/present';
@@ -1,5 +1,5 @@
1
1
  import { AuthenticatorBuilder } from '@prove-identity/mobile-auth';
2
- import Platform, { AuthSessionIntegration, MessageChannel, RequestSigner } from './platform';
2
+ import Platform, { AuthSessionIntegration, MessageChannel, PpbAuthOptions, PpbAuthResult, RequestSigner } from './platform';
3
3
  import WebDeviceAuth from './web-device-auth';
4
4
  import { Agent } from '@fingerprintjs/fingerprintjs-pro';
5
5
  export declare class WebSocketMessageChannel implements MessageChannel {
@@ -10,6 +10,7 @@ export declare class WebSocketMessageChannel implements MessageChannel {
10
10
  close(): void;
11
11
  }
12
12
  export declare class WebPlatform implements Platform {
13
+ private readonly log;
13
14
  private fpPromise;
14
15
  readonly webauthn: {
15
16
  getCredentials: (options?: CredentialRequestOptions) => Promise<CredentialType | null>;
@@ -22,6 +23,7 @@ export declare class WebPlatform implements Platform {
22
23
  fetch(input: string, init?: RequestInit): Promise<Response>;
23
24
  createMessageChannel(input: string): MessageChannel;
24
25
  createRequestSigner(session: AuthSessionIntegration): RequestSigner;
26
+ ppbAuthenticate(options: PpbAuthOptions): Promise<PpbAuthResult>;
25
27
  private getBrowserName;
26
28
  private getBrowserVersion;
27
29
  getOSName(): string;