Skip to content

Add the initial webauthn docs #896

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vale/SuperTokens/headings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ exceptions:
- JWTs
- UI
- Token
- WebAuthn
4 changes: 4 additions & 0 deletions docs/authentication/_passkeys/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Passkeys",
"position": 7
}
294 changes: 294 additions & 0 deletions docs/authentication/_passkeys/customization.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
---
title: Customization
hide_title: true
sidebar_position: 4
---

import { BackendTabs } from "/src/components/Tabs";

# Customization

## Overview

Like the other **SuperTokens** authentication recipes, you can customize the `WebAuthn` flow through different configuration options and overrides.
The following page describes the options that you can change and the different scenarios enabled through customization.

---

## Backend recipe configuration


The backend recipe accepts the following properties during initialization:

| Option | Description | Default |
|--------|-------------|---------|
| `getRelyingPartyId` | Sets the domain name associated with the WebAuthn credentials. This helps ensure that only your domain uses the credentials. | The `apiDomain` value that you have set in `appConfig` |
| `getRelyingPartyName` | Sets a human-readable name for your application. The name appears to users during the WebAuthn registration process. | The `appName` value that you have set in `appConfig` |
| `getOrigin` | Configures the origin URL that WebAuthn credentials bind to. This should match your application's domain and protocol. | Origin of the request |
| `emailDelivery` | Configures how the system builds and sends verification emails to users. Read the [email delivery page](/docs/platform-configuration/email-delivery) for more information. | Default email service |
| `validateEmailAddress` | Adds custom validation logic for email addresses. | Basic email format validation |

All the properties are optional.

<BackendTabs>

<BackendTabs.TabItem value="nodejs">

```ts
import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import WebAuthn from "supertokens-node/recipe/webauthn";

supertokens.init({
framework: "express",
supertokens: {
// https://try.supertokens.com is for demo purposes. Replace this with the address of your core instance (sign up on supertokens.com), or self host a core.
connectionURI: "https://try.supertokens.com",
// apiKey: <API_KEY(if configured)>,
},
appInfo: {
// learn more about this on https://supertokens.com/docs/session/appinfo
appName: "<YOUR_APP_NAME>",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth"
},
recipeList: [
WebAuthn.init({
getOrigin: () => {
return "https://example.com";
},
getRelyingPartyId: () => {
return "example.com";
},
getRelyingPartyName: () => {
return "example";
},
}),
Session.init() // initializes session features
]
});
```

</BackendTabs.TabItem>

<BackendTabs.TabItem value="go">

:::caution

At the moment there is no support for using passkeys authentication in the Go SDK.

:::

</BackendTabs.TabItem>

<BackendTabs.TabItem value="python">

:::caution

At the moment there is no support for using passkeys authentication in the Python SDK.

:::

</BackendTabs.TabItem>

</BackendTabs>

---

## Credential generation

The client generates the credentials based on the options provided by the backend SDK.
The frontend SDK uses the [`navigator.credentials.created`](https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/create) function to resolve this.

To change the options used to generate credentials, you need to override the `registerOptions` function.

<BackendTabs>

<BackendTabs.TabItem value="nodejs">

```ts
import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import WebAuthn from "supertokens-node/recipe/webauthn";

supertokens.init({
framework: "express",
supertokens: {
// https://try.supertokens.com is for demo purposes. Replace this with the address of your core instance (sign up on supertokens.com), or self host a core.
connectionURI: "https://try.supertokens.com",
// apiKey: <API_KEY(if configured)>,
},
appInfo: {
// learn more about this on https://supertokens.com/docs/session/appinfo
appName: "<YOUR_APP_NAME>",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth"
},
recipeList: [
WebAuthn.init({
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
registerOptions: (input) => {
return originalImplementation.registerOptions({
...input,
attestation: "direct",
residentKey: "required",
timeout: 10 * 1000,
userVerification: "required",
displayName: "John Doe",
supportedAlgorithms: [-257],
relyingPartyId: 'example.com',
relyingPartyName: 'example',
origin: 'https://example.com',
});
},
};
},
},
}),
Session.init() // initializes session features
]
});
```

<br />

#### Input properties

