@prove-identity/prove-auth 2.7.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -9
- package/build/bundle/release/prove-auth.js +1 -0
- package/build/lib/index.d.ts +3 -2
- package/build/lib/index.js +3 -1
- package/build/lib/proveauth/authenticator-builder.d.ts +4 -0
- package/build/lib/proveauth/authenticator-builder.js +59 -3
- package/build/lib/proveauth/darwinium-result.d.ts +11 -0
- package/build/lib/proveauth/darwinium-result.js +25 -0
- package/build/lib/proveauth/darwinium-wrapper.d.ts +6 -0
- package/build/lib/proveauth/darwinium-wrapper.js +97 -0
- package/build/lib/proveauth/device-context-options.d.ts +7 -0
- package/build/lib/proveauth/device-context-options.js +7 -1
- package/build/lib/proveauth/internal/auth-error.js +1 -1
- package/build/lib/proveauth/internal/auth-request.d.ts +1 -0
- package/build/lib/proveauth/internal/auth-response.d.ts +5 -1
- package/build/lib/proveauth/internal/auth-session.d.ts +7 -2
- package/build/lib/proveauth/internal/auth-session.js +115 -11
- package/build/lib/proveauth/internal/auth-status-actions.js +4 -4
- package/build/lib/proveauth/internal/auth-token-claims.d.ts +1 -0
- package/build/lib/proveauth/internal/device-auth.d.ts +3 -1
- package/build/lib/proveauth/internal/device-passive-register-step.d.ts +1 -0
- package/build/lib/proveauth/internal/device-passive-register-step.js +55 -35
- package/build/lib/proveauth/internal/device-passive-silent-step.js +9 -1
- package/build/lib/proveauth/internal/device-passive-step.d.ts +12 -4
- package/build/lib/proveauth/internal/device-passive-step.js +172 -52
- package/build/lib/proveauth/internal/device-passive-stepup-step.d.ts +2 -1
- package/build/lib/proveauth/internal/device-passive-stepup-step.js +25 -3
- package/build/lib/proveauth/internal/device-passive-verify-step.d.ts +3 -2
- package/build/lib/proveauth/internal/device-passive-verify-step.js +29 -10
- package/build/lib/proveauth/internal/fido-options-error.d.ts +30 -0
- package/build/lib/proveauth/internal/fido-options-error.js +161 -0
- package/build/lib/proveauth/internal/main-authenticator.js +1 -1
- package/build/lib/proveauth/internal/mobile-instantlink-step.js +36 -29
- package/build/lib/proveauth/internal/mobile-otp-step.d.ts +3 -0
- package/build/lib/proveauth/internal/mobile-otp-step.js +115 -67
- package/build/lib/proveauth/internal/platform.d.ts +2 -0
- package/build/lib/proveauth/internal/report-error-step.d.ts +1 -2
- package/build/lib/proveauth/internal/report-error-step.js +13 -12
- package/build/lib/proveauth/internal/scan-message-step.js +1 -1
- package/build/lib/proveauth/internal/settings.d.ts +4 -0
- package/build/lib/proveauth/internal/settings.js +16 -0
- package/build/lib/proveauth/internal/web-device-auth.d.ts +3 -1
- package/build/lib/proveauth/internal/web-device-auth.js +31 -15
- package/build/lib/proveauth/internal/web-platform.d.ts +2 -1
- package/build/lib/proveauth/internal/web-platform.js +19 -0
- package/build/lib/proveauth/internal/web-socket-close-reasons.d.ts +15 -0
- package/build/lib/proveauth/internal/web-socket-close-reasons.js +19 -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,8 @@ export interface AuthFailure {
|
|
|
9
9
|
code: number;
|
|
10
10
|
}
|
|
11
11
|
export interface RegisterStartAuthResponseData {
|
|
12
|
-
credCreateOptions
|
|
12
|
+
credCreateOptions?: PublicKeyCredentialCreationOptions;
|
|
13
|
+
credRequestOptions?: PublicKeyCredentialRequestOptions;
|
|
13
14
|
}
|
|
14
15
|
export interface RegisterStartAuthResponse extends AuthResponse {
|
|
15
16
|
data: RegisterStartAuthResponseData;
|
|
@@ -17,6 +18,7 @@ export interface RegisterStartAuthResponse extends AuthResponse {
|
|
|
17
18
|
export interface RegisterFinishAuthResponseData {
|
|
18
19
|
deviceId: string;
|
|
19
20
|
passkey: boolean;
|
|
21
|
+
scanMessage?: AuthMessage;
|
|
20
22
|
}
|
|
21
23
|
export interface RegisterFinishAuthResponse extends AuthResponse {
|
|
22
24
|
data: RegisterFinishAuthResponseData;
|
|
@@ -30,6 +32,8 @@ export interface VerifyStartAuthResponse extends AuthResponse {
|
|
|
30
32
|
}
|
|
31
33
|
export interface VerifyFinishAuthResponseData {
|
|
32
34
|
scanMessage?: AuthMessage;
|
|
35
|
+
deviceId?: string;
|
|
36
|
+
passkey?: boolean;
|
|
33
37
|
}
|
|
34
38
|
export interface VerifyFinishAuthResponse extends AuthResponse {
|
|
35
39
|
data?: VerifyFinishAuthResponseData;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/// <reference types="webappsec-credential-management" />
|
|
2
2
|
import AuthMessage from './auth-message';
|
|
3
|
-
import { AuthRequest, Signal } from './auth-request';
|
|
3
|
+
import { AuthRequest, Signal, Signals } 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';
|
|
7
7
|
import Platform, { AuthSessionIntegration, MessageChannel, RequestSigner } from './platform';
|
|
8
8
|
import Settings from './settings';
|
|
9
|
+
import { WebSocketCloseReasons } from './web-socket-close-reasons';
|
|
9
10
|
export default class AuthSession implements AuthSessionIntegration {
|
|
10
11
|
readonly platform: Platform;
|
|
11
12
|
readonly authToken?: string;
|
|
@@ -26,11 +27,15 @@ export default class AuthSession implements AuthSessionIntegration {
|
|
|
26
27
|
get next(): string;
|
|
27
28
|
constructor(settings: Settings, platform: Platform, authToken?: string);
|
|
28
29
|
fetchFromBackend(query: string, body: AuthRequest): Promise<AuthResponse>;
|
|
29
|
-
|
|
30
|
+
static parseCloseEvent(event: CloseEvent): [WebSocketCloseReasons, number];
|
|
31
|
+
createMessageChannel(query: string, onClose: (reason: WebSocketCloseReasons, code: number) => void, onError: (message: string) => void, onMessage: (data: string) => void): MessageChannel;
|
|
30
32
|
closeAllMessageChannels(): void;
|
|
31
33
|
getDeviceRegistration(): Promise<DeviceRegistration | null>;
|
|
32
34
|
embedFpResultToDeviceRegistration(registration: DeviceRegistration): Promise<DeviceRegistration>;
|
|
35
|
+
embedDarwiniumResultToDeviceRegistration(registration: DeviceRegistration): Promise<DeviceRegistration>;
|
|
36
|
+
embedDarwiniumSignal(signals: Signals): void;
|
|
33
37
|
getFingerprintData(): Promise<Signal | undefined>;
|
|
34
38
|
shouldCollectFP(): boolean;
|
|
39
|
+
shouldSendDarwiniumData(): boolean;
|
|
35
40
|
private parseJwt;
|
|
36
41
|
}
|
|
@@ -7,6 +7,7 @@ const logger_1 = require("../common/logger");
|
|
|
7
7
|
const version_1 = require("../version");
|
|
8
8
|
const auth_token_claims_1 = require("./auth-token-claims");
|
|
9
9
|
const error_code_1 = __importDefault(require("./error-code"));
|
|
10
|
+
const web_socket_close_reasons_1 = require("./web-socket-close-reasons");
|
|
10
11
|
class AuthSession {
|
|
11
12
|
get namespace() {
|
|
12
13
|
var _a;
|
|
@@ -90,6 +91,48 @@ class AuthSession {
|
|
|
90
91
|
.catch(reject);
|
|
91
92
|
});
|
|
92
93
|
}
|
|
94
|
+
static parseCloseEvent(event) {
|
|
95
|
+
var reason = web_socket_close_reasons_1.WebSocketCloseReasons.UNKNOWN_REASON;
|
|
96
|
+
switch (event.code) {
|
|
97
|
+
case 1000:
|
|
98
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.NORMAL_CLOSURE;
|
|
99
|
+
break;
|
|
100
|
+
case 1001:
|
|
101
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.GOING_AWAY;
|
|
102
|
+
break;
|
|
103
|
+
case 1002:
|
|
104
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.PROTOCOL_ERROR;
|
|
105
|
+
break;
|
|
106
|
+
case 1003:
|
|
107
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.UNSUPPORTED_DATA;
|
|
108
|
+
break;
|
|
109
|
+
case 1005:
|
|
110
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.NO_STATUS_RECEIVED;
|
|
111
|
+
break;
|
|
112
|
+
case 1006:
|
|
113
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.ABNORMAL_CLOSURE;
|
|
114
|
+
break;
|
|
115
|
+
case 1007:
|
|
116
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.INVALID_FRAME_PAYLOAD_DATA;
|
|
117
|
+
break;
|
|
118
|
+
case 1008:
|
|
119
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.POLICY_VIOLATION;
|
|
120
|
+
break;
|
|
121
|
+
case 1009:
|
|
122
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.MESSAGE_TOO_BIG;
|
|
123
|
+
break;
|
|
124
|
+
case 1010:
|
|
125
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.MANDATORY_EXTENSION;
|
|
126
|
+
break;
|
|
127
|
+
case 1011:
|
|
128
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.INTERNAL_ERROR;
|
|
129
|
+
break;
|
|
130
|
+
case 1015:
|
|
131
|
+
reason = web_socket_close_reasons_1.WebSocketCloseReasons.TLS_HANDSHAKE;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
return [reason, event.code];
|
|
135
|
+
}
|
|
93
136
|
createMessageChannel(query, onClose, onError, onMessage) {
|
|
94
137
|
if (!this.authToken) {
|
|
95
138
|
throw new Error('Authentication token is not initialized, cannot create MessageChannel');
|
|
@@ -105,29 +148,28 @@ class AuthSession {
|
|
|
105
148
|
channel.send('ping');
|
|
106
149
|
}
|
|
107
150
|
else {
|
|
108
|
-
this.log.
|
|
151
|
+
this.log.warn('Failed to receive ping response in time, closing the channel');
|
|
109
152
|
clearInterval(keepAlive);
|
|
110
153
|
channel.close();
|
|
111
154
|
onError('Channel communication stalled');
|
|
112
155
|
this.channels.delete(channel);
|
|
113
156
|
}
|
|
114
157
|
}, KEEP_ALIVE_INTERVAL);
|
|
115
|
-
channel.addEventListener('close', (
|
|
158
|
+
channel.addEventListener('close', (event) => {
|
|
159
|
+
var statusCode = event.code ? `with status code: ${event.code}` : 'without status code';
|
|
160
|
+
this.log.debug(`Message channel is closed ${statusCode}`);
|
|
116
161
|
clearInterval(keepAlive);
|
|
117
|
-
onClose();
|
|
118
162
|
this.channels.delete(channel);
|
|
163
|
+
const [reason, code] = AuthSession.parseCloseEvent(event);
|
|
164
|
+
onClose(reason, code);
|
|
119
165
|
});
|
|
120
166
|
channel.addEventListener('error', (event) => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
onError(event['message']);
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
onError(event.toString());
|
|
127
|
-
}
|
|
128
|
-
this.channels.delete(channel);
|
|
167
|
+
this.log.debug('Message channel encountered an error');
|
|
168
|
+
this.log.debug(event);
|
|
129
169
|
});
|
|
130
170
|
channel.addEventListener('message', (event) => {
|
|
171
|
+
this.log.trace('Message channel received a message');
|
|
172
|
+
this.log.trace(event);
|
|
131
173
|
if ('origin' in event && event['origin'] !== endpoint) {
|
|
132
174
|
onError('Unexpected origin');
|
|
133
175
|
}
|
|
@@ -150,6 +192,7 @@ class AuthSession {
|
|
|
150
192
|
return channel;
|
|
151
193
|
}
|
|
152
194
|
closeAllMessageChannels() {
|
|
195
|
+
this.log.trace('Closing all message channels, total ' + this.channels.size + ' registered channels');
|
|
153
196
|
const channelsCopy = new Set(this.channels);
|
|
154
197
|
channelsCopy.forEach((channel) => channel.close());
|
|
155
198
|
channelsCopy.clear();
|
|
@@ -190,6 +233,63 @@ class AuthSession {
|
|
|
190
233
|
});
|
|
191
234
|
});
|
|
192
235
|
}
|
|
236
|
+
embedDarwiniumResultToDeviceRegistration(registration) {
|
|
237
|
+
return new Promise((resolve) => {
|
|
238
|
+
const notAvaialbleErrMsg = 'Darwinium data is not avaialble';
|
|
239
|
+
if (this.shouldSendDarwiniumData()) {
|
|
240
|
+
const dResult = this.settings.darwiniumResult;
|
|
241
|
+
if (dResult) {
|
|
242
|
+
if (!dResult.isExpired()) {
|
|
243
|
+
if (dResult.getResultBlob()) {
|
|
244
|
+
registration.setDarwiniumSignal({ results: dResult.getResultBlob() });
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
if (dResult.getError()) {
|
|
248
|
+
registration.setDarwiniumSignal({ error: dResult.getError() });
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
registration.setDarwiniumSignal({ error: notAvaialbleErrMsg });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
registration.setDarwiniumSignal({ error: 'Darwinium data is expired' });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
registration.setDarwiniumSignal({ error: notAvaialbleErrMsg });
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
resolve(registration);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
embedDarwiniumSignal(signals) {
|
|
267
|
+
const notAvaialbleErrMsg = 'Darwinium data is not avaialble';
|
|
268
|
+
if (this.shouldSendDarwiniumData()) {
|
|
269
|
+
const dResult = this.settings.darwiniumResult;
|
|
270
|
+
if (dResult) {
|
|
271
|
+
if (!dResult.isExpired()) {
|
|
272
|
+
if (dResult.getResultBlob()) {
|
|
273
|
+
signals.darwinium = { results: dResult.getResultBlob() };
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
if (dResult.getError()) {
|
|
277
|
+
signals.darwinium = { error: dResult.getError() };
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
signals.darwinium = { error: notAvaialbleErrMsg };
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
signals.darwinium = { error: 'Darwinium data is expired' };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
signals.darwinium = { error: notAvaialbleErrMsg };
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
193
293
|
getFingerprintData() {
|
|
194
294
|
return new Promise((resolve) => {
|
|
195
295
|
var fpPromise = this.platform.getFpPromise();
|
|
@@ -231,6 +331,10 @@ class AuthSession {
|
|
|
231
331
|
}
|
|
232
332
|
return false;
|
|
233
333
|
}
|
|
334
|
+
shouldSendDarwiniumData() {
|
|
335
|
+
var _a, _b, _c;
|
|
336
|
+
return ((_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.dwn) ? true : false;
|
|
337
|
+
}
|
|
234
338
|
parseJwt(token) {
|
|
235
339
|
return JSON.parse(atob(token.split('.')[1]));
|
|
236
340
|
}
|
|
@@ -14,13 +14,12 @@ class AuthStatusActions {
|
|
|
14
14
|
var gotResponse = false;
|
|
15
15
|
this.log.trace('Waiting for auth status');
|
|
16
16
|
return new Promise((resolve, reject) => {
|
|
17
|
-
const channel = session.createMessageChannel('/v1/client/status?token=' + encodeURIComponent(session.authToken), () => {
|
|
17
|
+
const channel = session.createMessageChannel('/v1/client/status?token=' + encodeURIComponent(session.authToken), (reason, code) => {
|
|
18
18
|
if (!gotResponse) {
|
|
19
|
-
reject(new auth_error_1.default(
|
|
19
|
+
reject(new auth_error_1.default(`Failed to receive secondary authentication with status code ${code}. ${reason}`));
|
|
20
20
|
}
|
|
21
21
|
}, (errorMessage) => {
|
|
22
22
|
gotResponse = true;
|
|
23
|
-
this.log.error('Failed: ' + errorMessage);
|
|
24
23
|
reject(new auth_error_1.default('Failed to receive secondary authentication status: ' + errorMessage));
|
|
25
24
|
}, (data) => {
|
|
26
25
|
gotResponse = true;
|
|
@@ -28,7 +27,7 @@ class AuthStatusActions {
|
|
|
28
27
|
this.log.debug(('Secondary authentication status: ' + data));
|
|
29
28
|
const response = JSON.parse(data);
|
|
30
29
|
if (response.error) {
|
|
31
|
-
reject(new auth_error_1.default(response.error.message, response.error.code, response.next));
|
|
30
|
+
reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
|
|
32
31
|
}
|
|
33
32
|
else {
|
|
34
33
|
session.lastStep = response.next;
|
|
@@ -39,6 +38,7 @@ class AuthStatusActions {
|
|
|
39
38
|
reject(e);
|
|
40
39
|
}
|
|
41
40
|
finally {
|
|
41
|
+
this.log.trace('Closing channel');
|
|
42
42
|
channel.close();
|
|
43
43
|
}
|
|
44
44
|
});
|
|
@@ -10,11 +10,13 @@ export interface DeviceRegistration {
|
|
|
10
10
|
readonly endpoint: string;
|
|
11
11
|
deviceId: string | null;
|
|
12
12
|
fingerprint?: Signal;
|
|
13
|
+
darwinium?: Signal;
|
|
13
14
|
sign: (data: string) => Promise<string>;
|
|
14
15
|
getPublicKey: () => Promise<string>;
|
|
15
16
|
getAuthRegistration: (challenge: string) => Promise<AuthRegistration>;
|
|
16
17
|
setFpSignal: (fpSignal: Signal) => void;
|
|
17
|
-
|
|
18
|
+
setDarwiniumSignal: (dSignal: Signal) => void;
|
|
19
|
+
getSignals: () => Signals;
|
|
18
20
|
}
|
|
19
21
|
export default interface DeviceAuth {
|
|
20
22
|
createRegistration: (options: DeviceRegistrationOptions) => Promise<DeviceRegistration>;
|
|
@@ -5,6 +5,7 @@ export default class DevicePassiveRegisterStep implements AuthStep {
|
|
|
5
5
|
private readonly log;
|
|
6
6
|
readonly name = "device/passive/register";
|
|
7
7
|
execute(session: AuthSession): Promise<string>;
|
|
8
|
+
static hasAssertionResponse(session: AuthSession): boolean;
|
|
8
9
|
private finishRegistration;
|
|
9
10
|
private getFido2Registration;
|
|
10
11
|
}
|
|
@@ -7,6 +7,7 @@ const base64_1 = __importDefault(require("../common/base64"));
|
|
|
7
7
|
const logger_1 = require("../common/logger");
|
|
8
8
|
const auth_error_1 = __importDefault(require("./auth-error"));
|
|
9
9
|
const error_code_1 = __importDefault(require("./error-code"));
|
|
10
|
+
const device_passive_verify_step_1 = __importDefault(require("./device-passive-verify-step"));
|
|
10
11
|
class DevicePassiveRegisterStep {
|
|
11
12
|
constructor() {
|
|
12
13
|
this.log = logger_1.LoggerFactory.getLogger('device-passive-register-step');
|
|
@@ -14,42 +15,56 @@ class DevicePassiveRegisterStep {
|
|
|
14
15
|
}
|
|
15
16
|
execute(session) {
|
|
16
17
|
return new Promise((resolve, reject) => {
|
|
17
|
-
session
|
|
18
|
-
.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.
|
|
37
|
-
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
session.
|
|
41
|
-
|
|
42
|
-
|
|
18
|
+
if (DevicePassiveRegisterStep.hasAssertionResponse(session)) {
|
|
19
|
+
device_passive_verify_step_1.default.runFidoVerify(this.log, session).then(resolve).catch(reject);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
session
|
|
23
|
+
.getDeviceRegistration()
|
|
24
|
+
.then((devRegistration) => {
|
|
25
|
+
if (devRegistration) {
|
|
26
|
+
session
|
|
27
|
+
.embedFpResultToDeviceRegistration(devRegistration)
|
|
28
|
+
.then((devRegistration) => session.embedDarwiniumResultToDeviceRegistration(devRegistration))
|
|
29
|
+
.then((devRegistration) => {
|
|
30
|
+
this.finishRegistration(session, [this.getFido2Registration(session)], devRegistration.getSignals())
|
|
31
|
+
.then(resolve)
|
|
32
|
+
.catch(reject);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
session.platform.deviceAuth
|
|
37
|
+
.createRegistration({
|
|
38
|
+
namespace: session.namespace,
|
|
39
|
+
endpoint: session.backendOrigin,
|
|
40
|
+
})
|
|
41
|
+
.then((devRegistration) => session.embedFpResultToDeviceRegistration(devRegistration))
|
|
42
|
+
.then((devRegistration) => session.embedDarwiniumResultToDeviceRegistration(devRegistration))
|
|
43
|
+
.then((devRegistration) => {
|
|
44
|
+
devRegistration
|
|
45
|
+
.getAuthRegistration(session.challenge)
|
|
46
|
+
.then((authRegistration) => this.finishRegistration(session, [this.getFido2Registration(session), authRegistration], devRegistration.getSignals()))
|
|
47
|
+
.then((next) => {
|
|
48
|
+
devRegistration.deviceId = session.settings.deviceId;
|
|
49
|
+
session.platform.deviceAuth
|
|
50
|
+
.storeRegistration(devRegistration)
|
|
51
|
+
.then(() => resolve(next))
|
|
52
|
+
.catch(reject);
|
|
53
|
+
})
|
|
43
54
|
.catch(reject);
|
|
44
55
|
})
|
|
45
56
|
.catch(reject);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
.catch(reject);
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
.catch(reject);
|
|
60
|
+
}
|
|
51
61
|
});
|
|
52
62
|
}
|
|
63
|
+
static hasAssertionResponse(session) {
|
|
64
|
+
const credential = session.credential;
|
|
65
|
+
const assertion = credential.response;
|
|
66
|
+
return assertion && 'authenticatorData' in assertion && 'signature' in assertion;
|
|
67
|
+
}
|
|
53
68
|
finishRegistration(session, registrations, signals) {
|
|
54
69
|
return new Promise((resolve, reject) => {
|
|
55
70
|
session
|
|
@@ -61,13 +76,18 @@ class DevicePassiveRegisterStep {
|
|
|
61
76
|
})
|
|
62
77
|
.then((response) => {
|
|
63
78
|
if (response.error) {
|
|
64
|
-
reject(new auth_error_1.default(response.error.message, response.error.code, response.next));
|
|
79
|
+
reject(new auth_error_1.default(response.error.message, response.error.code, response.next, false));
|
|
65
80
|
}
|
|
66
81
|
else {
|
|
67
82
|
const data = response.data;
|
|
68
|
-
if (data
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
if (data) {
|
|
84
|
+
if (data.deviceId) {
|
|
85
|
+
session.settings.deviceId = data.deviceId;
|
|
86
|
+
session.settings.fidoPasskeyRegistered = true;
|
|
87
|
+
}
|
|
88
|
+
if (data.scanMessage) {
|
|
89
|
+
session.authMessage = data.scanMessage;
|
|
90
|
+
}
|
|
71
91
|
resolve(response.next);
|
|
72
92
|
}
|
|
73
93
|
else {
|
|
@@ -21,7 +21,10 @@ class DevicePassiveSilentStep {
|
|
|
21
21
|
.getDeviceRegistration()
|
|
22
22
|
.then((registration) => {
|
|
23
23
|
if (registration) {
|
|
24
|
-
session
|
|
24
|
+
session
|
|
25
|
+
.embedFpResultToDeviceRegistration(registration)
|
|
26
|
+
.then((registration) => session.embedDarwiniumResultToDeviceRegistration(registration))
|
|
27
|
+
.then((registration) => {
|
|
25
28
|
this.verify(session, registration).then(resolve).catch(reject);
|
|
26
29
|
});
|
|
27
30
|
}
|
|
@@ -36,6 +39,7 @@ class DevicePassiveSilentStep {
|
|
|
36
39
|
endpoint: session.backendOrigin,
|
|
37
40
|
})
|
|
38
41
|
.then((registration) => session.embedFpResultToDeviceRegistration(registration))
|
|
42
|
+
.then((registration) => session.embedDarwiniumResultToDeviceRegistration(registration))
|
|
39
43
|
.then((registration) => this.register(session, registration))
|
|
40
44
|
.then(resolve)
|
|
41
45
|
.catch(reject);
|
|
@@ -83,6 +87,10 @@ class DevicePassiveSilentStep {
|
|
|
83
87
|
session.settings.fidoPasskeyRegistered = deviceRegisterAuthResp.data.passkey;
|
|
84
88
|
registration.deviceId = deviceId;
|
|
85
89
|
this.log.debug('Device ID: ' + deviceId);
|
|
90
|
+
const data = response.data;
|
|
91
|
+
if (data && data.scanMessage) {
|
|
92
|
+
session.authMessage = data.scanMessage;
|
|
93
|
+
}
|
|
86
94
|
session.platform.deviceAuth
|
|
87
95
|
.storeRegistration(registration)
|
|
88
96
|
.then(() => resolve(response.next))
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import AuthSession from './auth-session';
|
|
2
2
|
import AuthStep from './auth-step';
|
|
3
|
-
import { DeviceRole } from '../authenticator-builder';
|
|
3
|
+
import { DeviceRole, PasskeyAlreadyExistCallback } from '../authenticator-builder';
|
|
4
4
|
import { AuthStatusActions } from './auth-status-actions';
|
|
5
|
+
import { Signals } from './auth-request';
|
|
5
6
|
export declare class DevicePassiveActions extends AuthStatusActions {
|
|
6
7
|
protected log: import("../common/logger").Logger;
|
|
7
8
|
private readonly getDisplayName;
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
private handler?;
|
|
10
|
+
static readonly NO_REQUEST_CREDS_FOUND = "Passkey has already been registered but found no CredentialRequestOptions in the fido/register/start response payload";
|
|
11
|
+
static readonly NO_CREDS_FOUND = "Neither credCreateOptions nor credRequestOptions are found in the fido/register/start response payload";
|
|
12
|
+
static readonly USER_NOT_ACCEPTING_RESPONSE = "User not accepting to continue by reusing the existing passkey with user response";
|
|
13
|
+
protected constructor(getDisplayName?: () => string | null, handler?: PasskeyAlreadyExistCallback);
|
|
14
|
+
protected register(session: AuthSession, signals?: Signals): Promise<string>;
|
|
10
15
|
protected verify(session: AuthSession): Promise<string>;
|
|
16
|
+
private createCredentials;
|
|
17
|
+
private parseCredRequestOptions;
|
|
18
|
+
private getCredentials;
|
|
11
19
|
}
|
|
12
20
|
export default class DevicePassiveStep extends DevicePassiveActions implements AuthStep {
|
|
13
21
|
static readonly NAME = "device/passive";
|
|
14
22
|
readonly name = "device/passive";
|
|
15
23
|
private readonly role;
|
|
16
|
-
constructor(getDisplayName?: () => string | null, role?: DeviceRole);
|
|
24
|
+
constructor(getDisplayName?: () => string | null, handler?: PasskeyAlreadyExistCallback, role?: DeviceRole);
|
|
17
25
|
execute(session: AuthSession): Promise<string>;
|
|
18
26
|
}
|