Skip to content
Merged
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
77 changes: 54 additions & 23 deletions authentication/email.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ To test OTP codes in our sandbox environment you can use the following:

- `alphanumeric` must be set to `false`
- `otpLength` must be set to `6`
- Email: [email protected]
- Email: [[email protected]](mailto:[email protected])
- OTP Code: `000000`

**Credential Bundle**
Expand All @@ -35,21 +35,18 @@ The authentication process happens in two steps:

<Steps>
<Step>
A 6-9 digit or alphanumeric OTP code is sent to the user's verified email
address
A 6-9 digit or alphanumeric OTP code is sent to the user's verified email address
</Step>
<Step>
Upon verification of the correct code, an API key credential is generated
and encrypted for the client
Upon verification of the correct code, an API key credential is generated and encrypted for the client
</Step>
</Steps>

### Credential bundle method

**Note:** on web, this method is only supported with the legacy iframe-based flow, if no hard requirement to use encrypted bundles, we suggest to use the IndexedDB-based OTP flow instead.

The API key credential is encrypted and delivered directly through email to the user.
Once the credential is live on the client side (within the context of an iframe), it is readily available to stamp (authenticate) requests. See the [enclave to end-user secure channel](/security/enclave-secure-channels) for more info on how we achieve secure delivery.
The API key credential is encrypted and delivered directly through email to the user. Once the credential is live on the client side (within the context of an iframe), it is readily available to stamp (authenticate) requests. See the [enclave to end-user secure channel](/security/enclave-secure-channels) for more info on how we achieve secure delivery.

## Prerequisites

Expand Down Expand Up @@ -84,9 +81,7 @@ The flow begins with a new activity of type `ACTIVITY_TYPE_INIT_OTP` using the p
- `otpType`: specify `"OTP_TYPE_EMAIL"`
- `contact`: user's email address
- `emailCustomization`: optional parameters for customizing emails
- `userIdentifier`: optional parameter for rate limiting SMS OTP requests per user.
We recommend generating this server-side based on the user's IP address or public key.
See the [OTP Rate Limits](#otp-rate-limits) section below for more details.
- `userIdentifier`: optional parameter for rate limiting SMS OTP requests per user. We recommend generating this server-side based on the user's IP address or public key. See the [OTP Rate Limits](#otp-rate-limits) section below for more details.
- `alphanumeric`: optional parameter for making this code bech32 alphanumeric or not. default: true
- `otpLength`: optional parameter for selecting the length of the OTP. default: 9
- `expirationSeconds`: optional validity window (defaults to 5 minutes)
Expand All @@ -108,10 +103,7 @@ After receiving the verification token, users complete OTP authentication flow w
- `invalidateExisting`: optional boolean to invalidate previous login sessions

<Frame>
<img
src="/images/authentication/img/auth_otp_email.png"
alt="auth otp email"
/>
![auth otp email](/images/authentication/img/auth_otp_email.png)
</Frame>

### OTP rate limits
Expand All @@ -134,7 +126,7 @@ This alternative method uses `ACTIVITY_TYPE_EMAIL_AUTH` with these parameters:
- `invalidateExisting`: optional boolean to invalidate previous Email Auth API keys

<Frame>
<img src="/images/authentication/img/auth_email.png" alt="auth email" />
![auth email](/images/authentication/img/auth_email.png)
</Frame>

## Email customization
Expand Down Expand Up @@ -165,6 +157,51 @@ const response = await client.emailAuth({
});
```

### Breaking Change: `appName` Required

<Warning>
**Effective December 8, 2025**

Beginning the week of December 8, 2025, all email-based OTP and recovery activities will require the `appName` parameter. Existing SDK versions will continue working, but upgrading without setting an `appName` will break email-based flows.

<CardGroup cols={2}>
<Card title="Auth Proxy Users" icon="server">
**Affected:** Anyone using Auth Proxy without `appName` set

**Action:** Set `appName` under [email configuration](https://app.turnkey.com/dashboard/walletKit)
</Card>
<Card title="Server SDK Users" icon="code">
**Affected:** Users calling `init_otp_auth`, `init_otp`, `email_recovery`, or `email_auth` without `appName`

**Action:**<br/>
• For `email_recovery` or `email_auth`: include `appName` in your request<br/>
• For `init_otp` or `init_otp_auth`: update your API call to match the new input structure when upgrading to the latest server-SDK
</Card>
</CardGroup>

<Card title="Policy activity type updates">
If you manage email flows with policies, update to the new activity types:

**EMAIL_AUTH**<br/>
Old: `ACTIVITY_TYPE_EMAIL_AUTH`, `ACTIVITY_TYPE_EMAIL_AUTH_V2`<br/>
New: `ACTIVITY_TYPE_EMAIL_AUTH_V3`

**INIT_OTP_AUTH**<br/>
Old: `ACTIVITY_TYPE_INIT_OTP_AUTH`, `ACTIVITY_TYPE_INIT_OTP_AUTH_V2`<br/>
New: `ACTIVITY_TYPE_INIT_OTP_AUTH_V3`

**INIT_OTP**<br/>
Old: `ACTIVITY_TYPE_INIT_OTP`<br/>
New: `ACTIVITY_TYPE_INIT_OTP_V2`

**INIT_USER_EMAIL_RECOVERY**<br/>
Old: `ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY`<br/>
New: `ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY_V2`
</Card>

</Warning>


### Email templates

We also support custom HTML email templates for [Enterprise](https://www.turnkey.com/pricing) clients on the **Scale** tier. This allows you to inject arbitrary data from a JSON string containing key-value pairs. In this case, the `emailCustomization` variable may look like:
Expand Down Expand Up @@ -238,10 +275,7 @@ Specifically:
- For credential bundle auth: `ACTIVITY_TYPE_EMAIL_AUTH`

<Frame>
<img
src="/images/authentication/img/diagrams/email_auth_authorization.png"
alt="email auth authorization"
/>
![email auth authorization](/images/authentication/img/diagrams/email_auth_authorization.png)
</Frame>

### Example implementations
Expand All @@ -255,10 +289,8 @@ Specifically:
For organizations accessed via dashboard:

1. Ensure the required features are enabled:

- `FEATURE_NAME_OTP_EMAIL_AUTH` for OTP-based authentication
- `FEATURE_NAME_EMAIL_AUTH` for credential bundle authentication

2. Users initiating the request must have appropriate permissions

## Opting out
Expand All @@ -278,7 +310,6 @@ When creating sub-organizations, use:
## Implementation notes

- Users are limited to:

- 10 long-lived API keys
- 10 expiring API keys (oldest are discarded when limit is reached)

Expand Down Expand Up @@ -316,4 +347,4 @@ turnkey request --host api.turnkey.com --path /public/v1/submit/set_organization
"name": "FEATURE_NAME_EMAIL_AUTH"
}
}' --organization <YOUR-ORG-ID>
```
```