| Name | Type | Description | Default Value |
|----------|----------|-------------|---------------|
| `relyingPartyId` | `string` | The domain name of your application that the system uses for validating the credential. | Uses `getRelyingPartyId` from the recipe configuration which defaults to the `apiDomain` |
| `relyingPartyName` | `string` | The human-readable name of your application. | Uses `getRelyingPartyName` from the recipe configuration which defaults to the `apiName` |
| `origin` | `string` | The origin URL where the credential is generated. | Uses `getOrigin` from the recipe configuration which defaults to the origin of the request |
| `timeout` | `number` | The time in milliseconds that the user has to complete the credential generation process. | `6000` |
| `attestation` | `"none" \| "indirect" \| "direct" \| "enterprise"` | The amount of information about the authenticator that gets included in the attestation statement. This controls what authenticators support. | `none` |
| `supportedAlgorithms` | `number[]` | The cryptographic algorithms that can generate credentials. Different authenticators support different algorithms. | `[-8, -7, -257]` |
| `residentKey` | `"discouraged" \| "preferred" \| "required"` | Whether the credential gest stored on the authenticator device. | `required` |
| `userVerification` | `"discouraged" \| "preferred" \| "required"` | Whether user verification (like `PIN` or biometrics) is necessary. | `preferred` |
| `displayName` | `string` | The display name of the user. | The user's `email` property |


</BackendTabs.TabItem>

<BackendTabs.TabItem value="go">

:::caution

At the moment there is no support for using passkeys authentication in the Go SDK.

:::

</BackendTabs.TabItem>

<BackendTabs.TabItem value="python">

:::caution

At the moment there is no support for using passkeys authentication in the Python SDK.

:::

</BackendTabs.TabItem>

</BackendTabs>

---

## Credential validation

When a user attempts to login, the authenticator uses their credential to sign a challenge on the client.
The frontend SDK uses the [`navigator.credentials.get`](https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/get) function to resolve this.

The server generates the options for signing the challenge through the backend SDK, and then sends them to the client.
To change those, you need to override the `signInOptions` function.


<BackendTabs>

<BackendTabs.TabItem value="nodejs">

```ts
import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import WebAuthn from "supertokens-node/recipe/webauthn";

supertokens.init({
framework: "express",
supertokens: {
// https://try.supertokens.com is for demo purposes. Replace this with the address of your core instance (sign up on supertokens.com), or self host a core.
connectionURI: "https://try.supertokens.com",
// apiKey: <API_KEY(if configured)>,
},
appInfo: {
// learn more about this on https://supertokens.com/docs/session/appinfo
appName: "<YOUR_APP_NAME>",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth"
},
recipeList: [
WebAuthn.init({
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
signInOptions: (input) => {
return originalImplementation.signInOptions({
...input,
timeout: 10 * 1000,
userVerification: "required",
relyingPartyId: 'example.com',
origin: 'https://example.com',
});
},
};
},
},
}),
Session.init() // initializes session features
]
});
```

#### Input properties

| Name | Type | Description | Default |
|----------|----------|-------------|---------|
| `relyingPartyId` | `string` | The domain name of your application that the system uses for validating the credential. | Uses `getRelyingPartyId` from the recipe configuration which defaults to the `apiDomain` |
| `relyingPartyName` | `string` | The human-readable name of your application. | Uses `getRelyingPartyName` from the recipe configuration which defaults to the `apiName` |
| `origin` | `string` | The origin URL where the credential is generated. | Uses `getOrigin` from the recipe configuration which defaults to the origin of the request |
| `timeout` | `number` | The time in milliseconds that the user has to complete the credential validation process. | `6000` |
| `userVerification` | `"discouraged" \| "preferred" \| "required"` | The parameter controls whether user verification (like `PIN` or biometrics) is necessary. | `preferred` |

</BackendTabs.TabItem>

<BackendTabs.TabItem value="go">

:::caution

At the moment there is no support for using passkeys authentication in the Go SDK.

:::

</BackendTabs.TabItem>

<BackendTabs.TabItem value="python">

:::caution

At the moment there is no support for using passkeys authentication in the Python SDK.

:::

</BackendTabs.TabItem>

</BackendTabs>


Loading