@prove-identity/prove-auth 2.4.4 → 2.7.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 (47) hide show
  1. package/build/lib/index.d.ts +3 -1
  2. package/build/lib/index.js +3 -1
  3. package/build/lib/proveauth/authenticator-builder.d.ts +13 -1
  4. package/build/lib/proveauth/authenticator-builder.js +123 -6
  5. package/build/lib/proveauth/device-context-options.d.ts +19 -0
  6. package/build/lib/proveauth/device-context-options.js +19 -0
  7. package/build/lib/proveauth/internal/auth-request.d.ts +12 -0
  8. package/build/lib/proveauth/internal/auth-response.d.ts +1 -0
  9. package/build/lib/proveauth/internal/auth-session.d.ts +15 -8
  10. package/build/lib/proveauth/internal/auth-session.js +106 -21
  11. package/build/lib/proveauth/internal/auth-status-actions.d.ts +5 -0
  12. package/build/lib/proveauth/internal/auth-status-actions.js +48 -0
  13. package/build/lib/proveauth/internal/auth-token-claims.d.ts +9 -0
  14. package/build/lib/proveauth/internal/device-auth.d.ts +4 -1
  15. package/build/lib/proveauth/internal/device-passive-register-step.js +10 -9
  16. package/build/lib/proveauth/internal/device-passive-silent-step.d.ts +7 -1
  17. package/build/lib/proveauth/internal/device-passive-silent-step.js +43 -14
  18. package/build/lib/proveauth/internal/device-passive-step.d.ts +2 -1
  19. package/build/lib/proveauth/internal/device-passive-step.js +4 -3
  20. package/build/lib/proveauth/internal/device-passive-verify-step.d.ts +2 -0
  21. package/build/lib/proveauth/internal/device-passive-verify-step.js +18 -0
  22. package/build/lib/proveauth/internal/device-universal-redirect-steps.d.ts +14 -0
  23. package/build/lib/proveauth/internal/device-universal-redirect-steps.js +55 -0
  24. package/build/lib/proveauth/internal/device-universal-step.d.ts +10 -0
  25. package/build/lib/proveauth/internal/device-universal-step.js +38 -0
  26. package/build/lib/proveauth/internal/{base-authenticator.d.ts → main-authenticator.d.ts} +8 -5
  27. package/build/lib/proveauth/internal/{base-authenticator.js → main-authenticator.js} +61 -17
  28. package/build/lib/proveauth/internal/mobile-instantlink-step.d.ts +2 -1
  29. package/build/lib/proveauth/internal/mobile-instantlink-step.js +9 -5
  30. package/build/lib/proveauth/internal/platform.d.ts +6 -1
  31. package/build/lib/proveauth/internal/report-error-step.d.ts +2 -2
  32. package/build/lib/proveauth/internal/report-error-step.js +11 -8
  33. package/build/lib/proveauth/internal/settings.d.ts +1 -0
  34. package/build/lib/proveauth/internal/settings.js +1 -0
  35. package/build/lib/proveauth/internal/web-device-auth.d.ts +4 -1
  36. package/build/lib/proveauth/internal/web-device-auth.js +6 -0
  37. package/build/lib/proveauth/internal/web-platform.d.ts +8 -1
  38. package/build/lib/proveauth/internal/web-platform.js +14 -2
  39. package/build/lib/proveauth/user-consent-step.d.ts +7 -0
  40. package/build/lib/proveauth/user-consent-step.js +2 -0
  41. package/build/lib/proveauth/version.d.ts +2 -2
  42. package/build/lib/proveauth/version.js +2 -2
  43. package/package.json +12 -3
  44. package/build/lib/proveauth/internal/primary-authenticator.d.ts +0 -14
  45. package/build/lib/proveauth/internal/primary-authenticator.js +0 -64
  46. package/build/lib/proveauth/internal/secondary-authenticator.d.ts +0 -10
  47. package/build/lib/proveauth/internal/secondary-authenticator.js +0 -65
@@ -1,5 +1,6 @@
1
1
  import { VERSION } from './proveauth/version';
2
2
  import AuthenticatorBuilder, { AuthMessageHandler, DeviceRole, MobileAuthImplementation } from './proveauth/authenticator-builder';
3
+ import DeviceContextOptions, { BuildConfig } from './proveauth/device-context-options';
3
4
  import AuthMessage from './proveauth/internal/auth-message';
4
5
  import { AuthResponseStatus } from './proveauth/internal/auth-response-status';
5
6
  import { LoggerFactory, LogWriter, LogLevel, Logger } from './proveauth/common/logger';
@@ -9,4 +10,5 @@ import Authenticator from './proveauth/authenticator';
9
10
  import { PhoneValidationError } from './proveauth/internal/phone-number-input';
10
11
  import { OtpError, OtpStartStep, OtpStartInput, OtpStartStepFn, OtpFinishStep, OtpFinishInput, OtpFinishStepFn, OtpFinishResult, OtpFinishResultType } from './proveauth/otp';
