File length: 19914 # Authentication - Passkeys - Customization Source: https://supertokens.com/docs/authentication/passkeys/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 ```ts 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: , }, appInfo: { // learn more about this on https://supertokens.com/docs/session/appinfo appName: "", apiDomain: "", websiteDomain: "", apiBasePath: "/auth", websiteBasePath: "/auth" }, recipeList: [ WebAuthn.init({ getOrigin: () => { return "https://example.com"; }, getRelyingPartyId: () => { return "example.com"; }, getRelyingPartyName: () => { return "example"; }, }), Session.init() // initializes session features ] }); ``` 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. :::caution At the moment there is no support for using passkeys authentication in the Go SDK. ::: ```python from typing import Optional from supertokens_python import InputAppInfo, SupertokensConfig, init from supertokens_python.framework import BaseRequest from supertokens_python.recipe import session, webauthn from supertokens_python.recipe.webauthn import WebauthnConfig from supertokens_python.types.base import UserContext async def get_origin(*, tenant_id: str, request: Optional[BaseRequest], user_context: UserContext): return "https://example.com" async def get_relying_party_id(*, tenant_id: str, request: Optional[BaseRequest], user_context: UserContext): return "example.com" async def get_relying_party_name(*, tenant_id: str, user_context: UserContext): return "example" init( app_info=InputAppInfo( app_name="", api_domain="", website_domain="", api_base_path="/auth", website_base_path="/auth" ), supertokens_config=SupertokensConfig( # 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. connection_uri="https://try.supertokens.com", # api_key="" ), framework='flask', # Replace this with the framework you are using recipe_list=[ webauthn.init( config=WebauthnConfig( get_origin=get_origin, get_relying_party_id=get_relying_party_id, get_relying_party_name=get_relying_party_name, ) ), session.init() # initializes session features ] ) ``` The backend recipe accepts the following properties during initialization: | Option | Description | Default | |--------|-------------|---------| | `get_relying_party_id` | Sets the domain name associated with the WebAuthn credentials. This helps ensure that only your domain uses the credentials. | The `api_domain` value that you have set in `app_config` | | `get_relying_party_name` | Sets a human-readable name for your application. The name appears to users during the WebAuthn registration process. | The `app_name` value that you have set in `app_config` | | `get_origin` | Configures the origin URL that WebAuthn credentials bind to. This should match your application's domain and protocol. | Origin of the request | | `email_delivery` | 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 | | `validate_email_address` | Adds custom validation logic for email addresses. | Basic email format validation | All the properties are optional. --- ## 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. ```ts 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: , }, appInfo: { // learn more about this on https://supertokens.com/docs/session/appinfo appName: "", apiDomain: "", websiteDomain: "", 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 ] }); ```
#### 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 |
:::caution At the moment there is no support for using passkeys authentication in the Go SDK. ::: ```python from typing import List, Optional, cast from typing_extensions import Unpack from supertokens_python import InputAppInfo, SupertokensConfig, init from supertokens_python.recipe import session, webauthn from supertokens_python.recipe.webauthn import RecipeInterface, WebauthnConfig from supertokens_python.recipe.webauthn.interfaces.recipe import ( Attestation, RegisterOptionsKwargsInput, ResidentKey, UserVerification, ) from supertokens_python.recipe.webauthn.types.config import OverrideConfig from supertokens_python.types.base import UserContext def override_webauthn_functions(original_implementation: RecipeInterface): original_register_options = original_implementation.register_options async def register_options( *, relying_party_id: str, relying_party_name: str, origin: str, resident_key: Optional[ResidentKey] = None, user_verification: Optional[UserVerification] = None, user_presence: Optional[bool] = None, attestation: Optional[Attestation] = None, supported_algorithm_ids: Optional[List[int]] = None, timeout: Optional[int] = None, tenant_id: str, user_context: UserContext, **kwargs: Unpack[RegisterOptionsKwargsInput], ): return await original_register_options( relying_party_id="example.com", relying_party_name="example", origin="https://example.com", resident_key="required", user_verification="required", user_presence=True, attestation="direct", timeout=10 * 1000, tenant_id=tenant_id, user_context=user_context, email=cast(str, kwargs.get("email")), recover_account_token=cast(str, kwargs.get("recover_account_token")), display_name="John Doe", ) original_implementation.register_options = register_options return original_implementation init( app_info=InputAppInfo( app_name="", api_domain="", website_domain="", api_base_path="/auth", website_base_path="/auth", ), supertokens_config=SupertokensConfig( # 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. connection_uri="https://try.supertokens.com", # api_key="" ), framework="flask", # Replace this with the framework you are using recipe_list=[ webauthn.init( config=WebauthnConfig( override=OverrideConfig(functions=override_webauthn_functions) ) ), session.init(), # initializes session features ], ) ```
#### Input properties | Name | Type | Description | Default Value | |----------|----------|-------------|---------------| | `relying_party_id` | `str` | The domain name of your application that the system uses for validating the credential. | Uses `get_relying_party_id` from the recipe configuration which defaults to the `api_domain` | | `relying_party_name` | `str` | The human-readable name of your application. | Uses `get_relying_party_name` from the recipe configuration which defaults to the `app_name` | | `origin` | `str` | The origin URL where the credential is generated. | Uses `get_origin` from the recipe configuration which defaults to the origin of the request | | `timeout` | `int` | 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` | | `supported_algorithms` | `List[int]` | The cryptographic algorithms that can generate credentials. Different authenticators support different algorithms. | `[-8, -7, -257]` | | `resident_key` | `"discouraged" \| "preferred" \| "required"` | Whether the credential gest stored on the authenticator device. | `required` | | `user_verification` | `"discouraged" \| "preferred" \| "required"` | Whether user verification (like `PIN` or biometrics) is necessary. | `preferred` | | `display_name` | `str` | The display name of the user. | The user's `email` property |
--- ## 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. ```ts 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: , }, appInfo: { // learn more about this on https://supertokens.com/docs/session/appinfo appName: "", apiDomain: "", websiteDomain: "", 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` | :::caution At the moment there is no support for using passkeys authentication in the Go SDK. ::: ```python from typing import Any from supertokens_python import InputAppInfo, SupertokensConfig, init from supertokens_python.recipe import session, webauthn from supertokens_python.recipe.webauthn import RecipeInterface, WebauthnConfig from supertokens_python.recipe.webauthn.types.config import OverrideConfig from supertokens_python.types.base import UserContext def override_webauthn_functions(original_implementation: RecipeInterface): original_sign_in_options = original_implementation.sign_in_options async def sign_in_options( *, tenant_id: str, user_context: UserContext, **kwargs: Any ): return await original_sign_in_options( tenant_id=tenant_id, user_context=user_context, timeout=10 * 1000, user_verification="required", relying_party_id='example.com', relying_party_name='Example', origin='https://example.com', ) original_implementation.sign_in_options = sign_in_options return original_implementation init( app_info=InputAppInfo( app_name="", api_domain="", website_domain="", api_base_path="/auth", website_base_path="/auth" ), supertokens_config=SupertokensConfig( # 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. connection_uri="https://try.supertokens.com", # api_key="" ), framework='flask', # Replace this with the framework you are using recipe_list=[ webauthn.init( config=WebauthnConfig( override=OverrideConfig( functions=override_webauthn_functions ) ) ), session.init() # initializes session features ] ) ``` #### Input properties | Name | Type | Description | Default | |----------|----------|-------------|---------| | `relying_party_id` | `str` | The domain name of your application that the system uses for validating the credential. | Uses `get_relying_party_id` from the recipe configuration which defaults to the `api_domain` | | `relying_party_name` | `str` | The human-readable name of your application. | Uses `get_relying_party_name` from the recipe configuration which defaults to the `app_name` | | `origin` | `str` | The origin URL where the credential is generated. | Uses `get_origin` from the recipe configuration which defaults to the origin of the request | | `timeout` | `int` | The time in milliseconds that the user has to complete the credential validation process. | `6000` | | `user_verification` | `"discouraged" \| "preferred" \| "required"` | The parameter controls whether user verification (like `PIN` or biometrics) is necessary. | `preferred` |