@prove-identity/prove-auth 2.14.0 → 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.
- package/build/bundle/release/prove-auth.js +1 -1
- package/build/lib/index.d.ts +3 -2
- package/build/lib/index.js +1 -2
- package/build/lib/proveauth/authenticator-builder.d.ts +5 -0
- package/build/lib/proveauth/authenticator-builder.js +25 -2
- package/build/lib/proveauth/external/@authid/web-component/authid-web-component.d.ts +3 -0
- package/build/lib/proveauth/external/@authid/web-component/authid-web-component.js +55 -0
- package/build/lib/proveauth/instantlink.d.ts +2 -6
- package/build/lib/proveauth/instantlink.js +1 -11
- package/build/lib/proveauth/internal/auth-request.d.ts +5 -1
- package/build/lib/proveauth/internal/auth-response.d.ts +24 -28
- package/build/lib/proveauth/internal/auth-session.d.ts +2 -1
- package/build/lib/proveauth/internal/auth-session.js +1 -0
- package/build/lib/proveauth/internal/auth-token-claims.d.ts +21 -3
- package/build/lib/proveauth/internal/device-passive-silent-step.js +5 -6
- package/build/lib/proveauth/internal/device-passive-step.js +7 -5
- package/build/lib/proveauth/internal/mobile-instant-step.js +2 -2
- package/build/lib/proveauth/internal/mobile-instantlink-step.d.ts +0 -3
- package/build/lib/proveauth/internal/mobile-instantlink-step.js +22 -122
- package/build/lib/proveauth/internal/mobile-otp-step.js +3 -3
- package/build/lib/proveauth/internal/platform.d.ts +11 -0
- package/build/lib/proveauth/internal/report-error-step.js +5 -2
- package/build/lib/proveauth/internal/user-mobileactive-step.js +1 -3
- package/build/lib/proveauth/internal/user-ppb-steps.d.ts +24 -0
- package/build/lib/proveauth/internal/user-ppb-steps.js +103 -0
- package/build/lib/proveauth/internal/user-present-step.js +1 -3
- package/build/lib/proveauth/internal/web-platform.d.ts +3 -1
- package/build/lib/proveauth/internal/web-platform.js +101 -0
- package/build/lib/proveauth/ppb.d.ts +9 -0
- package/build/lib/proveauth/ppb.js +2 -0
- package/build/lib/proveauth/version.d.ts +2 -2
- package/build/lib/proveauth/version.js +2 -2
- package/package.json +1 -1
|
@@ -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.
|
|
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
|
|
56
|
+
const data = authResponse.data;
|
|
57
|
+
const errorCode = data.code;
|
|
94
58
|
var errorMessage = '';
|
|
95
59
|
if (errorCode) {
|
|
96
|
-
errorMessage += `Error Code: ${
|
|
60
|
+
errorMessage += `Error Code: ${errorCode}, `;
|
|
97
61
|
}
|
|
98
|
-
if (
|
|
99
|
-
|
|
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
|
-
|
|
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.
|
|
128
|
-
.then(()
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
|
92
|
+
runRetryStep(session) {
|
|
150
93
|
return new Promise((resolve, reject) => {
|
|
151
94
|
if (this.retryStep) {
|
|
152
95
|
this.retryStep
|
|
153
|
-
.execute(
|
|
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.
|
|
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('
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
[
|
|
90
|
-
[
|
|
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;
|
|
@@ -9,9 +9,7 @@ class UserMobileActiveStep {
|
|
|
9
9
|
this.name = UserMobileActiveStep.NAME;
|
|
10
10
|
}
|
|
11
11
|
execute(session) {
|
|
12
|
-
return new
|
|
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
|
|
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;
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -6,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
15
|
exports.WebPlatform = exports.WebSocketMessageChannel = void 0;
|
|
7
16
|
const mobile_auth_1 = require("@prove-identity/mobile-auth");
|
|
8
17
|
const platform_1 = require("./platform");
|
|
18
|
+
const logger_1 = require("../common/logger");
|
|
9
19
|
const request_signer_v3_1 = __importDefault(require("./request-signer-v3"));
|
|
10
20
|
const web_device_auth_1 = __importDefault(require("./web-device-auth"));
|
|
11
21
|
class WebSocketMessageChannel {
|
|
@@ -25,6 +35,7 @@ class WebSocketMessageChannel {
|
|
|
25
35
|
exports.WebSocketMessageChannel = WebSocketMessageChannel;
|
|
26
36
|
class WebPlatform {
|
|
27
37
|
constructor() {
|
|
38
|
+
this.log = logger_1.LoggerFactory.getLogger('web-platform');
|
|
28
39
|
this.webauthn = {
|
|
29
40
|
getCredentials: (options) => {
|
|
30
41
|
return navigator.credentials.get(options);
|
|
@@ -53,6 +64,96 @@ class WebPlatform {
|
|
|
53
64
|
createRequestSigner(session) {
|
|
54
65
|
return new request_signer_v3_1.default(session);
|
|
55
66
|
}
|
|
67
|
+
ppbAuthenticate(options) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const operationMap = new Map([
|
|
70
|
+
['enroll', 'i'],
|
|
71
|
+
['verify', 't'],
|
|
72
|
+
]);
|
|
73
|
+
if (!options.authIdEndpointUrl) {
|
|
74
|
+
return Promise.reject('AuthID API endpoint URL is missing');
|
|
75
|
+
}
|
|
76
|
+
if (!options.authIdOperation) {
|
|
77
|
+
return Promise.reject('AuthID API operation is missing');
|
|
78
|
+
}
|
|
79
|
+
if (!operationMap.has(options.authIdOperation)) {
|
|
80
|
+
return Promise.reject('AuthID API operation is not recognized');
|
|
81
|
+
}
|
|
82
|
+
if (!options.authIdOperationId) {
|
|
83
|
+
return Promise.reject('AuthID operation ID is missing');
|
|
84
|
+
}
|
|
85
|
+
if (!options.authIdOneTimeSecret) {
|
|
86
|
+
return Promise.reject('AuthID operation secret is missing');
|
|
87
|
+
}
|
|
88
|
+
const componentName = 'authid-component';
|
|
89
|
+
try {
|
|
90
|
+
const authId = require('../external/@authid/web-component/authid-web-component');
|
|
91
|
+
if (!authId) {
|
|
92
|
+
return Promise.reject('Failed to load PPB Auth web component');
|
|
93
|
+
}
|
|
94
|
+
if (!window.customElements.get(componentName)) {
|
|
95
|
+
window.customElements.define(componentName, authId.AuthIDComponent);
|
|
96
|
+
}
|
|
97
|
+
yield window.customElements.whenDefined(componentName);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
this.log.error(e);
|
|
101
|
+
return Promise.reject(new Error('Failed to initialize PPB Auth web component'));
|
|
102
|
+
}
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
const existingComponent = document.querySelector(componentName);
|
|
105
|
+
if (existingComponent) {
|
|
106
|
+
this.log.trace('Removing existing component', componentName);
|
|
107
|
+
existingComponent.remove();
|
|
108
|
+
}
|
|
109
|
+
const authIdComponent = document.createElement(componentName);
|
|
110
|
+
const url = `${options.authIdEndpointUrl}/?` +
|
|
111
|
+
`${operationMap.get(options.authIdOperation)}=${options.authIdOperationId}&` +
|
|
112
|
+
`s=${options.authIdOneTimeSecret}`;
|
|
113
|
+
authIdComponent.setAttribute('data-url', url);
|
|
114
|
+
document.body.appendChild(authIdComponent);
|
|
115
|
+
const handleAuthDone = (success) => __awaiter(this, void 0, void 0, function* () {
|
|
116
|
+
window.removeEventListener('message', handleMessage);
|
|
117
|
+
this.log.trace('On PPB auth done');
|
|
118
|
+
resolve({ authIdSuccess: success });
|
|
119
|
+
});
|
|
120
|
+
const handleMessage = (event) => {
|
|
121
|
+
this.log.debug('PPB event', event.data);
|
|
122
|
+
if (event.data.success) {
|
|
123
|
+
const authIdComponent = document.querySelector(componentName);
|
|
124
|
+
if (authIdComponent) {
|
|
125
|
+
authIdComponent.remove();
|
|
126
|
+
}
|
|
127
|
+
handleAuthDone(true);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
switch (event.data.pageName) {
|
|
131
|
+
case 'documentFailedPage':
|
|
132
|
+
case 'documentFailedNonMobilePage':
|
|
133
|
+
case 'networkErrorPage':
|
|
134
|
+
case 'livenessErrorPage':
|
|
135
|
+
case 'docScanWasmTimeoutPage':
|
|
136
|
+
case 'requestTimeoutPage':
|
|
137
|
+
case 'transactionNotValidPage':
|
|
138
|
+
case 'transactionMaxAttemptsPage':
|
|
139
|
+
case 'QRCodePage':
|
|
140
|
+
return;
|
|
141
|
+
case 'verifiedMatchFailPage':
|
|
142
|
+
case 'verifyDeclinedPage':
|
|
143
|
+
authIdComponent.remove();
|
|
144
|
+
case 'docScanResolutionTooLowPage':
|
|
145
|
+
case 'videoDeviceNotFoundPage':
|
|
146
|
+
case 'standardErrorPage':
|
|
147
|
+
case 'defaultFailedPage':
|
|
148
|
+
handleAuthDone(false);
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
window.addEventListener('message', handleMessage);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
56
157
|
getBrowserName() {
|
|
57
158
|
const agent = navigator.userAgent;
|
|
58
159
|
let browserName;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PpbOperation = 'enroll' | 'verify';
|
|
2
|
+
export interface PpbStartStep {
|
|
3
|
+
execute: (operation: PpbOperation) => Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
export interface PpbFinishStep {
|
|
6
|
+
execute: (operation: PpbOperation, error?: Error) => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export type PpbStartStepFn = (operation: PpbOperation) => Promise<void>;
|
|
9
|
+
export type PpbFinishStepFn = (operation: PpbOperation, error?: Error) => Promise<void>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const VERSION = "2.
|
|
2
|
-
export declare const API_CONTRACT_VERSION = "2.
|
|
1
|
+
export declare const VERSION = "2.15.1";
|
|
2
|
+
export declare const API_CONTRACT_VERSION = "2.15.1";
|
|
3
3
|
export declare const USER_AGENT_VERSIONS: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.USER_AGENT_VERSIONS = exports.API_CONTRACT_VERSION = exports.VERSION = void 0;
|
|
4
|
-
exports.VERSION = '2.
|
|
5
|
-
exports.API_CONTRACT_VERSION = '2.
|
|
4
|
+
exports.VERSION = '2.15.1';
|
|
5
|
+
exports.API_CONTRACT_VERSION = '2.15.1';
|
|
6
6
|
exports.USER_AGENT_VERSIONS = `ProveAuth/${exports.VERSION} Contract/${exports.API_CONTRACT_VERSION} WEB/1`;
|