11
12
  import { InstantLinkStartInput, InstantLinkStartStep, InstantLinkStartStepFn } from './proveauth/instantlink';
12
- export { VERSION, AuthFinishStep, AuthFinishStepFn, AuthFinishStepInput, Authenticator, AuthenticatorBuilder, AuthMessage, AuthMessageHandler, AuthResponseStatus, CancelablePromise, DeviceRole, InstantLinkStartStep, InstantLinkStartInput, InstantLinkStartStepFn, Logger, LoggerFactory, LogLevel, LogWriter, MobileAuthImplementation, OtpFinishStep, OtpFinishInput, OtpFinishResult, OtpFinishStepFn, OtpFinishResultType, OtpStartStep, OtpStartInput, OtpStartStepFn, OtpError, PhoneValidationError, };
13
+ import UserConsentStep, { UserConsentOutput, UserConsentStepFn } from './proveauth/user-consent-step';
14
+ export { VERSION, AuthFinishStep, AuthFinishStepFn, AuthFinishStepInput, Authenticator, AuthenticatorBuilder, AuthMessage, AuthMessageHandler, AuthResponseStatus, CancelablePromise, DeviceRole, InstantLinkStartStep, InstantLinkStartInput, InstantLinkStartStepFn, Logger, LoggerFactory, LogLevel, LogWriter, MobileAuthImplementation, OtpFinishStep, OtpFinishInput, OtpFinishResult, OtpFinishStepFn, OtpFinishResultType, OtpStartStep, OtpStartInput, OtpStartStepFn, OtpError, PhoneValidationError, BuildConfig, DeviceContextOptions, UserConsentStep, UserConsentStepFn, UserConsentOutput, };
@@ -26,13 +26,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.PhoneValidationError = exports.OtpError = exports.OtpFinishResultType = exports.MobileAuthImplementation = exports.LogLevel = exports.LoggerFactory = exports.DeviceRole = exports.CancelablePromise = exports.AuthResponseStatus = exports.AuthenticatorBuilder = exports.VERSION = void 0;
29
+ exports.BuildConfig = exports.PhoneValidationError = exports.OtpError = exports.OtpFinishResultType = exports.MobileAuthImplementation = exports.LogLevel = exports.LoggerFactory = exports.DeviceRole = exports.CancelablePromise = exports.AuthResponseStatus = exports.AuthenticatorBuilder = exports.VERSION = void 0;
30
30
  const version_1 = require("./proveauth/version");
31
31
  Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return version_1.VERSION; } });
32
32
  const authenticator_builder_1 = __importStar(require("./proveauth/authenticator-builder"));
33
33
  exports.AuthenticatorBuilder = authenticator_builder_1.default;
34
34
  Object.defineProperty(exports, "DeviceRole", { enumerable: true, get: function () { return authenticator_builder_1.DeviceRole; } });
35
35
  Object.defineProperty(exports, "MobileAuthImplementation", { enumerable: true, get: function () { return authenticator_builder_1.MobileAuthImplementation; } });
36
+ const device_context_options_1 = require("./proveauth/device-context-options");
37
+ Object.defineProperty(exports, "BuildConfig", { enumerable: true, get: function () { return device_context_options_1.BuildConfig; } });
36
38
  const auth_response_status_1 = require("./proveauth/internal/auth-response-status");
37
39
  Object.defineProperty(exports, "AuthResponseStatus", { enumerable: true, get: function () { return auth_response_status_1.AuthResponseStatus; } });
38
40
  const logger_1 = require("./proveauth/common/logger");
@@ -5,6 +5,9 @@ import { AuthResponseStatus } from './internal/auth-response-status';
5
5
  import Platform from './internal/platform';
6
6
  import { OtpFinishStep, OtpFinishStepFn, OtpStartStep, OtpStartStepFn } from './otp';
7
7
  import { InstantLinkStartStep, InstantLinkStartStepFn } from './instantlink';
8
+ import type { Region } from '@fingerprintjs/fingerprintjs-pro';
9
+ import DeviceContextOptions, { BuildConfig } from './device-context-options';
10
+ import UserConsentStep, { UserConsentStepFn } from './user-consent-step';
8
11
  export type AuthMessageHandler = (message: AuthMessage) => Promise<AuthResponseStatus>;
