@dfns/sdk-react-native 0.5.10-alpha.2 → 0.6.0-rc.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/index.d.ts +20 -3
- package/index.js +30 -15
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import { CredentialSigner, CredentialStore, Fido2Assertion, Fido2Attestation, UserActionChallenge, UserRegistrationChallenge } from '@dfns/sdk';
|
|
2
2
|
export declare const DEFAULT_WAIT_TIMEOUT = 60000;
|
|
3
|
-
|
|
3
|
+
interface PasskeysSignerConf {
|
|
4
|
+
/**
|
|
5
|
+
* The relying party identifies your application to users, when users create/use passkeys. (Read more [here](https://www.w3.org/TR/webauthn-2/#relying-party)).
|
|
6
|
+
* - id: The relying party identifier is a valid domain string identifying the WebAuthn Relying Party.
|
|
7
|
+
* In other words, its the domain your application is running on, which will be tied to the passkeys that users create.
|
|
8
|
+
* We advise to use the root domain, not the full domain (eg `acme.com`, not `app.acme.com` nor `foo.app.acme.com`), that way, passkeys created
|
|
9
|
+
* by your users can be re-used on other subdomains (eg. on `foo.acme.com` and `bar.acme.com`) in the future. Read more [here](https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#rp).
|
|
10
|
+
* - name: A string representing the name of the relying party (e.g. "Acme"). This is the name the user will be presented with when creating or validating a WebAuthn operation.
|
|
11
|
+
*/
|
|
12
|
+
relyingParty: {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Timeout to use for navigotor.credentials calls. That's the time after which if user did not successfully
|
|
18
|
+
* select and use his passkey, an error will be thrown by webauthn client. Read more [here](https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#timeout).
|
|
19
|
+
* */
|
|
4
20
|
timeout?: number;
|
|
5
|
-
}
|
|
21
|
+
}
|
|
6
22
|
export declare class PasskeysSigner implements CredentialSigner<Fido2Assertion>, CredentialStore<Fido2Attestation> {
|
|
7
23
|
private platform;
|
|
8
|
-
constructor(
|
|
24
|
+
constructor(conf: PasskeysSignerConf);
|
|
9
25
|
sign(challenge: UserActionChallenge): Promise<Fido2Assertion>;
|
|
10
26
|
create(challenge: UserRegistrationChallenge): Promise<Fido2Attestation>;
|
|
11
27
|
}
|
|
28
|
+
export {};
|
package/index.js
CHANGED
|
@@ -15,16 +15,20 @@ const b64UrlSafeToStandard = (urlSafe) => {
|
|
|
15
15
|
// react-native-passkey is incorrect encoding the credId with standard base64 for
|
|
16
16
|
// some reason. we have to undo that.
|
|
17
17
|
class AndroidPasskeys {
|
|
18
|
-
constructor(
|
|
19
|
-
this.
|
|
18
|
+
constructor(conf) {
|
|
19
|
+
this.conf = conf;
|
|
20
|
+
if (!this.conf?.relyingParty?.id || !this.conf?.relyingParty?.name) {
|
|
21
|
+
throw new sdk_1.DfnsError(-1, `Relying party ID and name must be specified in the WebauthnSigner initializer`);
|
|
22
|
+
}
|
|
20
23
|
}
|
|
21
24
|
async sign(challenge) {
|
|
25
|
+
checkSpecifiedRpIdIsWhitelisted(this.conf.relyingParty.id, challenge.allowedRelyingParties);
|
|
22
26
|
const request = {
|
|
23
27
|
challenge: challenge.challenge,
|
|
24
28
|
allowCredentials: challenge.allowCredentials.webauthn,
|
|
25
|
-
rpId:
|
|
29
|
+
rpId: this.conf.relyingParty.id,
|
|
26
30
|
userVerification: challenge.userVerification,
|
|
27
|
-
timeout: this.
|
|
31
|
+
timeout: this.conf.timeout ?? exports.DEFAULT_WAIT_TIMEOUT,
|
|
28
32
|
};
|
|
29
33
|
const credential = await react_native_passkey_1.Passkey.authenticate(request);
|
|
30
34
|
return {
|
|
@@ -39,10 +43,11 @@ class AndroidPasskeys {
|
|
|
39
43
|
};
|
|
40
44
|
}
|
|
41
45
|
async create(challenge) {
|
|
46
|
+
checkSpecifiedRpIdIsWhitelisted(this.conf.relyingParty.id, challenge.allowedRelyingParties);
|
|
42
47
|
const request = {
|
|
43
48
|
challenge: challenge.challenge,
|
|
44
49
|
pubKeyCredParams: challenge.pubKeyCredParams,
|
|
45
|
-
rp:
|
|
50
|
+
rp: this.conf.relyingParty,
|
|
46
51
|
user: {
|
|
47
52
|
displayName: challenge.user.displayName,
|
|
48
53
|
id: (0, utils_1.toBase64Url)(challenge.user.id),
|
|
@@ -54,7 +59,7 @@ class AndroidPasskeys {
|
|
|
54
59
|
type: v.type,
|
|
55
60
|
})),
|
|
56
61
|
authenticatorSelection: challenge.authenticatorSelection,
|
|
57
|
-
timeout: this.
|
|
62
|
+
timeout: this.conf.timeout ?? exports.DEFAULT_WAIT_TIMEOUT,
|
|
58
63
|
};
|
|
59
64
|
const result = await react_native_passkey_1.Passkey.register(request);
|
|
60
65
|
return {
|
|
@@ -71,19 +76,23 @@ class AndroidPasskeys {
|
|
|
71
76
|
// are standard base64 encoded instead of base64url encoded. we have to convert the
|
|
72
77
|
// encoding in both directions.
|
|
73
78
|
class iOSPasskeys {
|
|
74
|
-
constructor(
|
|
75
|
-
this.
|
|
79
|
+
constructor(conf) {
|
|
80
|
+
this.conf = conf;
|
|
81
|
+
if (!this.conf?.relyingParty?.id || !this.conf?.relyingParty?.name) {
|
|
82
|
+
throw new sdk_1.DfnsError(-1, `Relying party ID and name must be specified in the WebauthnSigner initializer`);
|
|
83
|
+
}
|
|
76
84
|
}
|
|
77
85
|
async sign(challenge) {
|
|
86
|
+
checkSpecifiedRpIdIsWhitelisted(this.conf.relyingParty.id, challenge.allowedRelyingParties);
|
|
78
87
|
const request = {
|
|
79
88
|
challenge: b64UrlSafeToStandard(challenge.challenge),
|
|
80
89
|
allowCredentials: challenge.allowCredentials.webauthn.map(({ id, type }) => ({
|
|
81
90
|
id: b64UrlSafeToStandard(id),
|
|
82
91
|
type,
|
|
83
92
|
})),
|
|
84
|
-
rpId:
|
|
93
|
+
rpId: this.conf.relyingParty.id,
|
|
85
94
|
userVerification: 'preferred',
|
|
86
|
-
timeout: this.
|
|
95
|
+
timeout: this.conf.timeout ?? exports.DEFAULT_WAIT_TIMEOUT,
|
|
87
96
|
};
|
|
88
97
|
const credential = await react_native_passkey_1.Passkey.authenticate(request);
|
|
89
98
|
return {
|
|
@@ -98,10 +107,11 @@ class iOSPasskeys {
|
|
|
98
107
|
};
|
|
99
108
|
}
|
|
100
109
|
async create(challenge) {
|
|
110
|
+
checkSpecifiedRpIdIsWhitelisted(this.conf.relyingParty.id, challenge.allowedRelyingParties);
|
|
101
111
|
const request = {
|
|
102
112
|
challenge: b64UrlSafeToStandard(challenge.challenge),
|
|
103
113
|
pubKeyCredParams: challenge.pubKeyCredParams,
|
|
104
|
-
rp:
|
|
114
|
+
rp: this.conf.relyingParty,
|
|
105
115
|
user: {
|
|
106
116
|
displayName: challenge.user.displayName,
|
|
107
117
|
id: (0, utils_1.toBase64Url)(challenge.user.id),
|
|
@@ -113,7 +123,7 @@ class iOSPasskeys {
|
|
|
113
123
|
type,
|
|
114
124
|
})),
|
|
115
125
|
authenticatorSelection: challenge.authenticatorSelection,
|
|
116
|
-
timeout: this.
|
|
126
|
+
timeout: this.conf.timeout ?? exports.DEFAULT_WAIT_TIMEOUT,
|
|
117
127
|
};
|
|
118
128
|
const result = await react_native_passkey_1.Passkey.register(request);
|
|
119
129
|
return {
|
|
@@ -127,13 +137,13 @@ class iOSPasskeys {
|
|
|
127
137
|
}
|
|
128
138
|
}
|
|
129
139
|
class PasskeysSigner {
|
|
130
|
-
constructor(
|
|
140
|
+
constructor(conf) {
|
|
131
141
|
switch (react_native_1.Platform.OS) {
|
|
132
142
|
case 'android':
|
|
133
|
-
this.platform = new AndroidPasskeys(
|
|
143
|
+
this.platform = new AndroidPasskeys(conf);
|
|
134
144
|
break;
|
|
135
145
|
case 'ios':
|
|
136
|
-
this.platform = new iOSPasskeys(
|
|
146
|
+
this.platform = new iOSPasskeys(conf);
|
|
137
147
|
break;
|
|
138
148
|
default:
|
|
139
149
|
throw new sdk_1.DfnsError(-1, `${react_native_1.Platform.OS} is not supported`);
|
|
@@ -147,3 +157,8 @@ class PasskeysSigner {
|
|
|
147
157
|
}
|
|
148
158
|
}
|
|
149
159
|
exports.PasskeysSigner = PasskeysSigner;
|
|
160
|
+
const checkSpecifiedRpIdIsWhitelisted = (rpId, allowedRpIds) => {
|
|
161
|
+
if (!allowedRpIds.includes(rpId)) {
|
|
162
|
+
throw new sdk_1.DfnsError(-1, `The specified relying party id is not whitelisted in the Dfns organisation. Ask your Dfns admin to whitelist rpId "${rpId}" first, or use a whitelisted one: (${allowedRpIds.join(', ')})`);
|
|
163
|
+
}
|
|
164
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dfns/sdk-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-rc.0",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"buffer": "6.0.3",
|
|
6
6
|
"cross-fetch": "3.1.6",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"uuid": "9.0.0"
|
|
10
10
|
},
|
|
11
11
|
"peerDependencies": {
|
|
12
|
-
"@dfns/sdk": "0.
|
|
12
|
+
"@dfns/sdk": "0.6.0-rc.0"
|
|
13
13
|
},
|
|
14
14
|
"main": "./index.js",
|
|
15
15
|
"type": "commonjs"
|