From 5106a64ff2be217a321170d6fc80615a230bd6b1 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Thu, 16 Jul 2026 00:19:07 -0300 Subject: [PATCH 1/5] docs: Explain Cloud email delivery defaults --- .../concepts/passwords-secrets-env-vars.md | 2 + .../04-providers/02-email/01-setup.md | 55 ++++++++++++++----- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/cloud_docs/concepts/passwords-secrets-env-vars.md b/cloud_docs/concepts/passwords-secrets-env-vars.md index 03699f63..7736bee7 100644 --- a/cloud_docs/concepts/passwords-secrets-env-vars.md +++ b/cloud_docs/concepts/passwords-secrets-env-vars.md @@ -29,6 +29,8 @@ Passwords are the default tier for sensitive values the server reads through the Serverpod Cloud also provisions a set of platform-managed passwords automatically: database credentials, Insights tokens, `serverpod_auth_idp_server` keys, and keys for the legacy auth module. Run `scloud password list` to see them grouped into four categories: **Custom** (passwords you add), **Services** (database, Insights, and related platform passwords), **Auth** (passwords for `serverpod_auth_idp_server`), and **Legacy Auth** (passwords for the legacy authentication module). The Status column marks platform-managed passwords `AUTO (Platform)` and user-set ones `SET (User)`. +For new projects with authentication enabled, the Auth passwords include the `scloudAuthEmailKey` used by `ServerpodCloudEmailIdpConfig` to send registration and password-reset codes. Serverpod Cloud injects this key automatically. See [Set up email sign-in](/concepts/authentication/providers/email/setup) for run-mode behavior, delivery failures, and custom email providers. + Override a platform-managed password by setting a custom value with the same name. Unset it to restore the platform default. Set a password by name and value: diff --git a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md index 80a331dc..51f8a6b7 100644 --- a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md +++ b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md @@ -1,11 +1,11 @@ --- sidebar_label: Setup -description: Sign in with Email lets users authenticate with an email and password. Connect Serverpod to an SMTP service and configure the email identity provider. +description: Configure email and password authentication with Serverpod Cloud's email delivery or callbacks for your own email provider. --- # Set up email sign-in -To properly configure Sign in with Email, you must connect your Serverpod to an external service that can send the emails. One convenient option is the [mailer](https://pub.dev/packages/mailer) package, which can send emails through any SMTP service. Most email providers, such as Resend, Sendgrid or Mandrill, support SMTP. +Email sign-in sends verification codes during registration and password resets. New projects with authentication enabled are configured to use Serverpod Cloud's email service. You can replace it with your own email provider when self-hosting or when you need custom delivery. :::caution You need to install the auth module before you continue, see [Setup](../../setup). @@ -13,7 +13,41 @@ You need to install the auth module before you continue, see [Setup](../../setup ## Server-side configuration -In your main `server.dart` file, configure the email identity provider using the `EmailIdpConfig` object and add it to your `pod.initializeAuthServices()` configuration: +### Use Serverpod Cloud email delivery + +Newly generated projects add `ServerpodCloudEmailIdpConfig` to `pod.initializeAuthServices()` in `server.dart`: + +```dart +pod.initializeAuthServices( + tokenManagerBuilders: [ + JwtConfigFromPasswords(), + ], + identityProviderBuilders: [ + ServerpodCloudEmailIdpConfig( + appDisplayName: 'My App', + ), + ], +); +``` + +Set `appDisplayName` to the application name recipients should see in the verification emails. It can contain up to 64 characters. + +The delivery behavior depends on the server's run mode: + +- In `development` and `test`, Serverpod writes registration and password-reset codes to the server log instead of sending email. +- In `staging` and `production`, Serverpod sends the codes through the Serverpod Cloud transactional email service. + +When you deploy to Serverpod Cloud, the platform automatically injects the `scloudAuthEmailKey` password used by the email service. The configuration reads this password only when it sends an email. This lazy lookup means a self-hosted server can still start when the password is absent. Development and test continue to log codes without it. For self-hosted staging and production environments, replace the configuration with your own email provider. + +Delivery is best-effort. If the key is missing, the service is unavailable, a request times out, or the service rejects a request, the email callback records an error in the Serverpod session log and does not throw it to the authentication flow. Check your [server logs](../../../operations/logging) if a user does not receive a code. Registration may continue to the code-entry screen even when delivery fails. Password-reset responses also remain unchanged so they do not reveal whether an email address belongs to an account. + +`ServerpodCloudEmailIdpConfig` also reads `emailSecretHashPepper` through Serverpod's password system when it is created. New local projects include this value in their run-mode passwords, and Serverpod Cloud provides it as a platform-managed authentication password. + +### Use a custom email provider + +Replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` when you want to send verification codes through your own service. For example, the [mailer](https://pub.dev/packages/mailer) package can send email through SMTP services such as Resend, SendGrid, and Mandrill. + +Configure the callbacks in your main `server.dart` file: ```dart import 'package:serverpod/serverpod.dart'; @@ -34,9 +68,7 @@ void run(List args) async { identityProviderBuilders: [ // Configure the Email Identity Provider // This is the basic configuration for the Email IDP to work. - EmailIdpConfig( - // Secret pepper to hash the password and verification code. - secretHashPepper: pod.getPassword('emailSecretHashPepper')!, + EmailIdpConfigFromPasswords( // Callback to send the registration verification code to the user. sendRegistrationVerificationCode: _sendRegistrationCode, // Callback to send the password reset verification code to the user. @@ -73,7 +105,7 @@ void _sendPasswordResetCode( } ``` -Then extend the abstract endpoint to expose the email authentication routes on the server. Create the file anywhere under your server's `lib/` directory (for example, `_server/lib/src/endpoints/`); the generator picks it up: +Both configurations require an endpoint that exposes the email authentication routes. Extend the abstract endpoint in a file anywhere under your server's `lib/` directory, for example, `_server/lib/src/endpoints/`: ```dart import 'package:serverpod_auth_idp_server/providers/email.dart'; @@ -83,18 +115,14 @@ class EmailIdpEndpoint extends EmailIdpBaseEndpoint {} Then, start the server with `serverpod start` to generate the client code, then create and apply the migration that initializes the database for the provider (in the `serverpod start` terminal, press **M**, then **A**). More detailed instructions can be found in the general [identity providers setup section](../../setup#identity-providers-configuration). -### Basic configuration options +### Configure a custom provider -- `secretHashPepper`: Required. A secret pepper used for hashing passwords and verification codes. Must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. +- `emailSecretHashPepper`: Required by `EmailIdpConfigFromPasswords`. Add this password to `config/passwords.yaml` for each run mode or supply it through the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable. It must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. - `sendRegistrationVerificationCode`: A callback that will be called to send the registration verification code to the user. Here you should call the email sending service to send the verification code to the user. - `sendPasswordResetVerificationCode`: A callback that will be called to send the password reset verification code to the user. Here you should call the email sending service to send the verification code to the user. For more details on configuration options, such as customizing password requirements, verification code generation, rate limiting, and more, see the [configuration section](./configuration). -:::tip -If you are using the `config/passwords.yaml` file or environment variables, you can use the `EmailIdpConfigFromPasswords` constructor to automatically load the secret pepper. It will expect the `emailSecretHashPepper` key or the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable to be set with the secret pepper value. -::: - ## Client-side configuration If you have configured the `SignInWidget` as described in the [setup section](../../setup#present-the-authentication-ui), the Email identity provider will be automatically detected and displayed in the sign-in widget. @@ -122,6 +150,7 @@ EmailSignInWidget( ``` The widget automatically handles: + - Login with email and password. - Registration with terms acceptance and email verification. - Password reset flow with email verification. From 29cdd91e0bc6d3b940a3ed9001579c1748aa90db Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 15:47:29 -0300 Subject: [PATCH 2/5] docs: Restructure the email sign-in setup page Move the endpoint and migration step out of the custom provider branch, where a reader following the Serverpod Cloud path would never see it, and fold the parameter list back into the section it documents. Split the dense Cloud delivery paragraphs and drop the appDisplayName length limit, which the API already enforces. --- .../concepts/passwords-secrets-env-vars.md | 2 +- .../04-providers/02-email/01-setup.md | 46 ++++++++++--------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/cloud_docs/concepts/passwords-secrets-env-vars.md b/cloud_docs/concepts/passwords-secrets-env-vars.md index 7736bee7..feba1cc3 100644 --- a/cloud_docs/concepts/passwords-secrets-env-vars.md +++ b/cloud_docs/concepts/passwords-secrets-env-vars.md @@ -29,7 +29,7 @@ Passwords are the default tier for sensitive values the server reads through the Serverpod Cloud also provisions a set of platform-managed passwords automatically: database credentials, Insights tokens, `serverpod_auth_idp_server` keys, and keys for the legacy auth module. Run `scloud password list` to see them grouped into four categories: **Custom** (passwords you add), **Services** (database, Insights, and related platform passwords), **Auth** (passwords for `serverpod_auth_idp_server`), and **Legacy Auth** (passwords for the legacy authentication module). The Status column marks platform-managed passwords `AUTO (Platform)` and user-set ones `SET (User)`. -For new projects with authentication enabled, the Auth passwords include the `scloudAuthEmailKey` used by `ServerpodCloudEmailIdpConfig` to send registration and password-reset codes. Serverpod Cloud injects this key automatically. See [Set up email sign-in](/concepts/authentication/providers/email/setup) for run-mode behavior, delivery failures, and custom email providers. +One of those Auth passwords is `scloudAuthEmailKey`, which new projects with authentication enabled use to send registration and password-reset codes through Cloud's email service. It is provisioned on deploy, so email sign-in works without any setup on your side. See [Set up email sign-in](/concepts/authentication/providers/email/setup) for the run-mode behavior, what happens when delivery fails, and how to send the codes through your own email provider instead. Override a platform-managed password by setting a custom value with the same name. Unset it to restore the platform default. diff --git a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md index 51f8a6b7..9f8c5ccc 100644 --- a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md +++ b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md @@ -13,9 +13,11 @@ You need to install the auth module before you continue, see [Setup](../../setup ## Server-side configuration -### Use Serverpod Cloud email delivery +The identity provider is registered in `pod.initializeAuthServices()` in your main `server.dart` file. Pick the configuration that matches where the emails are sent from, then expose the endpoints as described below. -Newly generated projects add `ServerpodCloudEmailIdpConfig` to `pod.initializeAuthServices()` in `server.dart`: +### Serverpod Cloud email delivery + +Newly generated projects come with `ServerpodCloudEmailIdpConfig`, which sends the codes through Serverpod Cloud's transactional email service: ```dart pod.initializeAuthServices( @@ -30,24 +32,24 @@ pod.initializeAuthServices( ); ``` -Set `appDisplayName` to the application name recipients should see in the verification emails. It can contain up to 64 characters. +Set `appDisplayName` to the name recipients should see in the verification emails. -The delivery behavior depends on the server's run mode: +What happens when a code is sent depends on the run mode: -- In `development` and `test`, Serverpod writes registration and password-reset codes to the server log instead of sending email. -- In `staging` and `production`, Serverpod sends the codes through the Serverpod Cloud transactional email service. +- In `development` and `test`, the registration and password-reset codes are written to the server log and no email is sent. +- In `staging` and `production`, the codes are sent through the Serverpod Cloud email service. -When you deploy to Serverpod Cloud, the platform automatically injects the `scloudAuthEmailKey` password used by the email service. The configuration reads this password only when it sends an email. This lazy lookup means a self-hosted server can still start when the password is absent. Development and test continue to log codes without it. For self-hosted staging and production environments, replace the configuration with your own email provider. +Deploying to Serverpod Cloud injects the `scloudAuthEmailKey` password the service authenticates with, so there is nothing to configure. The password is read at the moment an email is sent rather than at startup, which is what lets a self-hosted server start without it and keep logging codes in development and test. Self-hosted staging and production environments need their own email provider instead. -Delivery is best-effort. If the key is missing, the service is unavailable, a request times out, or the service rejects a request, the email callback records an error in the Serverpod session log and does not throw it to the authentication flow. Check your [server logs](../../../operations/logging) if a user does not receive a code. Registration may continue to the code-entry screen even when delivery fails. Password-reset responses also remain unchanged so they do not reveal whether an email address belongs to an account. +Delivery is best-effort. A missing key, an unavailable service, a timeout, or a rejected request is recorded in the session log and never thrown into the authentication flow. Registration therefore continues to the code-entry screen even when the email never went out, and password-reset responses stay the same either way so they do not reveal whether an address belongs to an account. Check your [server logs](../../../operations/logging) when a user reports a missing code. -`ServerpodCloudEmailIdpConfig` also reads `emailSecretHashPepper` through Serverpod's password system when it is created. New local projects include this value in their run-mode passwords, and Serverpod Cloud provides it as a platform-managed authentication password. +The configuration also reads `emailSecretHashPepper` through Serverpod's password system when it is created. New projects ship this value in their run-mode passwords, and Serverpod Cloud provides it as a platform-managed authentication password. -### Use a custom email provider +### A custom email provider -Replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` when you want to send verification codes through your own service. For example, the [mailer](https://pub.dev/packages/mailer) package can send email through SMTP services such as Resend, SendGrid, and Mandrill. +Replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` to send the verification codes through your own service. The [mailer](https://pub.dev/packages/mailer) package, for example, sends email through SMTP services such as Resend, SendGrid, and Mandrill. -Configure the callbacks in your main `server.dart` file: +Pass your own callbacks for the two code-sending steps: ```dart import 'package:serverpod/serverpod.dart'; @@ -105,7 +107,17 @@ void _sendPasswordResetCode( } ``` -Both configurations require an endpoint that exposes the email authentication routes. Extend the abstract endpoint in a file anywhere under your server's `lib/` directory, for example, `_server/lib/src/endpoints/`: +The configuration takes these values: + +- `emailSecretHashPepper`: Required. `EmailIdpConfigFromPasswords` reads it from the `emailSecretHashPepper` key in `config/passwords.yaml` for each run mode, or from the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable. It must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. +- `sendRegistrationVerificationCode`: A callback that will be called to send the registration verification code to the user. Here you should call the email sending service to send the verification code to the user. +- `sendPasswordResetVerificationCode`: A callback that will be called to send the password reset verification code to the user. Here you should call the email sending service to send the verification code to the user. + +For more details on configuration options, such as customizing password requirements, verification code generation, rate limiting, and more, see the [configuration section](./configuration). + +### Email authentication endpoints + +Either configuration needs an endpoint that exposes the email authentication routes. Extend the abstract endpoint in a file anywhere under your server's `lib/` directory, for example, `_server/lib/src/endpoints/`: ```dart import 'package:serverpod_auth_idp_server/providers/email.dart'; @@ -115,14 +127,6 @@ class EmailIdpEndpoint extends EmailIdpBaseEndpoint {} Then, start the server with `serverpod start` to generate the client code, then create and apply the migration that initializes the database for the provider (in the `serverpod start` terminal, press **M**, then **A**). More detailed instructions can be found in the general [identity providers setup section](../../setup#identity-providers-configuration). -### Configure a custom provider - -- `emailSecretHashPepper`: Required by `EmailIdpConfigFromPasswords`. Add this password to `config/passwords.yaml` for each run mode or supply it through the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable. It must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. -- `sendRegistrationVerificationCode`: A callback that will be called to send the registration verification code to the user. Here you should call the email sending service to send the verification code to the user. -- `sendPasswordResetVerificationCode`: A callback that will be called to send the password reset verification code to the user. Here you should call the email sending service to send the verification code to the user. - -For more details on configuration options, such as customizing password requirements, verification code generation, rate limiting, and more, see the [configuration section](./configuration). - ## Client-side configuration If you have configured the `SignInWidget` as described in the [setup section](../../setup#present-the-authentication-ui), the Email identity provider will be automatically detected and displayed in the sign-in widget. From 3f373789e0be40643b9fbb34be2fd381bdb22960 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 17:16:13 -0300 Subject: [PATCH 3/5] docs: Scope the Cloud email delivery to apps deployed on Cloud The page read as if ServerpodCloudEmailIdpConfig pointed at a transactional email service that any server could use. It does not: the delivery is part of the Serverpod Cloud platform, and the key it authenticates with is injected into the deployed instance and is not obtainable anywhere else. Say so where a self-hosted reader would otherwise pick the wrong configuration and find out in production. --- .../concepts/passwords-secrets-env-vars.md | 2 +- .../04-providers/02-email/01-setup.md | 20 +++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/cloud_docs/concepts/passwords-secrets-env-vars.md b/cloud_docs/concepts/passwords-secrets-env-vars.md index feba1cc3..24dbcc68 100644 --- a/cloud_docs/concepts/passwords-secrets-env-vars.md +++ b/cloud_docs/concepts/passwords-secrets-env-vars.md @@ -29,7 +29,7 @@ Passwords are the default tier for sensitive values the server reads through the Serverpod Cloud also provisions a set of platform-managed passwords automatically: database credentials, Insights tokens, `serverpod_auth_idp_server` keys, and keys for the legacy auth module. Run `scloud password list` to see them grouped into four categories: **Custom** (passwords you add), **Services** (database, Insights, and related platform passwords), **Auth** (passwords for `serverpod_auth_idp_server`), and **Legacy Auth** (passwords for the legacy authentication module). The Status column marks platform-managed passwords `AUTO (Platform)` and user-set ones `SET (User)`. -One of those Auth passwords is `scloudAuthEmailKey`, which new projects with authentication enabled use to send registration and password-reset codes through Cloud's email service. It is provisioned on deploy, so email sign-in works without any setup on your side. See [Set up email sign-in](/concepts/authentication/providers/email/setup) for the run-mode behavior, what happens when delivery fails, and how to send the codes through your own email provider instead. +One of those Auth passwords is `scloudAuthEmailKey`, which lets Cloud deliver the registration and password-reset codes for new projects with authentication enabled. It is injected into the running instance on deploy, so email sign-in works with no setup on your side. The delivery it unlocks is part of the platform rather than a service reachable from outside it, so a server hosted elsewhere sends these codes through [its own email provider](/concepts/authentication/providers/email/setup#a-custom-email-provider). Override a platform-managed password by setting a custom value with the same name. Unset it to restore the platform default. diff --git a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md index 9f8c5ccc..dabb5af0 100644 --- a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md +++ b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md @@ -1,11 +1,11 @@ --- sidebar_label: Setup -description: Configure email and password authentication with Serverpod Cloud's email delivery or callbacks for your own email provider. +description: Configure email and password authentication, using the built-in delivery for apps deployed to Serverpod Cloud or callbacks for your own email provider. --- # Set up email sign-in -Email sign-in sends verification codes during registration and password resets. New projects with authentication enabled are configured to use Serverpod Cloud's email service. You can replace it with your own email provider when self-hosting or when you need custom delivery. +Email sign-in sends verification codes during registration and password resets. New projects with authentication enabled are set up to have Serverpod Cloud deliver them, which works without configuration once the app is deployed there. Anywhere else, connect your own email provider. :::caution You need to install the auth module before you continue, see [Setup](../../setup). @@ -15,9 +15,9 @@ You need to install the auth module before you continue, see [Setup](../../setup The identity provider is registered in `pod.initializeAuthServices()` in your main `server.dart` file. Pick the configuration that matches where the emails are sent from, then expose the endpoints as described below. -### Serverpod Cloud email delivery +### Email delivery on Serverpod Cloud -Newly generated projects come with `ServerpodCloudEmailIdpConfig`, which sends the codes through Serverpod Cloud's transactional email service: +Newly generated projects come with `ServerpodCloudEmailIdpConfig`, which has Serverpod Cloud deliver the codes for the app deployed there: ```dart pod.initializeAuthServices( @@ -36,10 +36,14 @@ Set `appDisplayName` to the name recipients should see in the verification email What happens when a code is sent depends on the run mode: -- In `development` and `test`, the registration and password-reset codes are written to the server log and no email is sent. -- In `staging` and `production`, the codes are sent through the Serverpod Cloud email service. +- In `development` and `test`, the registration and password-reset codes are written to the server log and no email is sent. This is how the flow works on your machine. +- In `staging` and `production`, the codes are sent by Serverpod Cloud. -Deploying to Serverpod Cloud injects the `scloudAuthEmailKey` password the service authenticates with, so there is nothing to configure. The password is read at the moment an email is sent rather than at startup, which is what lets a self-hosted server start without it and keep logging codes in development and test. Self-hosted staging and production environments need their own email provider instead. +:::warning +This delivery is part of the Serverpod Cloud platform, not a service you can point a server at from elsewhere. It authenticates with an `scloudAuthEmailKey` password that Serverpod Cloud injects into the running instance on deploy, and that key cannot be obtained or set anywhere else. A self-hosted server in `staging` or `production` therefore sends nothing with this configuration, and needs [its own email provider](#a-custom-email-provider) instead. +::: + +Because the key is only read at the moment an email is sent, and never at startup, a self-hosted server still starts normally and keeps logging codes in `development` and `test`. Delivery is best-effort. A missing key, an unavailable service, a timeout, or a rejected request is recorded in the session log and never thrown into the authentication flow. Registration therefore continues to the code-entry screen even when the email never went out, and password-reset responses stay the same either way so they do not reveal whether an address belongs to an account. Check your [server logs](../../../operations/logging) when a user reports a missing code. @@ -47,7 +51,7 @@ The configuration also reads `emailSecretHashPepper` through Serverpod's passwor ### A custom email provider -Replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` to send the verification codes through your own service. The [mailer](https://pub.dev/packages/mailer) package, for example, sends email through SMTP services such as Resend, SendGrid, and Mandrill. +Anywhere other than Serverpod Cloud, replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` and send the verification codes through your own service. The [mailer](https://pub.dev/packages/mailer) package, for example, sends email through SMTP services such as Resend, SendGrid, and Mandrill. Pass your own callbacks for the two code-sending steps: From 17dd6b0925c7df0a1fe6815140e1eddd0a6deaf9 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 17:49:39 -0300 Subject: [PATCH 4/5] docs: Keep the email setup page reading as a guide Cut the explanation block that had grown at the top of the page and the one under Server-side configuration. The generated configuration is now the single path through the page, followed by the endpoint and migration step, with the Cloud-only scope and the delivery failure behavior as short hooks where a reader runs into them. Move the custom provider to a variant section at the end, and leave the Cloud passwords page alone. --- .../concepts/passwords-secrets-env-vars.md | 2 - .../04-providers/02-email/01-setup.md | 51 +++++++------------ 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/cloud_docs/concepts/passwords-secrets-env-vars.md b/cloud_docs/concepts/passwords-secrets-env-vars.md index 24dbcc68..03699f63 100644 --- a/cloud_docs/concepts/passwords-secrets-env-vars.md +++ b/cloud_docs/concepts/passwords-secrets-env-vars.md @@ -29,8 +29,6 @@ Passwords are the default tier for sensitive values the server reads through the Serverpod Cloud also provisions a set of platform-managed passwords automatically: database credentials, Insights tokens, `serverpod_auth_idp_server` keys, and keys for the legacy auth module. Run `scloud password list` to see them grouped into four categories: **Custom** (passwords you add), **Services** (database, Insights, and related platform passwords), **Auth** (passwords for `serverpod_auth_idp_server`), and **Legacy Auth** (passwords for the legacy authentication module). The Status column marks platform-managed passwords `AUTO (Platform)` and user-set ones `SET (User)`. -One of those Auth passwords is `scloudAuthEmailKey`, which lets Cloud deliver the registration and password-reset codes for new projects with authentication enabled. It is injected into the running instance on deploy, so email sign-in works with no setup on your side. The delivery it unlocks is part of the platform rather than a service reachable from outside it, so a server hosted elsewhere sends these codes through [its own email provider](/concepts/authentication/providers/email/setup#a-custom-email-provider). - Override a platform-managed password by setting a custom value with the same name. Unset it to restore the platform default. Set a password by name and value: diff --git a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md index dabb5af0..1daad9ff 100644 --- a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md +++ b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md @@ -1,11 +1,11 @@ --- sidebar_label: Setup -description: Configure email and password authentication, using the built-in delivery for apps deployed to Serverpod Cloud or callbacks for your own email provider. +description: Sign in with Email lets users authenticate with an email and password. Connect Serverpod to an SMTP service and configure the email identity provider. --- # Set up email sign-in -Email sign-in sends verification codes during registration and password resets. New projects with authentication enabled are set up to have Serverpod Cloud deliver them, which works without configuration once the app is deployed there. Anywhere else, connect your own email provider. +Sign in with Email verifies the user's address with a code, both when they register and when they reset their password. :::caution You need to install the auth module before you continue, see [Setup](../../setup). @@ -13,11 +13,7 @@ You need to install the auth module before you continue, see [Setup](../../setup ## Server-side configuration -The identity provider is registered in `pod.initializeAuthServices()` in your main `server.dart` file. Pick the configuration that matches where the emails are sent from, then expose the endpoints as described below. - -### Email delivery on Serverpod Cloud - -Newly generated projects come with `ServerpodCloudEmailIdpConfig`, which has Serverpod Cloud deliver the codes for the app deployed there: +Newly generated projects already configure the email identity provider in `pod.initializeAuthServices()` in your main `server.dart` file: ```dart pod.initializeAuthServices( @@ -32,28 +28,29 @@ pod.initializeAuthServices( ); ``` -Set `appDisplayName` to the name recipients should see in the verification emails. +Set `appDisplayName` to the name recipients should see in the verification emails. In the `development` and `test` run modes the codes are written to the server log instead of being sent, so you can complete the flow locally. Once the app is deployed to Serverpod Cloud, they are sent as email. -What happens when a code is sent depends on the run mode: +:::info +`ServerpodCloudEmailIdpConfig` sends email only for apps running on Serverpod Cloud, which injects the key it authenticates with on deploy. If you host the server yourself, switch to [your own email provider](#use-your-own-email-provider) before you go to staging or production. +::: -- In `development` and `test`, the registration and password-reset codes are written to the server log and no email is sent. This is how the flow works on your machine. -- In `staging` and `production`, the codes are sent by Serverpod Cloud. +Then extend the abstract endpoint to expose the email authentication routes on the server. Create the file anywhere under your server's `lib/` directory (for example, `_server/lib/src/endpoints/`); the generator picks it up: -:::warning -This delivery is part of the Serverpod Cloud platform, not a service you can point a server at from elsewhere. It authenticates with an `scloudAuthEmailKey` password that Serverpod Cloud injects into the running instance on deploy, and that key cannot be obtained or set anywhere else. A self-hosted server in `staging` or `production` therefore sends nothing with this configuration, and needs [its own email provider](#a-custom-email-provider) instead. -::: +```dart +import 'package:serverpod_auth_idp_server/providers/email.dart'; -Because the key is only read at the moment an email is sent, and never at startup, a self-hosted server still starts normally and keeps logging codes in `development` and `test`. +class EmailIdpEndpoint extends EmailIdpBaseEndpoint {} +``` -Delivery is best-effort. A missing key, an unavailable service, a timeout, or a rejected request is recorded in the session log and never thrown into the authentication flow. Registration therefore continues to the code-entry screen even when the email never went out, and password-reset responses stay the same either way so they do not reveal whether an address belongs to an account. Check your [server logs](../../../operations/logging) when a user reports a missing code. +Then, start the server with `serverpod start` to generate the client code, then create and apply the migration that initializes the database for the provider (in the `serverpod start` terminal, press **M**, then **A**). More detailed instructions can be found in the general [identity providers setup section](../../setup#identity-providers-configuration). -The configuration also reads `emailSecretHashPepper` through Serverpod's password system when it is created. New projects ship this value in their run-mode passwords, and Serverpod Cloud provides it as a platform-managed authentication password. +If a code cannot be sent, the failure is recorded in the session log and the sign-in flow continues unchanged, so check your [server logs](../../../operations/logging) when a user reports a missing code. -### A custom email provider +### Use your own email provider -Anywhere other than Serverpod Cloud, replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` and send the verification codes through your own service. The [mailer](https://pub.dev/packages/mailer) package, for example, sends email through SMTP services such as Resend, SendGrid, and Mandrill. +Replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` to send the verification codes yourself. One convenient option is the [mailer](https://pub.dev/packages/mailer) package, which can send emails through any SMTP service. Most email providers, such as Resend, Sendgrid or Mandrill, support SMTP. -Pass your own callbacks for the two code-sending steps: +Pass your own callbacks for the two codes: ```dart import 'package:serverpod/serverpod.dart'; @@ -113,24 +110,12 @@ void _sendPasswordResetCode( The configuration takes these values: -- `emailSecretHashPepper`: Required. `EmailIdpConfigFromPasswords` reads it from the `emailSecretHashPepper` key in `config/passwords.yaml` for each run mode, or from the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable. It must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. +- `emailSecretHashPepper`: Required. A secret pepper used for hashing passwords and verification codes, read from the `emailSecretHashPepper` key in `config/passwords.yaml` or the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable. Must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. - `sendRegistrationVerificationCode`: A callback that will be called to send the registration verification code to the user. Here you should call the email sending service to send the verification code to the user. - `sendPasswordResetVerificationCode`: A callback that will be called to send the password reset verification code to the user. Here you should call the email sending service to send the verification code to the user. For more details on configuration options, such as customizing password requirements, verification code generation, rate limiting, and more, see the [configuration section](./configuration). -### Email authentication endpoints - -Either configuration needs an endpoint that exposes the email authentication routes. Extend the abstract endpoint in a file anywhere under your server's `lib/` directory, for example, `_server/lib/src/endpoints/`: - -```dart -import 'package:serverpod_auth_idp_server/providers/email.dart'; - -class EmailIdpEndpoint extends EmailIdpBaseEndpoint {} -``` - -Then, start the server with `serverpod start` to generate the client code, then create and apply the migration that initializes the database for the provider (in the `serverpod start` terminal, press **M**, then **A**). More detailed instructions can be found in the general [identity providers setup section](../../setup#identity-providers-configuration). - ## Client-side configuration If you have configured the `SignInWidget` as described in the [setup section](../../setup#present-the-authentication-ui), the Email identity provider will be automatically detected and displayed in the sign-in widget. From 51d00a07a19fe7e415c27d73359721f403f8a856 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 18:35:22 -0300 Subject: [PATCH 5/5] refactor: Simplify the documentation --- .../04-providers/02-email/01-setup.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md index 1daad9ff..895627c1 100644 --- a/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md +++ b/docs/06-concepts/04-authentication/04-providers/02-email/01-setup.md @@ -48,9 +48,9 @@ If a code cannot be sent, the failure is recorded in the session log and the sig ### Use your own email provider -Replace `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords` to send the verification codes yourself. One convenient option is the [mailer](https://pub.dev/packages/mailer) package, which can send emails through any SMTP service. Most email providers, such as Resend, Sendgrid or Mandrill, support SMTP. +Serverpod Cloud delivery is there to get sign-in working quickly, and it sends a standard message carrying your `appDisplayName`. You might prefer using a custom email provider to have full control over the body, layout, and language of the emails. For servers hosted outside of Serverpod Cloud, it is the only option. -Pass your own callbacks for the two codes: +Changing the email provider is done by replacing `ServerpodCloudEmailIdpConfig` with `EmailIdpConfig`, which requires you to pass your own callbacks for the two codes. One convenient option is the [mailer](https://pub.dev/packages/mailer) package, which can send emails through any SMTP service. Most email providers, such as Resend, Sendgrid or Mandrill, support SMTP. ```dart import 'package:serverpod/serverpod.dart'; @@ -71,7 +71,9 @@ void run(List args) async { identityProviderBuilders: [ // Configure the Email Identity Provider // This is the basic configuration for the Email IDP to work. - EmailIdpConfigFromPasswords( + EmailIdpConfig( + // Secret pepper to hash the password and verification code. + secretHashPepper: pod.getPassword('emailSecretHashPepper')!, // Callback to send the registration verification code to the user. sendRegistrationVerificationCode: _sendRegistrationCode, // Callback to send the password reset verification code to the user. @@ -108,14 +110,18 @@ void _sendPasswordResetCode( } ``` -The configuration takes these values: +#### Basic configuration options -- `emailSecretHashPepper`: Required. A secret pepper used for hashing passwords and verification codes, read from the `emailSecretHashPepper` key in `config/passwords.yaml` or the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable. Must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. +- `secretHashPepper`: Required. A secret pepper used for hashing passwords and verification codes. Must be at least 10 characters long, but the [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes. - `sendRegistrationVerificationCode`: A callback that will be called to send the registration verification code to the user. Here you should call the email sending service to send the verification code to the user. - `sendPasswordResetVerificationCode`: A callback that will be called to send the password reset verification code to the user. Here you should call the email sending service to send the verification code to the user. For more details on configuration options, such as customizing password requirements, verification code generation, rate limiting, and more, see the [configuration section](./configuration). +:::tip +If you are using the `config/passwords.yaml` file or environment variables, you can use the `EmailIdpConfigFromPasswords` constructor to automatically load the secret pepper. It will expect the `emailSecretHashPepper` key or the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable to be set with the secret pepper value. +::: + ## Client-side configuration If you have configured the `SignInWidget` as described in the [setup section](../../setup#present-the-authentication-ui), the Email identity provider will be automatically detected and displayed in the sign-in widget.