@prove-identity/prove-auth 2.4.5 → 2.7.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.
- package/README.md +35 -0
- package/build/lib/index.d.ts +3 -1
- package/build/lib/index.js +3 -1
- package/build/lib/proveauth/authenticator-builder.d.ts +12 -2
- package/build/lib/proveauth/authenticator-builder.js +114 -7
- package/build/lib/proveauth/device-context-options.d.ts +19 -0
- package/build/lib/proveauth/device-context-options.js +19 -0
- package/build/lib/proveauth/internal/auth-request.d.ts +12 -0
- package/build/lib/proveauth/internal/auth-response.d.ts +1 -0
- package/build/lib/proveauth/internal/auth-session.d.ts +12 -8
- package/build/lib/proveauth/internal/auth-session.js +94 -20
- package/build/lib/proveauth/internal/auth-token-claims.d.ts +4 -0
- package/build/lib/proveauth/internal/device-auth.d.ts +4 -1
- package/build/lib/proveauth/internal/device-passive-register-step.js +10 -9
- package/build/lib/proveauth/internal/device-passive-silent-step.d.ts +5 -3
- package/build/lib/proveauth/internal/device-passive-silent-step.js +30 -11
- package/build/lib/proveauth/internal/device-passive-verify-step.d.ts +2 -0
- package/build/lib/proveauth/internal/device-passive-verify-step.js +18 -0
- package/build/lib/proveauth/internal/device-universal-redirect-steps.js +2 -2
- package/build/lib/proveauth/internal/main-authenticator.d.ts +2 -3
- package/build/lib/proveauth/internal/main-authenticator.js +3 -10
- package/build/lib/proveauth/internal/mobile-instantlink-step.js +6 -4
- package/build/lib/proveauth/internal/platform.d.ts +5 -1
- package/build/lib/proveauth/internal/report-error-step.d.ts +2 -2
- package/build/lib/proveauth/internal/report-error-step.js +5 -5
- package/build/lib/proveauth/internal/settings.d.ts +1 -0
- package/build/lib/proveauth/internal/settings.js +1 -0
- package/build/lib/proveauth/internal/web-device-auth.d.ts +4 -1
- package/build/lib/proveauth/internal/web-device-auth.js +6 -0
- package/build/lib/proveauth/internal/web-platform.d.ts +7 -1
- package/build/lib/proveauth/internal/web-platform.js +11 -2
- package/build/lib/proveauth/user-consent-step.d.ts +7 -0
- package/build/lib/proveauth/user-consent-step.js +2 -0
- package/build/lib/proveauth/version.d.ts +2 -2
- package/build/lib/proveauth/version.js +2 -2
- package/package.json +9 -1
- package/build/bundle/release/prove-auth.js +0 -1
package/README.md
CHANGED
|
@@ -15,3 +15,38 @@ This SDK provides JavaScript client API to the Prove's authentication platform P
|
|
|
15
15
|
- Build the sdk first, then build the sample code:
|
|
16
16
|
- Build SDK web bundle - `npm run clean && npm run build && npm run bundle-dev`
|
|
17
17
|
- Build and start sample code - `cd samples/basic; npm run build && npm run serve`
|
|
18
|
+
|
|
19
|
+
## Running Unit Tests
|
|
20
|
+
|
|
21
|
+
This project provides several options for running unit tests. Follow these instructions to execute the tests:
|
|
22
|
+
|
|
23
|
+
### Standard Test Run
|
|
24
|
+
|
|
25
|
+
To run the standard test suite:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
npm test
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This command will execute all unit tests and display the results in your default web browser.
|
|
32
|
+
|
|
33
|
+
### Running Tests with Node
|
|
34
|
+
|
|
35
|
+
If you need to run tests in a Node.js environment:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
npm run test-with-node
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This command will execute all unit tests and display the results in your terminal.
|
|
42
|
+
|
|
43
|
+
### Using the Test Runner
|
|
44
|
+
|
|
45
|
+
To run integration tests using Test Runner:
|
|
46
|
+
|
|
47
|
+
npm run test-runner
|
|
48
|
+
|
|
49
|
+
This command uses Test Runner client to execute integration tests enabled for the Web SDK.
|
|
50
|
+
Execution of integration tests depends on the Test Runner server components, which are part of
|
|
51
|
+
(Garfield backend service)[https://gitlab.com/prove-identity/prove-auth/garfield], and must be
|
|
52
|
+
started in advance using `make test-localhost-up` command in that repo.
|
package/build/lib/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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, };
|
package/build/lib/index.js
CHANGED
|
@@ -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,9 +29,12 @@ export default class AuthenticatorBuilder {
|
|
|
26
29
|
private otpStartStep?;
|
|
27
30
|
private otpFinishStep?;
|
|
28
31
|
private instantLinkStartStep?;
|
|
29
|
-
private
|
|
30
|
-
private
|
|
32
|
+
private upkEnabled;
|
|
33
|
+
private userConsentStep?;
|
|
34
|
+
private readonly log;
|
|
35
|
+
private deviceContextOptions?;
|
|
31
36
|
constructor();
|
|
37
|
+
withDeviceContext(options: DeviceContextOptions): AuthenticatorBuilder;
|
|
32
38
|
withAuthFinishStep(step: AuthFinishStep | AuthFinishStepFn): AuthenticatorBuilder;
|
|
33
39
|
withDisplayName(displayName: string | (() => string | null) | null): AuthenticatorBuilder;
|
|
34
40
|
withAuthMessageHandler(handler: AuthMessageHandler): AuthenticatorBuilder;
|
|
@@ -40,5 +46,9 @@ export default class AuthenticatorBuilder {
|
|
|
40
46
|
withOtpFallback(startStep: OtpStartStep | OtpStartStepFn, finishStep: OtpFinishStep | OtpFinishStepFn): AuthenticatorBuilder;
|
|
41
47
|
withInstantLinkFallback(startStep: InstantLinkStartStep | InstantLinkStartStepFn): AuthenticatorBuilder;
|
|
42
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;
|
|
43
53
|
build(): Authenticator;
|
|
44
54
|
}
|
|
@@ -18,6 +18,9 @@ const device_passive_stepup_step_1 = __importDefault(require("./internal/device-
|
|
|
18
18
|
const device_universal_step_1 = __importDefault(require("./internal/device-universal-step"));
|
|
19
19
|
const device_universal_redirect_steps_1 = require("./internal/device-universal-redirect-steps");
|
|
20
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");
|
|
21
24
|
var DeviceRole;
|
|
22
25
|
(function (DeviceRole) {
|
|
23
26
|
DeviceRole[DeviceRole["Primary"] = 0] = "Primary";
|
|
@@ -32,13 +35,17 @@ class AuthenticatorBuilder {
|
|
|
32
35
|
constructor() {
|
|
33
36
|
this.role = DeviceRole.Primary;
|
|
34
37
|
this.mobileAuthImplementation = MobileAuthImplementation.Fetch;
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
38
|
+
this.upkEnabled = false;
|
|
39
|
+
this.log = logger_1.LoggerFactory.getLogger('authenticator-builder');
|
|
37
40
|
if (typeof window !== 'undefined') {
|
|
38
41
|
this.storage = window.localStorage;
|
|
39
42
|
this.platform = new web_platform_1.WebPlatform();
|
|
40
43
|
}
|
|
41
44
|
}
|
|
45
|
+
withDeviceContext(options) {
|
|
46
|
+
this.deviceContextOptions = options;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
42
49
|
withAuthFinishStep(step) {
|
|
43
50
|
if (typeof step === 'function') {
|
|
44
51
|
this.authFinishStep = {
|
|
@@ -103,18 +110,118 @@ class AuthenticatorBuilder {
|
|
|
103
110
|
return this;
|
|
104
111
|
}
|
|
105
112
|
withUPKEnabled() {
|
|
106
|
-
this.
|
|
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;
|
|
107
126
|
return this;
|
|
108
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
|
+
}
|
|
109
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;
|
|
110
217
|
if (this.role === DeviceRole.Primary) {
|
|
111
|
-
return new main_authenticator_1.default(this.platform,
|
|
112
|
-
new device_universal_step_1.default(this.
|
|
218
|
+
return new main_authenticator_1.default(this.platform, settings, this.authFinishStep, [
|
|
219
|
+
new device_universal_step_1.default(this.upkEnabled),
|
|
113
220
|
new device_universal_redirect_steps_1.DeviceUniversalRedirectExchangeStep(),
|
|
114
221
|
new device_universal_redirect_steps_1.DeviceUniversalRedirectFinishStep(),
|
|
115
222
|
new device_passive_step_1.default(this.getDisplayName, this.role),
|
|
116
223
|
new device_passive_stepup_step_1.default(this.getDisplayName),
|
|
117
|
-
new device_passive_silent_step_1.default(this.
|
|
224
|
+
new device_passive_silent_step_1.default(this.upkEnabled, this.userConsentStep),
|
|
118
225
|
new device_passive_register_step_1.default(),
|
|
119
226
|
new device_passive_verify_step_1.default(),
|
|
120
227
|
new mobile_instant_step_1.default(this.mobileAuthImplementation, this.getDeviceIp),
|
|
@@ -125,7 +232,7 @@ class AuthenticatorBuilder {
|
|
|
125
232
|
]);
|
|
126
233
|
}
|
|
127
234
|
else {
|
|
128
|
-
return new main_authenticator_1.default(this.platform,
|
|
235
|
+
return new main_authenticator_1.default(this.platform, settings, this.authFinishStep, [
|
|
129
236
|
new device_passive_step_1.default(this.getDisplayName, this.role),
|
|
130
237
|
new mobile_instant_step_1.default(this.mobileAuthImplementation, this.getDeviceIp),
|
|
131
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';
|
|
@@ -13,20 +13,24 @@ export default class AuthSession implements AuthSessionIntegration {
|
|
|
13
13
|
readonly settings: Settings;
|
|
14
14
|
readonly requestSigner: RequestSigner;
|
|
15
15
|
readonly channels: Set<MessageChannel>;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
private readonly log;
|
|
17
|
+
lastStep?: string;
|
|
18
|
+
credential?: CredentialType;
|
|
19
|
+
authMessage?: AuthMessage;
|
|
20
|
+
uvLevel?: UserVerificationLevel;
|
|
21
|
+
backendOriginOverride?: string;
|
|
21
22
|
get namespace(): string;
|
|
22
|
-
get
|
|
23
|
+
get backendOrigin(): string;
|
|
23
24
|
get authId(): string;
|
|
24
25
|
get challenge(): string;
|
|
25
26
|
get next(): string;
|
|
26
27
|
constructor(settings: Settings, platform: Platform, authToken?: string);
|
|
27
28
|
fetchFromBackend(query: string, body: AuthRequest): Promise<AuthResponse>;
|
|
28
|
-
createMessageChannel(
|
|
29
|
+
createMessageChannel(query: string, onClose: () => void, onError: (message: string) => void, onMessage: (data: string) => void): MessageChannel;
|
|
29
30
|
closeAllMessageChannels(): void;
|
|
30
31
|
getDeviceRegistration(): Promise<DeviceRegistration | null>;
|
|
32
|
+
embedFpResultToDeviceRegistration(registration: DeviceRegistration): Promise<DeviceRegistration>;
|
|
33
|
+
getFingerprintData(): Promise<Signal | undefined>;
|
|
34
|
+
shouldCollectFP(): boolean;
|
|
31
35
|
private parseJwt;
|
|
32
36
|
}
|
|
@@ -12,9 +12,9 @@ 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
|
|
15
|
+
get backendOrigin() {
|
|
16
16
|
var _a;
|
|
17
|
-
return ((_a = this.claims) === null || _a === void 0 ? void 0 : _a.auth.endp)
|
|
17
|
+
return this.backendOriginOverride || ((_a = this.claims) === null || _a === void 0 ? void 0 : _a.auth.endp);
|
|
18
18
|
}
|
|
19
19
|
get authId() {
|
|
20
20
|
var _a;
|
|
@@ -31,11 +31,7 @@ class AuthSession {
|
|
|
31
31
|
constructor(settings, platform, authToken) {
|
|
32
32
|
var _a, _b;
|
|
33
33
|
this.channels = new Set();
|
|
34
|
-
this.
|
|
35
|
-
this.credential = null;
|
|
36
|
-
this.authMessage = null;
|
|
37
|
-
this.uvLevel = null;
|
|
38
|
-
this.backendUrlOverride = null;
|
|
34
|
+
this.log = logger_1.LoggerFactory.getLogger('auth-session');
|
|
39
35
|
this.platform = platform;
|
|
40
36
|
this.authToken = authToken;
|
|
41
37
|
this.settings = settings;
|
|
@@ -73,7 +69,7 @@ class AuthSession {
|
|
|
73
69
|
headers.set('PA-Signature', signature.signature);
|
|
74
70
|
}
|
|
75
71
|
this.platform
|
|
76
|
-
.fetch(this.
|
|
72
|
+
.fetch(this.backendOrigin + query, {
|
|
77
73
|
mode: 'cors',
|
|
78
74
|
method: method,
|
|
79
75
|
headers: headers,
|
|
@@ -94,41 +90,56 @@ class AuthSession {
|
|
|
94
90
|
.catch(reject);
|
|
95
91
|
});
|
|
96
92
|
}
|
|
97
|
-
createMessageChannel(
|
|
93
|
+
createMessageChannel(query, onClose, onError, onMessage) {
|
|
98
94
|
if (!this.authToken) {
|
|
99
95
|
throw new Error('Authentication token is not initialized, cannot create MessageChannel');
|
|
100
96
|
}
|
|
101
97
|
const KEEP_ALIVE_INTERVAL = 30000;
|
|
102
|
-
const endpoint = this.
|
|
103
|
-
const channel = this.platform.createMessageChannel(endpoint +
|
|
104
|
-
|
|
98
|
+
const endpoint = this.backendOrigin.replace(/^http/, 'ws');
|
|
99
|
+
const channel = this.platform.createMessageChannel(endpoint + query);
|
|
100
|
+
var pongReceived = true;
|
|
105
101
|
const keepAlive = setInterval(() => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
if (pongReceived) {
|
|
103
|
+
this.log.trace('Sending ping message');
|
|
104
|
+
pongReceived = false;
|
|
105
|
+
channel.send('ping');
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.log.error('Failed to receive ping response in time, closing the channel');
|
|
111
109
|
clearInterval(keepAlive);
|
|
110
|
+
channel.close();
|
|
111
|
+
onError('Channel communication stalled');
|
|
112
|
+
this.channels.delete(channel);
|
|
112
113
|
}
|
|
114
|
+
}, KEEP_ALIVE_INTERVAL);
|
|
115
|
+
channel.addEventListener('close', (_) => {
|
|
116
|
+
clearInterval(keepAlive);
|
|
113
117
|
onClose();
|
|
114
118
|
this.channels.delete(channel);
|
|
115
119
|
});
|
|
116
120
|
channel.addEventListener('error', (event) => {
|
|
121
|
+
clearInterval(keepAlive);
|
|
117
122
|
if ('message' in event) {
|
|
118
123
|
onError(event['message']);
|
|
119
124
|
}
|
|
120
125
|
else {
|
|
121
126
|
onError(event.toString());
|
|
122
127
|
}
|
|
128
|
+
this.channels.delete(channel);
|
|
123
129
|
});
|
|
124
130
|
channel.addEventListener('message', (event) => {
|
|
125
131
|
if ('origin' in event && event['origin'] !== endpoint) {
|
|
126
132
|
onError('Unexpected origin');
|
|
127
133
|
}
|
|
128
134
|
else {
|
|
129
|
-
|
|
135
|
+
const data = event.data;
|
|
130
136
|
if (data && typeof data === 'string') {
|
|
131
|
-
|
|
137
|
+
if (data === 'pong') {
|
|
138
|
+
pongReceived = true;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
onMessage(data);
|
|
142
|
+
}
|
|
132
143
|
}
|
|
133
144
|
else {
|
|
134
145
|
onMessage(event.toString());
|
|
@@ -150,13 +161,76 @@ class AuthSession {
|
|
|
150
161
|
.getRegistration(this.namespace)
|
|
151
162
|
.then((registration) => {
|
|
152
163
|
if (registration) {
|
|
153
|
-
this.
|
|
164
|
+
if (!this.backendOriginOverride) {
|
|
165
|
+
this.backendOriginOverride = registration.endpoint;
|
|
166
|
+
this.log.debug('backend URL overridden with ' + this.backendOriginOverride);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this.log.debug('Not overriding backend URL since it has been already set');
|
|
170
|
+
}
|
|
154
171
|
}
|
|
155
172
|
resolve(registration);
|
|
156
173
|
})
|
|
157
174
|
.catch(reject);
|
|
158
175
|
});
|
|
159
176
|
}
|
|
177
|
+
embedFpResultToDeviceRegistration(registration) {
|
|
178
|
+
return new Promise((resolve) => {
|
|
179
|
+
this.getFingerprintData()
|
|
180
|
+
.then((result) => {
|
|
181
|
+
if (result) {
|
|
182
|
+
registration.setFpSignal(result);
|
|
183
|
+
}
|
|
184
|
+
resolve(registration);
|
|
185
|
+
})
|
|
186
|
+
.catch((error) => {
|
|
187
|
+
const errorMsg = `Unexpected error happened during Fingerprint data collection: ${error.toString}`;
|
|
188
|
+
this.log.warn(errorMsg);
|
|
189
|
+
registration.setFpSignal({ error: errorMsg });
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
getFingerprintData() {
|
|
194
|
+
return new Promise((resolve) => {
|
|
195
|
+
var fpPromise = this.platform.getFpPromise();
|
|
196
|
+
if (!this.shouldCollectFP()) {
|
|
197
|
+
this.log.debug('Fingerprint is not enabled from AuthToken');
|
|
198
|
+
resolve(undefined);
|
|
199
|
+
}
|
|
200
|
+
else if (!fpPromise) {
|
|
201
|
+
const msg = 'Found null instance of Fingerprint, check if your input API key is valid';
|
|
202
|
+
this.log.warn(msg);
|
|
203
|
+
resolve({ error: msg });
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
fpPromise
|
|
207
|
+
.then((fp) => fp.get())
|
|
208
|
+
.then((result) => {
|
|
209
|
+
if (result.sealedResult) {
|
|
210
|
+
this.log.debug(`FP result: ${result.sealedResult}`);
|
|
211
|
+
resolve({ results: result.sealedResult });
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
const msg = 'Cannot found sealed result in Fingerprint returned payload';
|
|
215
|
+
this.log.warn(msg);
|
|
216
|
+
resolve({ error: msg });
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
.catch((error) => {
|
|
220
|
+
const msg = `Error in collecting Fingerprint data: ${error.toString}`;
|
|
221
|
+
this.log.warn(msg);
|
|
222
|
+
resolve({ error: msg });
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
shouldCollectFP() {
|
|
228
|
+
var _a, _b, _c;
|
|
229
|
+
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) {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
160
234
|
parseJwt(token) {
|
|
161
235
|
return JSON.parse(atob(token.split('.')[1]));
|
|
162
236
|
}
|
|
@@ -27,8 +27,12 @@ export interface Authenticators {
|
|
|
27
27
|
otp?: OtpAuthenticator;
|
|
28
28
|
unvsl?: UniversalAuthenticator;
|
|
29
29
|
}
|
|
30
|
+
export interface Signals {
|
|
31
|
+
fpt?: boolean;
|
|
32
|
+
}
|
|
30
33
|
export interface DeviceAuthSubjectClaim {
|
|
31
34
|
auths: Authenticators;
|
|
35
|
+
sgnls?: Signals;
|
|
32
36
|
}
|
|
33
37
|
export interface MobileAuthSubjectClaim {
|
|
34
38
|
auths: Authenticators;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthRegistration } from './auth-request';
|
|
1
|
+
import { AuthRegistration, Signal, Signals } from './auth-request';
|
|
2
2
|
export interface DeviceRegistrationOptions {
|
|
3
3
|
namespace: string;
|
|
4
4
|
endpoint: string;
|
|
@@ -9,9 +9,12 @@ export interface DeviceRegistration {
|
|
|
9
9
|
readonly algorithm: string;
|
|
10
10
|
readonly endpoint: string;
|
|
11
11
|
deviceId: string | null;
|
|
12
|
+
fingerprint?: Signal;
|
|
12
13
|
sign: (data: string) => Promise<string>;
|
|
13
14
|
getPublicKey: () => Promise<string>;
|
|
14
15
|
getAuthRegistration: (challenge: string) => Promise<AuthRegistration>;
|
|
16
|
+
setFpSignal: (fpSignal: Signal) => void;
|
|
17
|
+
getSignals: () => Signals | undefined;
|
|
15
18
|
}
|
|
16
19
|
export default interface DeviceAuth {
|
|
17
20
|
createRegistration: (options: DeviceRegistrationOptions) => Promise<DeviceRegistration>;
|
|
@@ -18,23 +18,23 @@ class DevicePassiveRegisterStep {
|
|
|
18
18
|
.getDeviceRegistration()
|
|
19
19
|
.then((devRegistration) => {
|
|
20
20
|
if (devRegistration) {
|
|
21
|
-
|
|
22
|
-
.
|
|
23
|
-
|
|
21
|
+
session.embedFpResultToDeviceRegistration(devRegistration).then((devRegistration) => {
|
|
22
|
+
this.finishRegistration(session, [this.getFido2Registration(session)], devRegistration.getSignals())
|
|
23
|
+
.then(resolve)
|
|
24
|
+
.catch(reject);
|
|
25
|
+
});
|
|
24
26
|
}
|
|
25
27
|
else {
|
|
26
28
|
session.platform.deviceAuth
|
|
27
29
|
.createRegistration({
|
|
28
30
|
namespace: session.namespace,
|
|
29
|
-
endpoint: session.
|
|
31
|
+
endpoint: session.backendOrigin,
|
|
30
32
|
})
|
|
33
|
+
.then((devRegistration) => session.embedFpResultToDeviceRegistration(devRegistration))
|
|
31
34
|
.then((devRegistration) => {
|
|
32
35
|
devRegistration
|
|
33
36
|
.getAuthRegistration(session.challenge)
|
|
34
|
-
.then((authRegistration) => this.finishRegistration(session, [
|
|
35
|
-
this.getFido2Registration(session),
|
|
36
|
-
authRegistration,
|
|
37
|
-
]))
|
|
37
|
+
.then((authRegistration) => this.finishRegistration(session, [this.getFido2Registration(session), authRegistration], devRegistration.getSignals()))
|
|
38
38
|
.then((next) => {
|
|
39
39
|
devRegistration.deviceId = session.settings.deviceId;
|
|
40
40
|
session.platform.deviceAuth
|
|
@@ -50,13 +50,14 @@ class DevicePassiveRegisterStep {
|
|
|
50
50
|
.catch(reject);
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
|
-
finishRegistration(session, registrations) {
|
|
53
|
+
finishRegistration(session, registrations, signals) {
|
|
54
54
|
return new Promise((resolve, reject) => {
|
|
55
55
|
session
|
|
56
56
|
.fetchFromBackend('/v1/client/device/fido2/register/finish', {
|
|
57
57
|
deviceName: session.platform.getPlatformName(),
|
|
58
58
|
deviceCapabilities: session.platform.getDeviceCapabilities(),
|
|
59
59
|
registrations: registrations,
|
|
60
|
+
signals: signals,
|
|
60
61
|
})
|
|
61
62
|
.then((response) => {
|
|
62
63
|
if (response.error) {
|