Skip to content

Commit 2e7c818

Browse files
authored
Merge pull request #762 from Web3Auth/passkeys-sfa-docs
Added docs for passkeys SFA
2 parents 63f1cb4 + b5bebd7 commit 2e7c818

2 files changed

Lines changed: 336 additions & 0 deletions

File tree

Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
---
2+
title: Passkeys SFA Plugin
3+
displayed_sidebar: sdk
4+
description: "Web3Auth - Passkeys SFA Plugin | Documentation - Web3Auth"
5+
---
6+
7+
import TabItem from "@theme/TabItem";
8+
import Tabs from "@theme/Tabs";
9+
10+
### [`@web3auth/passkeys-sfa-plugin`](https://npmjs.com/package/@web3auth/passkeys-sfa-plugin)
11+
12+
The Passkeys SFA Plugin allows your application to use passkeys for secure and easy authentication.
13+
This plugin integrates seamlessly with Web3Auth Single Factor Auth (SFA) Web SDK, enabling passkey
14+
registration, login, and management functionalities.
15+
16+
**This Documentation is based on the `8.0.1` SDK Version.**
17+
18+
:::note Note
19+
20+
Passkeys SFA Plugin is designed for Web3Auth Single Factor Auth (SFA) Web SDK.
21+
22+
:::
23+
24+
## Installation
25+
26+
```bash npm2yarn
27+
npm install --save @web3auth/passkeys-sfa-plugin
28+
```
29+
30+
## Initialization
31+
32+
Import the `PasskeysPlugin` **class** from `@web3auth/passkeys-sfa-plugin`.
33+
34+
```javascript
35+
import { PasskeysPlugin } from "@web3auth/passkeys-sfa-plugin";
36+
```
37+
38+
#### Assign the `PasskeysPlugin` class to a variable
39+
40+
After creating your Web3Auth SFA instance, you need to initialize the Passkeys Plugin and add it to
41+
the class for further usage.
42+
43+
```javascript
44+
const passkeysPlugin = new PasskeysPlugin(options);
45+
```
46+
47+
This constructor takes an object with `IPasskeysPluginOptions` as input.
48+
49+
### Arguments
50+
51+
While initializing the Passkeys plugin, you need to pass the following parameters to the
52+
constructor:
53+
54+
<Tabs
55+
defaultValue="table"
56+
values={[
57+
{ label: "Table", value: "table" },
58+
{ label: "Interface", value: "interface" },
59+
]}
60+
>
61+
62+
<TabItem value="table">
63+
64+
| Parameter | Description |
65+
| ----------- | --------------------------------------------------------------------------------------------- |
66+
| `rpID?` | Your app domain. If your app is hosted on "your.app.xyz", the RPID can be "your.app.xyz". |
67+
| `rpName?` | Name of your app. We recommend setting it to the correctly capitalized name of your app. |
68+
| `buildEnv?` | Specifies the build environment to use: `production`, `staging`, `testing`, or `development`. |
69+
70+
</TabItem>
71+
72+
<TabItem value="interface">
73+
74+
```tsx
75+
export interface IPasskeysPluginOptions {
76+
buildEnv?: BUILD_ENV_TYPE;
77+
/**
78+
* `rpID` should be your app domain.
79+
*
80+
* If your app is hosted on "your.app.xyz" the RPID can be "your.app.xyz" or "app.xyz".
81+
*
82+
* Be aware: if you create passkeys on "your.app.xyz", they won't be usable on other subdomains (e.g. "other.app.xyz").
83+
* So unless you have good reasons not to, use the top-level domain as the RPID.
84+
*
85+
* `rpID` will show up in the initial registration popup:
86+
*
87+
* @defaultValue tld
88+
*/
89+
rpID?: string;
90+
/**
91+
* `rpName` doesn't show up in the popup so can be set to anything.
92+
*
93+
* We recommend setting it to the correctly capitalized name of your app,
94+
* in case browsers start showing it in their native UIs in the future.
95+
*
96+
* @defaultValue window.title || window.location.hostname
97+
*/
98+
rpName?: string;
99+
}
100+
```
101+
102+
</TabItem>
103+
104+
</Tabs>
105+
106+
#### Add the `passkeysPlugin` class to your Web3Auth SFA instance
107+
108+
After initializing the `passkeysPlugin`, use the `addPlugin()` function to add it to your Web3Auth
109+
SFA instance.
110+
111+
```javascript
112+
web3AuthInstance.addPlugin(passkeysPlugin);
113+
```
114+
115+
### Example
116+
117+
```javascript
118+
import { PasskeysPlugin } from "@web3auth/passkeys-sfa-plugin";
119+
120+
const passkeysPlugin = new PasskeysPlugin({
121+
rpID: "your.app.xyz",
122+
rpName: "Your App",
123+
});
124+
125+
web3auth.addPlugin(passkeysPlugin); // Add the plugin to web3auth
126+
127+
// Register a new passkey
128+
await passkeysPlugin.registerPasskey({ username: "user@example.com" });
129+
130+
// Login with an existing passkey
131+
await passkeysPlugin.loginWithPasskey({ authenticatorId: "authenticator_id" });
132+
133+
// List all registered passkeys
134+
const passkeys = await passkeysPlugin.listAllPasskeys();
135+
console.log(passkeys);
136+
```
137+
138+
:::note Note
139+
140+
First, a user needs to log in the usual way, and then register a passkey. From the next time, they
141+
can log in using a passkey.
142+
143+
:::
144+
145+
## Using Passkeys SFA Plugin
146+
147+
### `registerPasskey()`
148+
149+
Registers a new passkey for the user.
150+
151+
#### Parameters
152+
153+
| Parameter | Description |
154+
| -------------------------- | ---------------------------------------------------------------------------------------------------- |
155+
| `authenticatorAttachment?` | Option to restrict the type of authenticators that can be registered. |
156+
| `username?` | The passkey in the user device will be saved with this name. Default is `loginProvider\|verifierId.` |
157+
158+
#### Example
159+
160+
```javascript
161+
await passkeysPlugin.registerPasskey({
162+
username: "user@example.com",
163+
authenticatorAttachment: "platform",
164+
});
165+
```
166+
167+
### `loginWithPasskey()`
168+
169+
Logs in the user with an existing passkey.
170+
171+
#### Parameters
172+
173+
| Parameter | Description |
174+
| ------------------ | --------------------------------------------- |
175+
| `authenticatorId?` | The ID of the authenticator to use for login. |
176+
177+
#### Example
178+
179+
```javascript
180+
await passkeysPlugin.loginWithPasskey({
181+
authenticatorId: "authenticator_id",
182+
});
183+
```
184+
185+
### `listAllPasskeys()`
186+
187+
Lists all registered passkeys for the user.
188+
189+
#### Example
190+
191+
```javascript
192+
const passkeys = await passkeysPlugin.listAllPasskeys();
193+
console.log(passkeys);
194+
```
195+
196+
## Using with Web3Auth SFA
197+
198+
:::note Note
199+
200+
Below are two files, `App.tsx` and `utils.ts`, demonstrating the implementation of the Passkeys SFA
201+
Plugin. The `utils.ts` file is kept non-opinionated and can be configured according to your
202+
requirements for your users.
203+
204+
:::
205+
206+
<Tabs
207+
defaultValue="App.tsx"
208+
values={[
209+
{ label: "App.tsx", value: "App.tsx" },
210+
{ label: "utils.ts", value: "utils.ts" },
211+
]}
212+
>
213+
214+
<TabItem value="App.tsx">
215+
216+
```javascript
217+
import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK, IProvider } from "@web3auth/base";
218+
import Web3Auth from "@web3auth/single-factor-auth";
219+
import { PasskeysPlugin } from "@web3auth/passkeys-sfa-plugin";
220+
221+
const clientId = "Your_Web3Auth_Client_ID";
222+
223+
const chainConfig = {
224+
chainId: "0x1", // Please use 0x1 for Mainnet
225+
rpcTarget: "https://rpc.ankr.com/eth",
226+
displayName: "Ethereum Mainnet",
227+
blockExplorerUrl: "https://etherscan.io/",
228+
ticker: "ETH",
229+
tickerName: "Ethereum",
230+
logo: "https://images.toruswallet.io/eth.svg",
231+
};
232+
233+
const web3AuthOptions = {
234+
clientId,
235+
chainConfig: { ...chainConfig, chainNamespace: CHAIN_NAMESPACES.EIP155 },
236+
web3AuthNetwork: WEB3AUTH_NETWORK.MAINNET,
237+
};
238+
239+
const web3auth = new Web3Auth(web3AuthOptions);
240+
241+
const passkeysPlugin = new PasskeysPlugin({
242+
rpID: "your.app.xyz",
243+
rpName: "Your App",
244+
});
245+
246+
web3auth.addPlugin(passkeysPlugin); // Add the plugin to web3auth
247+
248+
// Register a new passkey
249+
await passkeysPlugin.registerPasskey({ username: "user@example.com" });
250+
251+
// Login with an existing passkey
252+
await passkeysPlugin.loginWithPasskey({ authenticatorId: "authenticator_id" });
253+
254+
// List all registered passkeys
255+
const passkeys = await passkeysPlugin.listAllPasskeys();
256+
console.log(passkeys);
257+
```
258+
259+
</TabItem>
260+
261+
<TabItem value="utils.ts">
262+
263+
```javascript
264+
import bowser from "bowser";
265+
266+
const PASSKEYS_ALLOWED_MAP = [bowser.OS_MAP.iOS, bowser.OS_MAP.MacOS, bowser.OS_MAP.Android, bowser.OS_MAP.Windows];
267+
268+
const getWindowsVersion = (osVersion: string) => {
269+
const windowsVersionRegex = /NT (\d+\.\d+)/;
270+
const match = osVersion.match(windowsVersionRegex);
271+
if (match) return parseInt(match[1], 10);
272+
return 0;
273+
};
274+
275+
const checkIfOSIsSupported = (osName: string, osVersion: string) => {
276+
if (!PASSKEYS_ALLOWED_MAP.includes(osName)) return false;
277+
if (osName === bowser.OS_MAP.MacOS) return true;
278+
switch (osName) {
279+
case bowser.OS_MAP.iOS: {
280+
const version = parseInt(osVersion.split(".")[0], 10);
281+
return version >= 16;
282+
}
283+
case bowser.OS_MAP.Android: {
284+
const version = parseInt(osVersion.split(".")[0], 10);
285+
return version >= 9;
286+
}
287+
case bowser.OS_MAP.Windows: {
288+
const version = getWindowsVersion(osVersion);
289+
return version >= 10;
290+
}
291+
default:
292+
return false;
293+
}
294+
};
295+
296+
export function shouldSupportPasskey(): { isBrowserSupported: boolean; isOsSupported: boolean; supported
297+
298+
Browser?: Record<string, string> } {
299+
const browser = bowser.getParser(navigator.userAgent);
300+
const osDetails = browser.parseOS();
301+
if (!osDetails) return { isBrowserSupported: false, isOsSupported: false };
302+
const osName = osDetails.name || "";
303+
const result = checkIfOSIsSupported(osName, osDetails.version || "");
304+
if (!result) return { isBrowserSupported: false, isOsSupported: false };
305+
const browserData: Record<string, Record<string, string>> = {
306+
iOS: {
307+
safari: ">=16",
308+
chrome: ">=108",
309+
},
310+
macOS: {
311+
safari: ">=16",
312+
chrome: ">=108",
313+
firefox: ">=122",
314+
},
315+
Android: {
316+
chrome: ">=108",
317+
},
318+
Windows: {
319+
edge: ">=108",
320+
chrome: ">=108",
321+
},
322+
};
323+
const isBrowserSupported = browser.satisfies({ ...browserData }) || false;
324+
return { isBrowserSupported, isOsSupported: true, supportedBrowser: browserData[osName] };
325+
}
326+
327+
export function browserSupportsWebAuthn() {
328+
return (window?.PublicKeyCredential !== undefined &&
329+
typeof window.PublicKeyCredential === 'function');
330+
}
331+
```
332+
333+
</TabItem>
334+
335+
</Tabs>

sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ const sidebars: SidebarsConfig = {
13481348
label: "Wallet Services",
13491349
items: ["sdk/wallet-services/wallet-services", "sdk/wallet-services/wallet-services-hooks"],
13501350
},
1351+
"sdk/passkeys-sfa/passkeys-sfa",
13511352
{
13521353
type: "category",
13531354
label: "Providers",

0 commit comments

Comments
 (0)