@dfns/sdk-react-native 0.3.2 → 0.3.3-alpha.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/index.d.ts +8 -6
- package/index.js +95 -15
- package/package.json +2 -1
package/index.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { AllowCredential, CredentialSigner, CredentialStore, Fido2Assertion, Fido2Attestation, UserRegistrationChallenge } from '@dfns/sdk';
|
|
2
2
|
export declare const DEFAULT_WAIT_TIMEOUT = 60000;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
type PasskeysOptions = {
|
|
4
|
+
rpId: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare class PasskeysSigner implements CredentialSigner<Fido2Assertion>, CredentialStore<Fido2Attestation> {
|
|
8
|
+
private inner;
|
|
9
|
+
constructor(options: PasskeysOptions);
|
|
9
10
|
sign(challenge: string, allowCredentials: {
|
|
10
11
|
key: AllowCredential[];
|
|
11
12
|
webauthn: AllowCredential[];
|
|
12
13
|
}): Promise<Fido2Assertion>;
|
|
13
14
|
create(challenge: UserRegistrationChallenge): Promise<Fido2Attestation>;
|
|
14
15
|
}
|
|
16
|
+
export {};
|
package/index.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.PasskeysSigner = exports.DEFAULT_WAIT_TIMEOUT = void 0;
|
|
4
4
|
const utils_1 = require("@dfns/sdk/utils");
|
|
5
|
-
const
|
|
5
|
+
const react_native_1 = require("react-native");
|
|
6
6
|
const react_native_passkey_1 = require("react-native-passkey");
|
|
7
7
|
exports.DEFAULT_WAIT_TIMEOUT = 60000;
|
|
8
|
-
|
|
8
|
+
const b64StandardToUrlSafe = (standard) => {
|
|
9
|
+
return standard.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
10
|
+
};
|
|
11
|
+
const b64UrlSafeToStandard = (urlSafe) => {
|
|
12
|
+
return (urlSafe + '==='.slice((urlSafe.length + 3) % 4)).replace(/-/g, '+').replace(/_/g, '/');
|
|
13
|
+
};
|
|
14
|
+
class AndroidPasskeys {
|
|
9
15
|
constructor(options) {
|
|
10
16
|
this.options = options;
|
|
11
17
|
}
|
|
@@ -25,11 +31,11 @@ class PasskeySigner {
|
|
|
25
31
|
return {
|
|
26
32
|
kind: 'Fido2',
|
|
27
33
|
credentialAssertion: {
|
|
28
|
-
credId: credential.id,
|
|
29
|
-
clientData:
|
|
30
|
-
authenticatorData:
|
|
31
|
-
signature:
|
|
32
|
-
userHandle: credential.response.userHandle
|
|
34
|
+
credId: b64StandardToUrlSafe(credential.id),
|
|
35
|
+
clientData: credential.response.clientDataJSON,
|
|
36
|
+
authenticatorData: credential.response.authenticatorData,
|
|
37
|
+
signature: credential.response.signature,
|
|
38
|
+
userHandle: credential.response.userHandle,
|
|
33
39
|
},
|
|
34
40
|
};
|
|
35
41
|
}
|
|
@@ -52,17 +58,91 @@ class PasskeySigner {
|
|
|
52
58
|
timeout: this.options.timeout ?? exports.DEFAULT_WAIT_TIMEOUT,
|
|
53
59
|
};
|
|
54
60
|
const result = await react_native_passkey_1.Passkey.register(options);
|
|
55
|
-
if (result === null) {
|
|
56
|
-
throw Error(`Failed to create and sign with Passkey credential`);
|
|
57
|
-
}
|
|
58
61
|
return {
|
|
59
62
|
credentialKind: 'Fido2',
|
|
60
63
|
credentialInfo: {
|
|
61
|
-
credId: result.id,
|
|
62
|
-
attestationData:
|
|
63
|
-
clientData:
|
|
64
|
+
credId: b64StandardToUrlSafe(result.id),
|
|
65
|
+
attestationData: result.response.attestationObject,
|
|
66
|
+
clientData: result.response.clientDataJSON,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
class iOsPasskeys {
|
|
72
|
+
constructor(options) {
|
|
73
|
+
this.options = options;
|
|
74
|
+
}
|
|
75
|
+
async sign(challenge, allowCredentials) {
|
|
76
|
+
const request = {
|
|
77
|
+
challenge: b64UrlSafeToStandard(challenge),
|
|
78
|
+
allowCredentials: allowCredentials.webauthn.map(({ id, type, transports }) => ({
|
|
79
|
+
id: b64UrlSafeToStandard(id),
|
|
80
|
+
type,
|
|
81
|
+
transports: transports ?? [],
|
|
82
|
+
})),
|
|
83
|
+
rpId: this.options.rpId,
|
|
84
|
+
userVerification: 'required',
|
|
85
|
+
timeout: this.options.timeout ?? exports.DEFAULT_WAIT_TIMEOUT,
|
|
86
|
+
};
|
|
87
|
+
const credential = await react_native_passkey_1.Passkey.authenticate(request);
|
|
88
|
+
return {
|
|
89
|
+
kind: 'Fido2',
|
|
90
|
+
credentialAssertion: {
|
|
91
|
+
credId: b64StandardToUrlSafe(credential.id),
|
|
92
|
+
clientData: b64StandardToUrlSafe(credential.response.clientDataJSON),
|
|
93
|
+
authenticatorData: b64StandardToUrlSafe(credential.response.authenticatorData),
|
|
94
|
+
signature: b64StandardToUrlSafe(credential.response.signature),
|
|
95
|
+
userHandle: b64StandardToUrlSafe(credential.response.userHandle),
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
async create(challenge) {
|
|
100
|
+
const options = {
|
|
101
|
+
challenge: b64UrlSafeToStandard(challenge.challenge),
|
|
102
|
+
pubKeyCredParams: challenge.pubKeyCredParams,
|
|
103
|
+
rp: challenge.rp,
|
|
104
|
+
user: {
|
|
105
|
+
displayName: challenge.user.displayName,
|
|
106
|
+
id: (0, utils_1.toBase64Url)(challenge.user.id),
|
|
107
|
+
name: challenge.user.name,
|
|
108
|
+
},
|
|
109
|
+
attestation: challenge.attestation,
|
|
110
|
+
excludeCredentials: challenge.excludeCredentials.map((cred) => ({
|
|
111
|
+
id: cred.id,
|
|
112
|
+
type: cred.type,
|
|
113
|
+
})),
|
|
114
|
+
authenticatorSelection: challenge.authenticatorSelection,
|
|
115
|
+
timeout: this.options.timeout ?? exports.DEFAULT_WAIT_TIMEOUT,
|
|
116
|
+
};
|
|
117
|
+
const result = await react_native_passkey_1.Passkey.register(options);
|
|
118
|
+
return {
|
|
119
|
+
credentialKind: 'Fido2',
|
|
120
|
+
credentialInfo: {
|
|
121
|
+
credId: b64StandardToUrlSafe(result.id),
|
|
122
|
+
attestationData: b64StandardToUrlSafe(result.response.attestationObject),
|
|
123
|
+
clientData: b64StandardToUrlSafe(result.response.clientDataJSON),
|
|
64
124
|
},
|
|
65
125
|
};
|
|
66
126
|
}
|
|
67
127
|
}
|
|
68
|
-
|
|
128
|
+
class PasskeysSigner {
|
|
129
|
+
constructor(options) {
|
|
130
|
+
switch (react_native_1.Platform.OS) {
|
|
131
|
+
case 'android':
|
|
132
|
+
this.inner = new AndroidPasskeys(options);
|
|
133
|
+
break;
|
|
134
|
+
case 'ios':
|
|
135
|
+
this.inner = new iOsPasskeys(options);
|
|
136
|
+
break;
|
|
137
|
+
default:
|
|
138
|
+
throw Error(`${react_native_1.Platform.OS} not supported`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async sign(challenge, allowCredentials) {
|
|
142
|
+
return this.inner.sign(challenge, allowCredentials);
|
|
143
|
+
}
|
|
144
|
+
async create(challenge) {
|
|
145
|
+
return this.inner.create(challenge);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.PasskeysSigner = PasskeysSigner;
|
package/package.json
CHANGED