@prove-identity/prove-auth 2.3.2
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/LICENSE +404 -0
- package/README.md +17 -0
- package/build/lib/index.d.ts +12 -0
- package/build/lib/index.js +47 -0
- package/build/lib/proveauth/auth-finish-step.d.ts +7 -0
- package/build/lib/proveauth/auth-finish-step.js +2 -0
- package/build/lib/proveauth/authenticator-builder.d.ts +42 -0
- package/build/lib/proveauth/authenticator-builder.js +126 -0
- package/build/lib/proveauth/authenticator.d.ts +12 -0
- package/build/lib/proveauth/authenticator.js +2 -0
- package/build/lib/proveauth/common/base64.d.ts +5 -0
- package/build/lib/proveauth/common/base64.js +19 -0
- package/build/lib/proveauth/common/cancelable-promise.d.ts +5 -0
- package/build/lib/proveauth/common/cancelable-promise.js +15 -0
- package/build/lib/proveauth/common/logger.d.ts +25 -0
- package/build/lib/proveauth/common/logger.js +85 -0
- package/build/lib/proveauth/instantlink.d.ts +4 -0
- package/build/lib/proveauth/instantlink.js +2 -0
- package/build/lib/proveauth/internal/auth-error.d.ts +7 -0
- package/build/lib/proveauth/internal/auth-error.js +27 -0
- package/build/lib/proveauth/internal/auth-message.d.ts +12 -0
- package/build/lib/proveauth/internal/auth-message.js +2 -0
- package/build/lib/proveauth/internal/auth-request.d.ts +90 -0
- package/build/lib/proveauth/internal/auth-request.js +2 -0
- package/build/lib/proveauth/internal/auth-response-status.d.ts +8 -0
- package/build/lib/proveauth/internal/auth-response-status.js +12 -0
- package/build/lib/proveauth/internal/auth-response.d.ts +61 -0
- package/build/lib/proveauth/internal/auth-response.js +2 -0
- package/build/lib/proveauth/internal/auth-session.d.ts +30 -0
- package/build/lib/proveauth/internal/auth-session.js +156 -0
- package/build/lib/proveauth/internal/auth-step.d.ts +5 -0
- package/build/lib/proveauth/internal/auth-step.js +2 -0
- package/build/lib/proveauth/internal/auth-token-claims.d.ts +46 -0
- package/build/lib/proveauth/internal/auth-token-claims.js +9 -0
- package/build/lib/proveauth/internal/base-authenticator.d.ts +28 -0
- package/build/lib/proveauth/internal/base-authenticator.js +129 -0
- package/build/lib/proveauth/internal/device-auth.d.ts +22 -0
- package/build/lib/proveauth/internal/device-auth.js +2 -0
- package/build/lib/proveauth/internal/device-passive-register-step.d.ts +10 -0
- package/build/lib/proveauth/internal/device-passive-register-step.js +97 -0
- package/build/lib/proveauth/internal/device-passive-silent-step.d.ts +10 -0
- package/build/lib/proveauth/internal/device-passive-silent-step.js +98 -0
- package/build/lib/proveauth/internal/device-passive-step.d.ts +17 -0
- package/build/lib/proveauth/internal/device-passive-step.js +133 -0
- package/build/lib/proveauth/internal/device-passive-stepup-step.d.ts +9 -0
- package/build/lib/proveauth/internal/device-passive-stepup-step.js +25 -0
- package/build/lib/proveauth/internal/device-passive-verify-step.d.ts +8 -0
- package/build/lib/proveauth/internal/device-passive-verify-step.js +54 -0
- package/build/lib/proveauth/internal/error-code.d.ts +9 -0
- package/build/lib/proveauth/internal/error-code.js +12 -0
- package/build/lib/proveauth/internal/mobile-instant-step.d.ts +15 -0
- package/build/lib/proveauth/internal/mobile-instant-step.js +100 -0
- package/build/lib/proveauth/internal/mobile-instantlink-step.d.ts +14 -0
- package/build/lib/proveauth/internal/mobile-instantlink-step.js +108 -0
- package/build/lib/proveauth/internal/mobile-otp-step.d.ts +14 -0
- package/build/lib/proveauth/internal/mobile-otp-step.js +141 -0
- package/build/lib/proveauth/internal/phone-number-input.d.ts +11 -0
- package/build/lib/proveauth/internal/phone-number-input.js +13 -0
- package/build/lib/proveauth/internal/platform.d.ts +45 -0
- package/build/lib/proveauth/internal/platform.js +20 -0
- package/build/lib/proveauth/internal/primary-authenticator.d.ts +14 -0
- package/build/lib/proveauth/internal/primary-authenticator.js +64 -0
- package/build/lib/proveauth/internal/report-error-step.d.ts +16 -0
- package/build/lib/proveauth/internal/report-error-step.js +88 -0
- package/build/lib/proveauth/internal/request-signer-v3.d.ts +10 -0
- package/build/lib/proveauth/internal/request-signer-v3.js +104 -0
- package/build/lib/proveauth/internal/scan-message-step.d.ts +11 -0
- package/build/lib/proveauth/internal/scan-message-step.js +45 -0
- package/build/lib/proveauth/internal/secondary-authenticator.d.ts +10 -0
- package/build/lib/proveauth/internal/secondary-authenticator.js +65 -0
- package/build/lib/proveauth/internal/settings.d.ts +18 -0
- package/build/lib/proveauth/internal/settings.js +50 -0
- package/build/lib/proveauth/internal/user-mobileactive-step.d.ts +7 -0
- package/build/lib/proveauth/internal/user-mobileactive-step.js +18 -0
- package/build/lib/proveauth/internal/user-present-step.d.ts +7 -0
- package/build/lib/proveauth/internal/user-present-step.js +18 -0
- package/build/lib/proveauth/internal/web-device-auth.d.ts +32 -0
- package/build/lib/proveauth/internal/web-device-auth.js +242 -0
- package/build/lib/proveauth/internal/web-platform.d.ts +30 -0
- package/build/lib/proveauth/internal/web-platform.js +160 -0
- package/build/lib/proveauth/otp.d.ts +23 -0
- package/build/lib/proveauth/otp.js +18 -0
- package/build/lib/proveauth/version.d.ts +3 -0
- package/build/lib/proveauth/version.js +6 -0
- package/package.json +75 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default class ErrorCode {
|
|
2
|
+
static readonly ERROR_AUTHENTICATION_FAILURE = 10000;
|
|
3
|
+
static readonly ERROR_AUTHENTICATION_EXTERNAL_FAILURE = 10001;
|
|
4
|
+
static readonly ERROR_AUTHENTICATION_CLIENT_FAILURE = 10002;
|
|
5
|
+
static readonly ERROR_AUTHENTICATION_PROHIBITED_ACTION = 10003;
|
|
6
|
+
static readonly ERROR_MISSING_AUTHENTICATOR_COMPLETION = 10004;
|
|
7
|
+
static readonly ERROR_MAX_ATTEMPTS = 10005;
|
|
8
|
+
static readonly ERROR_NO_DEVICE_FOUND = 10006;
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class ErrorCode {
|
|
4
|
+
}
|
|
5
|
+
ErrorCode.ERROR_AUTHENTICATION_FAILURE = 10000;
|
|
6
|
+
ErrorCode.ERROR_AUTHENTICATION_EXTERNAL_FAILURE = 10001;
|
|
7
|
+
ErrorCode.ERROR_AUTHENTICATION_CLIENT_FAILURE = 10002;
|
|
8
|
+
ErrorCode.ERROR_AUTHENTICATION_PROHIBITED_ACTION = 10003;
|
|
9
|
+
ErrorCode.ERROR_MISSING_AUTHENTICATOR_COMPLETION = 10004;
|
|
10
|
+
ErrorCode.ERROR_MAX_ATTEMPTS = 10005;
|
|
11
|
+
ErrorCode.ERROR_NO_DEVICE_FOUND = 10006;
|
|
12
|
+
exports.default = ErrorCode;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import AuthSession from './auth-session';
|
|
2
|
+
import AuthStep from './auth-step';
|
|
3
|
+
import { MobileAuthImplementation } from '../authenticator-builder';
|
|
4
|
+
export default class MobileInstantStep implements AuthStep {
|
|
5
|
+
static readonly NAME = "mobile/instant";
|
|
6
|
+
readonly name = "mobile/instant";
|
|
7
|
+
protected log: import("../common/logger").Logger;
|
|
8
|
+
private readonly implementation;
|
|
9
|
+
private readonly getDeviceIp;
|
|
10
|
+
private readonly deviceIpDetection;
|
|
11
|
+
private errorCodeBak?;
|
|
12
|
+
private nextBak?;
|
|
13
|
+
constructor(implementation: MobileAuthImplementation, getDeviceIp?: () => string | null);
|
|
14
|
+
execute(session: AuthSession): Promise<string>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
const auth_error_1 = __importDefault(require("./auth-error"));
|
|
7
|
+
const logger_1 = require("../common/logger");
|
|
8
|
+
const authenticator_builder_1 = require("../authenticator-builder");
|
|
9
|
+
const error_code_1 = __importDefault(require("./error-code"));
|
|
10
|
+
class MobileInstantStep {
|
|
11
|
+
constructor(implementation, getDeviceIp) {
|
|
12
|
+
this.name = MobileInstantStep.NAME;
|
|
13
|
+
this.log = logger_1.LoggerFactory.getLogger('mobile-instant-step');
|
|
14
|
+
this.errorCodeBak = error_code_1.default.ERROR_AUTHENTICATION_CLIENT_FAILURE;
|
|
15
|
+
this.implementation = implementation;
|
|
16
|
+
if (getDeviceIp) {
|
|
17
|
+
this.getDeviceIp = getDeviceIp;
|
|
18
|
+
this.deviceIpDetection = false;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.getDeviceIp = () => null;
|
|
22
|
+
this.deviceIpDetection = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
execute(session) {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
let builder = session.platform
|
|
28
|
+
.getMobileAuthBuilder()
|
|
29
|
+
.withDeviceIpDetection(this.deviceIpDetection);
|
|
30
|
+
switch (this.implementation) {
|
|
31
|
+
case authenticator_builder_1.MobileAuthImplementation.Pixel: {
|
|
32
|
+
builder = builder.withPixelImplementation();
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
case authenticator_builder_1.MobileAuthImplementation.Fetch: {
|
|
36
|
+
builder = builder.withFetchImplementation().withFinishStep((input) => {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
session
|
|
39
|
+
.fetchFromBackend('/v1/client/mobile/instant/finish', {
|
|
40
|
+
vfp: input.vfp,
|
|
41
|
+
})
|
|
42
|
+
.then(resolve)
|
|
43
|
+
.catch(reject);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
builder = builder.withStartStep((input) => {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const ip = this.deviceIpDetection ? input.deviceDescriptor.ip : this.getDeviceIp();
|
|
52
|
+
session
|
|
53
|
+
.fetchFromBackend('/v1/client/mobile/instant/start', {
|
|
54
|
+
cellularIp: ip,
|
|
55
|
+
implementation: this.implementation,
|
|
56
|
+
})
|
|
57
|
+
.then((response) => {
|
|
58
|
+
var _a;
|
|
59
|
+
if (response.error) {
|
|
60
|
+
this.nextBak = response.next;
|
|
61
|
+
this.errorCodeBak = response.error.code;
|
|
62
|
+
reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
resolve({
|
|
66
|
+
authUrl: (_a = response.data) === null || _a === void 0 ? void 0 : _a.redirectUrl,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
.catch(reject);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
const authenticator = builder.build();
|
|
74
|
+
authenticator
|
|
75
|
+
.authenticate()
|
|
76
|
+
.then((response) => {
|
|
77
|
+
if (response) {
|
|
78
|
+
const authResponse = response;
|
|
79
|
+
if (authResponse.error) {
|
|
80
|
+
reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
|
|
81
|
+
}
|
|
82
|
+
resolve(authResponse.next);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
session
|
|
86
|
+
.fetchFromBackend('/v1/client/mobile/instant/finish', {})
|
|
87
|
+
.then((response) => resolve(response.next))
|
|
88
|
+
.catch((error) => {
|
|
89
|
+
reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
.catch((error) => {
|
|
94
|
+
reject(new auth_error_1.default(error, this.errorCodeBak, this.nextBak, false));
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
MobileInstantStep.NAME = 'mobile/instant';
|
|
100
|
+
exports.default = MobileInstantStep;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import AuthSession from './auth-session';
|
|
2
|
+
import AuthStep from './auth-step';
|
|
3
|
+
import { InstantLinkStartStep } from '../instantlink';
|
|
4
|
+
export default class MobileInstantLinkStep implements AuthStep {
|
|
5
|
+
static readonly NAME = "mobile/instantlink";
|
|
6
|
+
readonly name = "mobile/instantlink";
|
|
7
|
+
protected log: import("../common/logger").Logger;
|
|
8
|
+
private readonly startStep?;
|
|
9
|
+
private readonly getDeviceIp;
|
|
10
|
+
constructor(startStep?: InstantLinkStartStep, getDeviceIp?: () => string | null);
|
|
11
|
+
execute(session: AuthSession): Promise<string>;
|
|
12
|
+
private runStartStep;
|
|
13
|
+
private runFinishStep;
|
|
14
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
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
|
+
const logger_1 = require("../common/logger");
|
|
7
|
+
const phone_number_input_1 = require("./phone-number-input");
|
|
8
|
+
const auth_error_1 = __importDefault(require("./auth-error"));
|
|
9
|
+
const SIMULATED_LINK_CLICK_DELAY = 100;
|
|
10
|
+
class MobileInstantLinkStep {
|
|
11
|
+
constructor(startStep, getDeviceIp) {
|
|
12
|
+
this.name = MobileInstantLinkStep.NAME;
|
|
13
|
+
this.log = logger_1.LoggerFactory.getLogger('mobile-instantlink-step');
|
|
14
|
+
this.startStep = startStep;
|
|
15
|
+
this.getDeviceIp = getDeviceIp !== null && getDeviceIp !== void 0 ? getDeviceIp : (() => null);
|
|
16
|
+
}
|
|
17
|
+
execute(session) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
var _a, _b, _c, _d, _e, _f;
|
|
20
|
+
var phoneNumberNeeded = true;
|
|
21
|
+
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.mnp) {
|
|
22
|
+
phoneNumberNeeded = false;
|
|
23
|
+
}
|
|
24
|
+
var testMode = false;
|
|
25
|
+
if ((_f = (_e = (_d = session.claims) === null || _d === void 0 ? void 0 : _d.auth.subs.mob) === null || _e === void 0 ? void 0 : _e.auths.inln) === null || _f === void 0 ? void 0 : _f.tme) {
|
|
26
|
+
testMode = true;
|
|
27
|
+
}
|
|
28
|
+
this.runStartStep(session, phoneNumberNeeded)
|
|
29
|
+
.then((next) => {
|
|
30
|
+
this.runFinishStep(session, testMode)
|
|
31
|
+
.then(() => resolve(next))
|
|
32
|
+
.catch(reject);
|
|
33
|
+
})
|
|
34
|
+
.catch(reject);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
runStartStep(session, phoneNumberNeeded, phoneValidationError) {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
if (this.startStep) {
|
|
40
|
+
this.startStep
|
|
41
|
+
.execute(phoneNumberNeeded, phoneValidationError)
|
|
42
|
+
.then((input) => {
|
|
43
|
+
session
|
|
44
|
+
.fetchFromBackend('/v1/client/mobile/instantlink/start', {
|
|
45
|
+
sourceIp: this.getDeviceIp(),
|
|
46
|
+
mobileNumber: input === null || input === void 0 ? void 0 : input.phoneNumber,
|
|
47
|
+
})
|
|
48
|
+
.then((response) => {
|
|
49
|
+
var _a, _b, _c;
|
|
50
|
+
const authResponse = response;
|
|
51
|
+
if (authResponse.error) {
|
|
52
|
+
reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
|
|
53
|
+
}
|
|
54
|
+
else if (authResponse.data) {
|
|
55
|
+
var errorMessage = '';
|
|
56
|
+
if ((_a = authResponse.data) === null || _a === void 0 ? void 0 : _a.code) {
|
|
57
|
+
errorMessage += `Error Code: ${authResponse.data.code}, `;
|
|
58
|
+
}
|
|
59
|
+
if ((_b = authResponse.data) === null || _b === void 0 ? void 0 : _b.message) {
|
|
60
|
+
errorMessage += `${authResponse.data.message}`;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
errorMessage += `Error validating phone number`;
|
|
64
|
+
}
|
|
65
|
+
let phoneNumberValidationError = new phone_number_input_1.PhoneValidationError(errorMessage, (_c = authResponse.data) === null || _c === void 0 ? void 0 : _c.code);
|
|
66
|
+
this.log.error(`Server reports invalid phone number: ${errorMessage}`);
|
|
67
|
+
this.runStartStep(session, phoneNumberNeeded, phoneNumberValidationError)
|
|
68
|
+
.then(resolve)
|
|
69
|
+
.catch(reject);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
resolve(authResponse.next);
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
.catch(reject);
|
|
76
|
+
})
|
|
77
|
+
.catch(reject);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
reject(new Error('InstantLink start step must be specified'));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
runFinishStep(session, testMode) {
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
if (testMode) {
|
|
87
|
+
this.log.info('Simulating user clicking the instant link');
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
session.platform
|
|
90
|
+
.fetch(session.backendUrl +
|
|
91
|
+
'/v1/client/mobile/instantlink/finish?token=' +
|
|
92
|
+
session.authToken +
|
|
93
|
+
'&vfp=test-vfp', {
|
|
94
|
+
mode: 'cors',
|
|
95
|
+
method: 'GET',
|
|
96
|
+
})
|
|
97
|
+
.then((_) => resolve())
|
|
98
|
+
.catch(reject);
|
|
99
|
+
}, SIMULATED_LINK_CLICK_DELAY);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
resolve();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
MobileInstantLinkStep.NAME = 'mobile/instantlink';
|
|
108
|
+
exports.default = MobileInstantLinkStep;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import AuthSession from './auth-session';
|
|
2
|
+
import AuthStep from './auth-step';
|
|
3
|
+
import { OtpStartStep, OtpFinishStep } from '../otp';
|
|
4
|
+
export default class MobileOtpStep implements AuthStep {
|
|
5
|
+
static readonly NAME = "mobile/otp";
|
|
6
|
+
readonly name = "mobile/otp";
|
|
7
|
+
protected log: import("../common/logger").Logger;
|
|
8
|
+
private otpStartStep?;
|
|
9
|
+
private otpFinishStep?;
|
|
10
|
+
constructor(otpStartStep?: OtpStartStep, otpFinishStep?: OtpFinishStep);
|
|
11
|
+
execute(session: AuthSession): Promise<string>;
|
|
12
|
+
private runOtpStartStep;
|
|
13
|
+
private runOtpFinishStep;
|
|
14
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
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
|
+
const logger_1 = require("../common/logger");
|
|
7
|
+
const auth_error_1 = __importDefault(require("./auth-error"));
|
|
8
|
+
const otp_1 = require("../otp");
|
|
9
|
+
const phone_number_input_1 = require("./phone-number-input");
|
|
10
|
+
class MobileOtpStep {
|
|
11
|
+
constructor(otpStartStep, otpFinishStep) {
|
|
12
|
+
this.name = MobileOtpStep.NAME;
|
|
13
|
+
this.log = logger_1.LoggerFactory.getLogger('mobile-otp-step');
|
|
14
|
+
this.otpStartStep = otpStartStep;
|
|
15
|
+
this.otpFinishStep = otpFinishStep;
|
|
16
|
+
}
|
|
17
|
+
execute(session) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
var _a, _b, _c;
|
|
20
|
+
if (!this.otpStartStep) {
|
|
21
|
+
reject(new Error('OtpStartStep step must be specified'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!this.otpFinishStep) {
|
|
25
|
+
reject(new Error('OtpFinishStep step must be specified'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
var phoneNumberNeeded = true;
|
|
29
|
+
if ((_c = (_b = (_a = session.claims) === null || _a === void 0 ? void 0 : _a.auth.subs.mob) === null || _b === void 0 ? void 0 : _b.auths.otp) === null || _c === void 0 ? void 0 : _c.mnp) {
|
|
30
|
+
phoneNumberNeeded = false;
|
|
31
|
+
}
|
|
32
|
+
this.runOtpStartStep(session, this.otpStartStep, this.otpFinishStep, phoneNumberNeeded)
|
|
33
|
+
.then(resolve)
|
|
34
|
+
.catch(reject);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, phoneValidationError) {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
otpStartStep
|
|
40
|
+
.execute(phoneNumberNeeded, phoneValidationError)
|
|
41
|
+
.then((input) => {
|
|
42
|
+
session
|
|
43
|
+
.fetchFromBackend('/v1/client/mobile/otp/start', {
|
|
44
|
+
mobileNumber: input === null || input === void 0 ? void 0 : input.phoneNumber,
|
|
45
|
+
})
|
|
46
|
+
.then((response) => {
|
|
47
|
+
const authResponse = response;
|
|
48
|
+
if (authResponse.error) {
|
|
49
|
+
reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
|
|
50
|
+
}
|
|
51
|
+
else if (authResponse.data) {
|
|
52
|
+
let data = authResponse.data;
|
|
53
|
+
var errorMessage = '';
|
|
54
|
+
if (data === null || data === void 0 ? void 0 : data.code) {
|
|
55
|
+
errorMessage += `Error Code: ${data.code}, `;
|
|
56
|
+
}
|
|
57
|
+
if (data === null || data === void 0 ? void 0 : data.message) {
|
|
58
|
+
errorMessage += `${data.message}`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
errorMessage += `Error validating phone number`;
|
|
62
|
+
}
|
|
63
|
+
let phoneNumberValidationError = new phone_number_input_1.PhoneValidationError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
|
|
64
|
+
this.log.error(`Server reports invalid phone number: ${errorMessage}`);
|
|
65
|
+
this.runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, phoneNumberValidationError)
|
|
66
|
+
.then(resolve)
|
|
67
|
+
.catch(reject);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded)
|
|
71
|
+
.then(resolve)
|
|
72
|
+
.catch(reject);
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
.catch(reject);
|
|
76
|
+
})
|
|
77
|
+
.catch((error) => {
|
|
78
|
+
const message = auth_error_1.default.extractMessage(error);
|
|
79
|
+
reject(new Error(`Failed to start OTP flow: ${message}`));
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, otpError) {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
otpFinishStep
|
|
86
|
+
.execute(otpError)
|
|
87
|
+
.then((otpFinishResult) => {
|
|
88
|
+
var _a;
|
|
89
|
+
let result = otpFinishResult;
|
|
90
|
+
switch (result.resultType) {
|
|
91
|
+
case otp_1.OtpFinishResultType.OnResendOtp:
|
|
92
|
+
this.runOtpStartStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded)
|
|
93
|
+
.then(resolve)
|
|
94
|
+
.catch(reject);
|
|
95
|
+
break;
|
|
96
|
+
case otp_1.OtpFinishResultType.OnSuccess:
|
|
97
|
+
let input = result.input;
|
|
98
|
+
session
|
|
99
|
+
.fetchFromBackend('/v1/client/mobile/otp/finish', {
|
|
100
|
+
otp: (_a = input === null || input === void 0 ? void 0 : input.otp) !== null && _a !== void 0 ? _a : '',
|
|
101
|
+
})
|
|
102
|
+
.then((response) => {
|
|
103
|
+
const authResponse = response;
|
|
104
|
+
if (authResponse.error) {
|
|
105
|
+
reject(new auth_error_1.default(authResponse.error.message, authResponse.error.code, response.next, false));
|
|
106
|
+
}
|
|
107
|
+
else if (authResponse.data) {
|
|
108
|
+
let data = authResponse.data;
|
|
109
|
+
var errorMessage = '';
|
|
110
|
+
if (data === null || data === void 0 ? void 0 : data.code) {
|
|
111
|
+
errorMessage += `Error Code: ${data.code}, `;
|
|
112
|
+
}
|
|
113
|
+
if (data === null || data === void 0 ? void 0 : data.message) {
|
|
114
|
+
errorMessage += `${data.message}`;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
errorMessage += `Error validating OTP`;
|
|
118
|
+
}
|
|
119
|
+
let otpError = new otp_1.OtpError(errorMessage, data === null || data === void 0 ? void 0 : data.code);
|
|
120
|
+
this.log.error(`Server reports invalid OTP: ${errorMessage}`);
|
|
121
|
+
this.runOtpFinishStep(session, otpStartStep, otpFinishStep, phoneNumberNeeded, otpError)
|
|
122
|
+
.then(resolve)
|
|
123
|
+
.catch(reject);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
resolve(response.next);
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
.catch(reject);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
.catch((error) => {
|
|
134
|
+
const message = auth_error_1.default.extractMessage(error);
|
|
135
|
+
reject(new Error(`Failed to obtain OTP for verification: ${message}}`));
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
MobileOtpStep.NAME = 'mobile/otp';
|
|
141
|
+
exports.default = MobileOtpStep;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import AuthError from './auth-error';
|
|
2
|
+
export default interface PhoneNumberInput {
|
|
3
|
+
phoneNumber: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class PhoneValidationError extends AuthError {
|
|
6
|
+
constructor(message?: string, code?: number);
|
|
7
|
+
}
|
|
8
|
+
export interface PhoneNumberStep {
|
|
9
|
+
execute: (phoneNumberNeeded: boolean, phoneValidationError?: PhoneValidationError) => Promise<PhoneNumberInput | null>;
|
|
10
|
+
}
|
|
11
|
+
export type PhoneNumberStepFn = (phoneNumberNeeded: boolean, phoneValidationError?: PhoneValidationError) => Promise<PhoneNumberInput | null>;
|
|
@@ -0,0 +1,13 @@
|
|
|
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.PhoneValidationError = void 0;
|
|
7
|
+
const auth_error_1 = __importDefault(require("./auth-error"));
|
|
8
|
+
class PhoneValidationError extends auth_error_1.default {
|
|
9
|
+
constructor(message, code) {
|
|
10
|
+
super(message, code);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.PhoneValidationError = PhoneValidationError;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/// <reference types="webappsec-credential-management" />
|
|
2
|
+
import { AuthenticatorBuilder } from '@prove-identity/mobile-auth';
|
|
3
|
+
import { AuthRequest } from './auth-request';
|
|
4
|
+
import AuthResponse from './auth-response';
|
|
5
|
+
import DeviceAuth, { DeviceRegistration } from './device-auth';
|
|
6
|
+
export declare const DEVICE_CAPABILITY_WEBAUTHN = "webauthn";
|
|
7
|
+
export interface MessageChannel {
|
|
8
|
+
addEventListener: (type: string, listener: (event: any) => void) => void;
|
|
9
|
+
send: (data: string) => void;
|
|
10
|
+
close: () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface WebAuthN {
|
|
13
|
+
getCredentials: (options?: CredentialRequestOptions) => Promise<CredentialType | null>;
|
|
14
|
+
createCredentials: (options: CredentialCreationOptions) => Promise<CredentialType | null>;
|
|
15
|
+
}
|
|
16
|
+
export interface RequestSignature {
|
|
17
|
+
version: string;
|
|
18
|
+
challenge: string;
|
|
19
|
+
keyId: string;
|
|
20
|
+
signature: string;
|
|
21
|
+
}
|
|
22
|
+
export interface RequestSigner {
|
|
23
|
+
sign: (method: string, path: string, query: string, contentType: string, body: string) => Promise<RequestSignature | null>;
|
|
24
|
+
}
|
|
25
|
+
export interface AuthSessionIntegration {
|
|
26
|
+
getDeviceRegistration: () => Promise<DeviceRegistration | null>;
|
|
27
|
+
fetchFromBackend: (query: string, body: AuthRequest) => Promise<AuthResponse>;
|
|
28
|
+
}
|
|
29
|
+
export default interface Platform {
|
|
30
|
+
readonly webauthn: WebAuthN;
|
|
31
|
+
readonly deviceAuth: DeviceAuth;
|
|
32
|
+
getPlatformName: () => string;
|
|
33
|
+
getUserAgent: () => string | null;
|
|
34
|
+
isFidoSupported: () => boolean;
|
|
35
|
+
fetch: (input: string, init?: RequestInit) => Promise<Response>;
|
|
36
|
+
createMessageChannel: (endpointUrl: string) => MessageChannel;
|
|
37
|
+
createRequestSigner: (session: AuthSessionIntegration) => RequestSigner;
|
|
38
|
+
getDeviceCapabilities: () => string[];
|
|
39
|
+
getMobileAuthBuilder: () => AuthenticatorBuilder<any>;
|
|
40
|
+
exit: (code?: number) => void;
|
|
41
|
+
}
|
|
42
|
+
export declare function stringToArrayBuffer(input: string): ArrayBuffer;
|
|
43
|
+
export declare function arrayBufferToString(input: ArrayBuffer): string;
|
|
44
|
+
export declare function arrayBufferToHexString(input: ArrayBuffer): string;
|
|
45
|
+
export declare function getUnixTime(): number;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getUnixTime = exports.arrayBufferToHexString = exports.arrayBufferToString = exports.stringToArrayBuffer = exports.DEVICE_CAPABILITY_WEBAUTHN = void 0;
|
|
4
|
+
exports.DEVICE_CAPABILITY_WEBAUTHN = 'webauthn';
|
|
5
|
+
function stringToArrayBuffer(input) {
|
|
6
|
+
return new TextEncoder().encode(input);
|
|
7
|
+
}
|
|
8
|
+
exports.stringToArrayBuffer = stringToArrayBuffer;
|
|
9
|
+
function arrayBufferToString(input) {
|
|
10
|
+
return String.fromCharCode.apply(null, Array.from(new Uint8Array(input)));
|
|
11
|
+
}
|
|
12
|
+
exports.arrayBufferToString = arrayBufferToString;
|
|
13
|
+
function arrayBufferToHexString(input) {
|
|
14
|
+
return Array.from(new Uint8Array(input), (x) => ('00' + x.toString(16)).slice(-2)).join('');
|
|
15
|
+
}
|
|
16
|
+
exports.arrayBufferToHexString = arrayBufferToHexString;
|
|
17
|
+
function getUnixTime() {
|
|
18
|
+
return Math.floor(Date.now() / 1000);
|
|
19
|
+
}
|
|
20
|
+
exports.getUnixTime = getUnixTime;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import AuthFinishStep from '../auth-finish-step';
|
|
2
|
+
import AuthStep from './auth-step';
|
|
3
|
+
import AuthSession from './auth-session';
|
|
4
|
+
import Platform from './platform';
|
|
5
|
+
import CancelablePromise from '../common/cancelable-promise';
|
|
6
|
+
import BaseAuthenticator from './base-authenticator';
|
|
7
|
+
export default class PrimaryAuthenticator extends BaseAuthenticator {
|
|
8
|
+
static readonly MAX_ATTEMPTS = 50;
|
|
9
|
+
private readonly steps;
|
|
10
|
+
constructor(platform?: Platform, storage?: Storage, finishStep?: AuthFinishStep, steps?: Array<AuthStep>);
|
|
11
|
+
process(session: AuthSession): CancelablePromise<void>;
|
|
12
|
+
private nextStep;
|
|
13
|
+
private getNextStep;
|
|
14
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
const report_error_step_1 = __importDefault(require("./report-error-step"));
|
|
7
|
+
const logger_1 = require("../common/logger");
|
|
8
|
+
const cancelable_promise_1 = __importDefault(require("../common/cancelable-promise"));
|
|
9
|
+
const base_authenticator_1 = __importDefault(require("./base-authenticator"));
|
|
10
|
+
const auth_error_1 = __importDefault(require("./auth-error"));
|
|
11
|
+
const error_code_1 = __importDefault(require("./error-code"));
|
|
12
|
+
class PrimaryAuthenticator extends base_authenticator_1.default {
|
|
13
|
+
constructor(platform, storage, finishStep, steps) {
|
|
14
|
+
super(platform, storage, finishStep);
|
|
15
|
+
this.steps = new Map();
|
|
16
|
+
this.log = logger_1.LoggerFactory.getLogger('primary-authenticator');
|
|
17
|
+
if (steps) {
|
|
18
|
+
for (let step of steps) {
|
|
19
|
+
this.steps.set(step.name, step);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
process(session) {
|
|
24
|
+
return new cancelable_promise_1.default((resolve, reject, onCancel) => {
|
|
25
|
+
onCancel(() => {
|
|
26
|
+
this.log.info('Canceled');
|
|
27
|
+
resolve();
|
|
28
|
+
});
|
|
29
|
+
this.nextStep(session, session.next, 1).then(resolve).catch(reject);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
nextStep(session, step, attempt) {
|
|
33
|
+
this.log.debug(`Authentication attempt ${attempt}, next step: ${step}`);
|
|
34
|
+
session.lastStep = step;
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
if ([base_authenticator_1.default.AUTH_DONE, base_authenticator_1.default.AUTH_EMPTY].includes(step)) {
|
|
37
|
+
resolve();
|
|
38
|
+
}
|
|
39
|
+
else if (attempt > PrimaryAuthenticator.MAX_ATTEMPTS) {
|
|
40
|
+
reject(new auth_error_1.default('Too many authentication steps', error_code_1.default.ERROR_MAX_ATTEMPTS));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
this.getNextStep(step)
|
|
44
|
+
.execute(session)
|
|
45
|
+
.then((next) => this.nextStep(session, next, attempt + 1))
|
|
46
|
+
.then(resolve)
|
|
47
|
+
.catch((e) => new report_error_step_1.default(e)
|
|
48
|
+
.execute(session)
|
|
49
|
+
.then((next) => this.nextStep(session, next, attempt + 1))
|
|
50
|
+
.then(resolve)
|
|
51
|
+
.catch(reject));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
getNextStep(step) {
|
|
56
|
+
var nextStep = this.steps.get(step);
|
|
57
|
+
if (nextStep) {
|
|
58
|
+
return nextStep;
|
|
59
|
+
}
|
|
60
|
+
return new report_error_step_1.default('Unknown authentication step: ' + step);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
PrimaryAuthenticator.MAX_ATTEMPTS = 50;
|
|
64
|
+
exports.default = PrimaryAuthenticator;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import AuthSession from './auth-session';
|
|
2
|
+
import AuthStep from './auth-step';
|
|
3
|
+
export default class ReportErrorStep implements AuthStep {
|
|
4
|
+
private static readonly errorKinds;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private _message;
|
|
7
|
+
private _code?;
|
|
8
|
+
private nextStep?;
|
|
9
|
+
private reportable?;
|
|
10
|
+
constructor(error: any);
|
|
11
|
+
readonly name = "error";
|
|
12
|
+
get code(): number | undefined;
|
|
13
|
+
get message(): string;
|
|
14
|
+
execute(session: AuthSession): Promise<string>;
|
|
15
|
+
private getKind;
|
|
16
|
+
}
|