9
12
  export declare enum DeviceRole {
10
13
  Primary = 0,
@@ -26,8 +29,12 @@ export default class AuthenticatorBuilder {
26
29
  private otpStartStep?;
27
30
  private otpFinishStep?;
28
31
  private instantLinkStartStep?;
29
- private instantLinkTestMode;
32
+ private upkEnabled;
33
+ private userConsentStep?;
34
+ private readonly log;
35
+ private deviceContextOptions?;
30
36
  constructor();
37
+ withDeviceContext(options: DeviceContextOptions): AuthenticatorBuilder;
31
38
  withAuthFinishStep(step: AuthFinishStep | AuthFinishStepFn): AuthenticatorBuilder;
32
39
  withDisplayName(displayName: string | (() => string | null) | null): AuthenticatorBuilder;
33
40
  withAuthMessageHandler(handler: AuthMessageHandler): AuthenticatorBuilder;
@@ -38,5 +45,10 @@ export default class AuthenticatorBuilder {
38
45
  withDeviceIpAddress(deviceIp: string | (() => string | null) | null): AuthenticatorBuilder;
39
46
  withOtpFallback(startStep: OtpStartStep | OtpStartStepFn, finishStep: OtpFinishStep | OtpFinishStepFn): AuthenticatorBuilder;
40
47
  withInstantLinkFallback(startStep: InstantLinkStartStep | InstantLinkStartStepFn): AuthenticatorBuilder;
48
+ withUPKEnabled(): this;
49
+ withUniversalProveKey(step?: UserConsentStep | UserConsentStepFn): this;
50
+ getUrlsByBuildConfig(buildConfig?: BuildConfig): [string | undefined, string | undefined];
51
+ getRegionByBuildConfig(buildConfig?: BuildConfig): Region;
52
+ private getFpPromiseInstanceFromOptions;
41
53
  build(): Authenticator;
42
54
  }
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.MobileAuthImplementation = exports.DeviceRole = void 0;
7
- const primary_authenticator_1 = __importDefault(require("./internal/primary-authenticator"));
8
7
  const web_platform_1 = require("./internal/web-platform");
9
8
  const device_passive_register_step_1 = __importDefault(require("./internal/device-passive-register-step"));
10
9
  const device_passive_step_1 = __importDefault(require("./internal/device-passive-step"));
@@ -14,9 +13,14 @@ const mobile_instantlink_step_1 = __importDefault(require("./internal/mobile-ins
14
13
  const mobile_otp_step_1 = __importDefault(require("./internal/mobile-otp-step"));
15
14
  const scan_message_step_1 = __importDefault(require("./internal/scan-message-step"));
16
15
  const user_mobileactive_step_1 = __importDefault(require("./internal/user-mobileactive-step"));
17
- const secondary_authenticator_1 = __importDefault(require("./internal/secondary-authenticator"));
18
16
  const device_passive_silent_step_1 = __importDefault(require("./internal/device-passive-silent-step"));
19
17
  const device_passive_stepup_step_1 = __importDefault(require("./internal/device-passive-stepup-step"));
18
+ const device_universal_step_1 = __importDefault(require("./internal/device-universal-step"));
19
+ const device_universal_redirect_steps_1 = require("./internal/device-universal-redirect-steps");
20
+ const main_authenticator_1 = __importDefault(require("./internal/main-authenticator"));
21
+ const logger_1 = require("./common/logger");
22
+ const settings_1 = __importDefault(require("./internal/settings"));
23
+ const device_context_options_1 = require("./device-context-options");
20
24
  var DeviceRole;
21
25
  (function (DeviceRole) {
22
26
  DeviceRole[DeviceRole["Primary"] = 0] = "Primary";
@@ -31,12 +35,17 @@ class AuthenticatorBuilder {
31
35
  constructor() {
32
36
  this.role = DeviceRole.Primary;
33
37
  this.mobileAuthImplementation = MobileAuthImplementation.Fetch;
34
- this.instantLinkTestMode = false;
38
+ this.upkEnabled = false;
39
+ this.log = logger_1.LoggerFactory.getLogger('authenticator-builder');
35
40
  if (typeof window !== 'undefined') {
36
41
  this.storage = window.localStorage;
37
42
  this.platform = new web_platform_1.WebPlatform();
38
43
  }
39
44
  }
45
+ withDeviceContext(options) {
46
+ this.deviceContextOptions = options;
47
+ return this;
48
+ }
40
49
  withAuthFinishStep(step) {
41
50
  if (typeof step === 'function') {
42
51
  this.authFinishStep = {
@@ -100,22 +109,130 @@ class AuthenticatorBuilder {
100
109
  }
101
110
  return this;
102
111
  }
112
+ withUPKEnabled() {
113
+ return this.withUniversalProveKey();
114
+ }
115
+ withUniversalProveKey(step) {
116
+ if (!step) {
117
+ this.userConsentStep = { execute: () => Promise.resolve({ consentGranted: true }) };
118
+ }
119
+ else if (typeof step === 'function') {
120
+ this.userConsentStep = { execute: step };
121
+ }
122
+ else {
123
+ this.userConsentStep = step;
124
+ }
125
+ this.upkEnabled = this.userConsentStep != null;
126
+ return this;
127
+ }
128
+ getUrlsByBuildConfig(buildConfig) {
129
+ switch (buildConfig) {
130
+ case device_context_options_1.BuildConfig.US_PROD:
131
+ return [
132
+ device_context_options_1.ProveAuthProxyScriptUrl.DEFAULT_US_PROD_SCRIPT_URL.toString(),
133
+ device_context_options_1.ProveAuthProxyEndpoint.DEFAULT_US_PROD_ENDPOINT.toString(),
134
+ ];
135
+ case device_context_options_1.BuildConfig.US_UAT:
136
+ return [
137
+ device_context_options_1.ProveAuthProxyScriptUrl.DEFAULT_US_UAT_SCRIPT_URL.toString(),
138
+ device_context_options_1.ProveAuthProxyEndpoint.DEFAULT_US_UAT_ENDPOINT.toString(),
139
+ ];
140
+ case device_context_options_1.BuildConfig.DEV:
141
+ this.log.debug("Recommended for Prove's internal testing only, BuildConfig.DEV might need custom endpoint URL and custom script URL values to bypass ad blockers");
142
+ return [undefined, undefined];
143
+ default:
144
+ this.log.warn('Unknown BuildConfig value: ' + buildConfig);
145
+ return [undefined, undefined];
146
+ }
147
+ }
148
+ getRegionByBuildConfig(buildConfig) {
149
+ var region;
150
+ switch (buildConfig) {
151
+ case device_context_options_1.BuildConfig.DEV:
152
+ case device_context_options_1.BuildConfig.US_PROD:
153
+ case device_context_options_1.BuildConfig.US_UAT:
154
+ region = 'us';
155
+ break;
156
+ default:
157
+ this.log.warn('Unknown BuildConfig value, set Region to default value: us');
158
+ region = 'us';
159
+ break;
160
+ }
161
+ return region;
162
+ }
163
+ getFpPromiseInstanceFromOptions(options) {
164
+ try {
165
+ const FingerprintJS = require('@fingerprintjs/fingerprintjs-pro');
166
+ if (!FingerprintJS) {
167
+ this.log.debug('fingerprintjs package is not installed or failed to load');
168
+ }
169
+ else if (!options) {
170
+ this.log.warn('Prove Key Persistence feature is not enabled');
171
+ }
172
+ else {
173
+ let region = this.getRegionByBuildConfig(options.buildConfig);
174
+ let [scriptUrl, endpointUrl] = this.getUrlsByBuildConfig(options.buildConfig);
175
+ if (options.customScriptUrl && options.customEndpointUrl) {
176
+ scriptUrl = options.customScriptUrl;
177
+ endpointUrl = options.customEndpointUrl;
178
+ }
179
+ const scriptUrlPattern = scriptUrl
180
+ ? [
181
+ `${scriptUrl}?apiKey=<apiKey>&version=<version>&loaderVersion=<loaderVersion>`,
182
+ FingerprintJS.defaultScriptUrlPattern,
183
+ ]
184
+ : [FingerprintJS.defaultScriptUrlPattern];
185
+ const endpoint = endpointUrl
186
+ ? [`${endpointUrl}?region=${region}`, FingerprintJS.defaultEndpoint]
187
+ : [FingerprintJS.defaultEndpoint];
188
+ const fpPromise = FingerprintJS.load({
189
+ apiKey: options.publicApiKey,
190
+ endpoint: endpoint,
191
+ scriptUrlPattern: scriptUrlPattern,
192
+ region: region,
193
+ });
194
+ const status = fpPromise ? 'successfully' : 'unsuccessfully with null instance';
195
+ this.log.trace(`Instantiating FingerprintJS ${status}`);
196
+ return fpPromise;
197
+ }
198
+ }
199
+ catch (error) {
200
+ this.log.trace('FingerprintJS is not installed or failed to load', error);
201
+ }
202
+ }
103
203
  build() {
204
+ var _a;
205
+ if (!this.platform) {
206
+ throw new Error('Implementation of Platform is required');
207
+ }
208
+ if (!this.storage) {
209
+ throw new Error('Implementation of Storage is required');
210
+ }
211
+ const fpPromise = this.getFpPromiseInstanceFromOptions(this.deviceContextOptions);
212
+ if (fpPromise) {
213
+ (_a = this.platform) === null || _a === void 0 ? void 0 : _a.setFpPromise(fpPromise);
214
+ }
215
+ const settings = new settings_1.default(this.storage);
216
+ settings.upkEnabled = this.upkEnabled;
104
217
  if (this.role === DeviceRole.Primary) {
105
- return new primary_authenticator_1.default(this.platform, this.storage, this.authFinishStep, [
218
+ return new main_authenticator_1.default(this.platform, settings, this.authFinishStep, [
219
+ new device_universal_step_1.default(this.upkEnabled),
220
+ new device_universal_redirect_steps_1.DeviceUniversalRedirectExchangeStep(),
221
+ new device_universal_redirect_steps_1.DeviceUniversalRedirectFinishStep(),
106
222
  new device_passive_step_1.default(this.getDisplayName, this.role),
107
223
  new device_passive_stepup_step_1.default(this.getDisplayName),
108
- new device_passive_silent_step_1.default(),
224
+ new device_passive_silent_step_1.default(this.upkEnabled, this.userConsentStep),
109
225
  new device_passive_register_step_1.default(),
110
226
  new device_passive_verify_step_1.default(),
111
227
  new mobile_instant_step_1.default(this.mobileAuthImplementation, this.getDeviceIp),
228
+ new mobile_instantlink_step_1.default(this.instantLinkStartStep, this.getDeviceIp),
112
229
  new mobile_otp_step_1.default(this.otpStartStep, this.otpFinishStep),
113
230
  new user_mobileactive_step_1.default(),
114
231
  new scan_message_step_1.default(this.authMessageHandler),
115
232
  ]);
116
233
  }
117
234
  else {
118
- return new secondary_authenticator_1.default(this.platform, this.storage, this.authFinishStep, [
235
+ return new main_authenticator_1.default(this.platform, settings, this.authFinishStep, [
119
236
  new device_passive_step_1.default(this.getDisplayName, this.role),
120
237
  new mobile_instant_step_1.default(this.mobileAuthImplementation, this.getDeviceIp),
121
238
  new mobile_instantlink_step_1.default(this.instantLinkStartStep, this.getDeviceIp),
@@ -0,0 +1,19 @@
1
+ export declare enum ProveAuthProxyScriptUrl {
2
+ DEFAULT_US_UAT_SCRIPT_URL = "https://upk.uat.prove-auth.proveapis.com/vFqZceQyx8/uqLttozA7q",
3
+ DEFAULT_US_PROD_SCRIPT_URL = "https://upk.prove-auth.proveapis.com/vf82rhgDRK/r4VnwuwPUd"
4
+ }
5
+ export declare enum ProveAuthProxyEndpoint {
6
+ DEFAULT_US_UAT_ENDPOINT = "https://upk.uat.prove-auth.proveapis.com/vFqZceQyx8/bt9xhGAgQw",
7
+ DEFAULT_US_PROD_ENDPOINT = "https://upk.prove-auth.proveapis.com/vf82rhgDRK/ePaZsNne4X"
8
+ }
9
+ export declare enum BuildConfig {
10
+ DEV = "DEV",
11
+ US_UAT = "US_UAT",
12
+ US_PROD = "US_PROD"
13
+ }
14
+ export default interface DeviceContextOptions {
15
+ readonly buildConfig: BuildConfig;
16
+ readonly publicApiKey: string;
17
+ readonly customScriptUrl?: string;
18
+ readonly customEndpointUrl?: string;
19
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BuildConfig = exports.ProveAuthProxyEndpoint = exports.ProveAuthProxyScriptUrl = void 0;
4
+ var ProveAuthProxyScriptUrl;
5
+ (function (ProveAuthProxyScriptUrl) {
6
+ ProveAuthProxyScriptUrl["DEFAULT_US_UAT_SCRIPT_URL"] = "https://upk.uat.prove-auth.proveapis.com/vFqZceQyx8/uqLttozA7q";
7
+ ProveAuthProxyScriptUrl["DEFAULT_US_PROD_SCRIPT_URL"] = "https://upk.prove-auth.proveapis.com/vf82rhgDRK/r4VnwuwPUd";
8
+ })(ProveAuthProxyScriptUrl = exports.ProveAuthProxyScriptUrl || (exports.ProveAuthProxyScriptUrl = {}));
9
+ var ProveAuthProxyEndpoint;
10
+ (function (ProveAuthProxyEndpoint) {
11
+ ProveAuthProxyEndpoint["DEFAULT_US_UAT_ENDPOINT"] = "https://upk.uat.prove-auth.proveapis.com/vFqZceQyx8/bt9xhGAgQw";
12
+ ProveAuthProxyEndpoint["DEFAULT_US_PROD_ENDPOINT"] = "https://upk.prove-auth.proveapis.com/vf82rhgDRK/ePaZsNne4X";
13
+ })(ProveAuthProxyEndpoint = exports.ProveAuthProxyEndpoint || (exports.ProveAuthProxyEndpoint = {}));
14
+ var BuildConfig;
15
+ (function (BuildConfig) {
16
+ BuildConfig["DEV"] = "DEV";
17
+ BuildConfig["US_UAT"] = "US_UAT";
18
+ BuildConfig["US_PROD"] = "US_PROD";
19
+ })(BuildConfig = exports.BuildConfig || (exports.BuildConfig = {}));
@@ -32,6 +32,7 @@ export interface V1ClientDeviceFido2RegisterFinish {
32
32
  deviceName: string;
33
33
  deviceCapabilities: string[];
34
34
  registrations: AuthRegistration[];
35
+ signals?: Signals;
35
36
  }
36
37
  export interface V1ClientDeviceFido2VerifyStart {
37
38
  deviceId: string;
@@ -50,16 +51,19 @@ export interface WebAuthnAssertion {
50
51
  }
51
52
  export interface V1ClientDeviceFido2VerifyFinish {
52
53
  webAuthnAssertion: WebAuthnAssertion;
54
+ signals?: Signals;
53
55
  }
54
56
  export interface V1ClientDevicePassiveRegister {
55
57
  deviceName: string;
56
58
  deviceCapabilities: string[];
57
59
  registrations: PassiveRegistration[];
60
+ signals?: Signals;
58
61
  }
59
62
  export interface V1ClientDevicePassiveVerify {
60
63
  deviceId: string;
61
64
  keyId: string;
62
65
  signature: string;
66
+ signals?: Signals;
63
67
  }
64
68
  export interface V1ClientUserResponse {
65
69
  response: AuthResponseStatus;
@@ -88,3 +92,11 @@ export interface V1ClientOtpStart {
88
92
  export interface V1ClientOtpFinish {
89
93
  otp: string;
90
94
  }
95
+ export interface Signals {
96
+ fingerprint?: Signal;
97
+ darwinium?: Signal;
98
+ }
99
+ export interface Signal {
100
+ results?: string;
101
+ error?: string;
102
+ }
@@ -16,6 +16,7 @@ export interface RegisterStartAuthResponse extends AuthResponse {
16
16
  }
17
17
  export interface RegisterFinishAuthResponseData {
18
18
  deviceId: string;
19
+ passkey: boolean;
19
20
  }
20
21
  export interface RegisterFinishAuthResponse extends AuthResponse {
21
22
  data: RegisterFinishAuthResponseData;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="webappsec-credential-management" />
2
2
  import AuthMessage from './auth-message';
3
- import { AuthRequest } from './auth-request';
3
+ import { AuthRequest, Signal } from './auth-request';
4
4
  import AuthResponse from './auth-response';
5
5
  import AuthTokenClaims, { UserVerificationLevel } from './auth-token-claims';
6
6
  import { DeviceRegistration } from './device-auth';
@@ -12,19 +12,26 @@ export default class AuthSession implements AuthSessionIntegration {
12
12
  readonly claims?: AuthTokenClaims;
13
13
  readonly settings: Settings;
14
14
  readonly requestSigner: RequestSigner;
15
- lastStep: string | null;
16
- credential: CredentialType | null;
17
- authMessage: AuthMessage | null;
18
- uvLevel: UserVerificationLevel | null;
19
- backendUrlOverride: string | null;
15
+ readonly channels: Set<MessageChannel>;
16
+ private readonly log;
17
+ lastStep?: string;
18
+ credential?: CredentialType;
19
+ authMessage?: AuthMessage;
20
+ uvLevel?: UserVerificationLevel;
21
+ backendOriginOverride?: string;
20
22
  get namespace(): string;
21
- get backendUrl(): string;
23
+ get backendOrigin(): string;
24
+ set backendOrigin(backendOrigin: string);
22
25
  get authId(): string;
23
26
  get challenge(): string;
24
27
  get next(): string;
25
28
  constructor(settings: Settings, platform: Platform, authToken?: string);
26
29
  fetchFromBackend(query: string, body: AuthRequest): Promise<AuthResponse>;
27
- createMessageChannel(endpointPath: string, onClose: () => void, onError: (message: string) => void, onMessage: (data: string) => void): MessageChannel;
30
+ createMessageChannel(query: string, onClose: () => void, onError: (message: string) => void, onMessage: (data: string) => void): MessageChannel;
31
+ closeAllMessageChannels(): void;
28
32
  getDeviceRegistration(): Promise<DeviceRegistration | null>;
33
+ embedFpResultToDeviceRegistration(registration: DeviceRegistration): Promise<DeviceRegistration>;
34
+ getFingerprintData(): Promise<Signal | undefined>;
35
+ shouldCollectFP(): boolean;
29
36
  private parseJwt;
30
37
  }
@@ -12,9 +12,12 @@ class AuthSession {
12
12
  var _a;
13
13
  return ((_a = this.claims) === null || _a === void 0 ? void 0 : _a.auth.ans) || this.settings.namespace;
14
14
  }
15
- get backendUrl() {
15
+ get backendOrigin() {
16
16
  var _a;
17
- return ((_a = this.claims) === null || _a === void 0 ? void 0 : _a.auth.endp) || this.backendUrlOverride;
17
+ return this.backendOriginOverride || ((_a = this.claims) === null || _a === void 0 ? void 0 : _a.auth.endp);
18
+ }
19
+ set backendOrigin(backendOrigin) {
20
+ this.backendOriginOverride = backendOrigin;
18
21
  }
19
22
  get authId() {
20
23
  var _a;
@@ -30,11 +33,8 @@ class AuthSession {
30
33
  }
31
34
  constructor(settings, platform, authToken) {
32
35
  var _a, _b;
33
- this.lastStep = null;
34
- this.credential = null;
35
- this.authMessage = null;
36
- this.uvLevel = null;
37
- this.backendUrlOverride = null;
36
+ this.channels = new Set();
37
+ this.log = logger_1.LoggerFactory.getLogger('auth-session');
38
38
  this.platform = platform;
39
39
  this.authToken = authToken;
40
40
  this.settings = settings;
@@ -72,7 +72,7 @@ class AuthSession {
72
72
  headers.set('PA-Signature', signature.signature);
73
73
  }
74
74
  this.platform
75
- .fetch(this.backendUrl + query, {
75
+ .fetch(this.backendOrigin + query, {
76
76
  mode: 'cors',
77
77
  method: method,
78
78
  headers: headers,
@@ -93,62 +93,147 @@ class AuthSession {
93
93
  .catch(reject);
94
94
  });
95
95
  }
96
- createMessageChannel(endpointPath, onClose, onError, onMessage) {
96
+ createMessageChannel(query, onClose, onError, onMessage) {
97
97
  if (!this.authToken) {
98
98
  throw new Error('Authentication token is not initialized, cannot create MessageChannel');
99
99
  }
100
100
  const KEEP_ALIVE_INTERVAL = 30000;
101
- const endpoint = this.backendUrl.replace(/^http/, 'ws');
102
- const encodedAuthToken = encodeURIComponent(this.authToken);
103
- const channel = this.platform.createMessageChannel(endpoint + endpointPath + '?token=' + encodedAuthToken);
104
- const log = logger_1.LoggerFactory.getLogger('web-message-channel');
101
+ const endpoint = this.backendOrigin.replace(/^http/, 'ws');
102
+ const channel = this.platform.createMessageChannel(endpoint + query);
103
+ var pongReceived = true;
105
104
  const keepAlive = setInterval(() => {
106
- log.debug('Sending keep-alive message');
107
- channel.send('');
108
- }, KEEP_ALIVE_INTERVAL);
109
- channel.addEventListener('close', (_) => {
110
- if (keepAlive) {
105
+ if (pongReceived) {
106
+ this.log.trace('Sending ping message');
107
+ pongReceived = false;
108
+ channel.send('ping');
109
+ }
110
+ else {
111
+ this.log.error('Failed to receive ping response in time, closing the channel');
111
112
  clearInterval(keepAlive);
113
+ channel.close();
114
+ onError('Channel communication stalled');
115
+ this.channels.delete(channel);
112
116
  }
117
+ }, KEEP_ALIVE_INTERVAL);
118
+ channel.addEventListener('close', (_) => {
119
+ clearInterval(keepAlive);
113
120
  onClose();
121
+ this.channels.delete(channel);
114
122
  });
115
123
  channel.addEventListener('error', (event) => {
124
+ clearInterval(keepAlive);
116
125
  if ('message' in event) {
117
126
  onError(event['message']);
118
127
  }
119
128
  else {
120
129
  onError(event.toString());
121
130
  }
131
+ this.channels.delete(channel);
122
132
  });
123
133
  channel.addEventListener('message', (event) => {
124
134
  if ('origin' in event && event['origin'] !== endpoint) {
125
135
  onError('Unexpected origin');
126
136
  }
127
137
  else {
128
- var data = event.data;
138
+ const data = event.data;
129
139
  if (data && typeof data === 'string') {
130
- onMessage(data);
140
+ if (data === 'pong') {
141
+ pongReceived = true;
142
+ }
143
+ else {
144
+ onMessage(data);
145
+ }
131
146
  }
132
147
  else {
133
148
  onMessage(event.toString());
134
149
  }
135
150
  }
136
151
  });
152
+ this.channels.add(channel);
137
153
  return channel;
138
154
  }
155
+ closeAllMessageChannels() {
156
+ const channelsCopy = new Set(this.channels);
157
+ channelsCopy.forEach((channel) => channel.close());
158
+ channelsCopy.clear();
159
+ this.channels.clear();
160
+ }
139
161
  getDeviceRegistration() {
140
162
  return new Promise((resolve, reject) => {
141
163
  this.platform.deviceAuth
142
164
  .getRegistration(this.namespace)
143
165
  .then((registration) => {
144
166
  if (registration) {
145
- this.backendUrlOverride = registration === null || registration === void 0 ? void 0 : registration.endpoint;
167
+ if (!this.backendOriginOverride) {
168
+ this.backendOriginOverride = registration.endpoint;
169
+ this.log.debug('backend URL overridden with ' + this.backendOriginOverride);
170
+ }
171
+ else {
172
+ this.log.debug('Not overriding backend URL since it has been already set');
173
+ }
146
174
  }
147
175
  resolve(registration);
148
176
  })
149
177
  .catch(reject);
150
178
  });
151
179
  }
180
+ embedFpResultToDeviceRegistration(registration) {
181
+ return new Promise((resolve) => {
182
+ this.getFingerprintData()
183
+ .then((result) => {
184
+ if (result) {
185
+ registration.setFpSignal(result);
186
+ }
187
+ resolve(registration);
188
+ })
189
+ .catch((error) => {
190
+ const errorMsg = `Unexpected error happened during Fingerprint data collection: ${error.toString}`;
191
+ this.log.warn(errorMsg);
192
+ registration.setFpSignal({ error: errorMsg });
193
+ });
194
+ });
195
+ }
196
+ getFingerprintData() {
197
+ return new Promise((resolve) => {
198
+ var fpPromise = this.platform.getFpPromise();
199
+ if (!this.shouldCollectFP()) {
200
+ this.log.debug('Fingerprint is not enabled from AuthToken');
201
+ resolve(undefined);
202
+ }
203
+ else if (!fpPromise) {
204
+ const msg = 'Found null instance of Fingerprint, check if your input API key is valid';
205
+ this.log.warn(msg);
206
+ resolve({ error: msg });
207
+ }
208
+ else {
209
+ fpPromise
210
+ .then((fp) => fp.get())
211
+ .then((result) => {
212
+ if (result.sealedResult) {
213
+ this.log.debug(`FP result: ${result.sealedResult}`);
214
+ resolve({ results: result.sealedResult });
215
+ }
216
+ else {
217
+ const msg = 'Cannot found sealed result in Fingerprint returned payload';
218
+ this.log.warn(msg);
219
+ resolve({ error: msg });
220
+ }
221
+ })
222
+ .catch((error) => {
223
+ const msg = `Error in collecting Fingerprint data: ${error.toString}`;
224
+ this.log.warn(msg);
225
+ resolve({ error: msg });
226
+ });
227
+ }
228
+ });
229
+ }
230
+ shouldCollectFP() {
231
+ var _a, _b, _c;
232
+ if ((_c = (_b = (_a = this.claims) === null || _a === void 0 ? void 0 : _a.auth.subs.dev) === null || _b === void 0 ? void 0 : _b.sgnls) === null || _c === void 0 ? void 0 : _c.fpt) {
233
+ return true;
234
+ }
235
+ return false;
236
+ }
152
237
  parseJwt(token) {
153
238
  return JSON.parse(atob(token.split('.')[1]));
154
239
  }
@@ -0,0 +1,5 @@
1
+ import AuthSession from './auth-session';
2
+ export declare class AuthStatusActions {
3
+ protected log: import("../common/logger").Logger;
4
+ protected waitForStatus(session: AuthSession): Promise<string>;
5
+ }
@@ -0,0 +1,48 @@
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.AuthStatusActions = void 0;
7
+ const logger_1 = require("../common/logger");
8
+ const auth_error_1 = __importDefault(require("./auth-error"));
9
+ class AuthStatusActions {
10
+ constructor() {
11
+ this.log = logger_1.LoggerFactory.getLogger('auth-status-actions');
12
+ }
13
+ waitForStatus(session) {
14
+ var gotResponse = false;
15
+ this.log.trace('Waiting for auth status');
16
+ return new Promise((resolve, reject) => {
17
+ const channel = session.createMessageChannel('/v1/client/status?token=' + encodeURIComponent(session.authToken), () => {
18
+ if (!gotResponse) {
19
+ reject(new auth_error_1.default('Failed to receive secondary authentication status, no response'));
20
+ }
21
+ }, (errorMessage) => {
22
+ gotResponse = true;
23
+ this.log.error('Failed: ' + errorMessage);
24
+ reject(new auth_error_1.default('Failed to receive secondary authentication status: ' + errorMessage));
25
+ }, (data) => {
26
+ gotResponse = true;
27
+ try {
28
+ this.log.debug(('Secondary authentication status: ' + data));
29
+ const response = JSON.parse(data);
30
+ if (response.error) {
31
+ reject(new auth_error_1.default(response.error.message, response.error.code, response.next));
32
+ }
33
+ else {
34
+ session.lastStep = response.next;
35
+ resolve(response.next);
36
+ }
37
+ }
38
+ catch (e) {
39
+ reject(e);
40
+ }
41
+ finally {
42
+ channel.close();
43
+ }
44
+ });
45
+ });
46
+ }
47
+ }
48
+ exports.AuthStatusActions = AuthStatusActions;
@@ -16,14 +16,23 @@ export interface InstantLinkAuthenticator {
16
16
  export interface OtpAuthenticator {
17
17
  mnp: boolean;
18
18
  }
19
+ export interface UniversalAuthenticator {
20
+ endp: string;
21
+ ftu: string;
22
+ }
19
23
  export interface Authenticators {
20
24
  pasv?: PassiveAuthenticator;
21
25
  inst?: InstantAuthenticator;
22
26
  inln?: InstantLinkAuthenticator;
23
27
  otp?: OtpAuthenticator;
28
+ unvsl?: UniversalAuthenticator;
29
+ }
30
+ export interface Signals {
31
+ fpt?: boolean;
24
32
  }
25
33
  export interface DeviceAuthSubjectClaim {
26
34
  auths: Authenticators;
35
+ sgnls?: Signals;
27
36
  }
28
37
  export interface MobileAuthSubjectClaim {
29
38
  auths: Authenticators;