Skip to content
Open
Original file line number Diff line number Diff line change
@@ -1,19 +1,58 @@
---
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: Sign in with Email lets users authenticate with an email and password, with verification codes delivered by Serverpod Cloud or 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.
Sign in with Email verifies the user's address with a code, both when they register and when they reset their password.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The frontmatter description still says "Connect Serverpod to an SMTP service and configure the email identity provider", which now contradicts this intro, since the default needs no SMTP service. Something like: "Sign in with Email lets users authenticate with an email and password. Email delivery works out of the box on Serverpod Cloud, or through your own provider."

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed at f17bdee.


:::caution
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:
Newly generated projects already configure the email identity provider in `pod.initializeAuthServices()` in your main `server.dart` file:

```dart
pod.initializeAuthServices(
tokenManagerBuilders: [
JwtConfigFromPasswords(),
],
identityProviderBuilders: [
ServerpodCloudEmailIdpConfig(
appDisplayName: 'My App',
),
],
);
```

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. In the `staging` and `production` run modes, the codes are sent as email through the Serverpod Cloud email service.

Sending is authenticated with the `scloudAuthEmailKey` password, which Serverpod Cloud sets for you on deploy. The password is read when an email is sent rather than at startup, so a self-hosted server still starts without it, but it cannot deliver any codes. If you host the server yourself, switch to [your own email provider](#use-your-own-email-provider) before you go to staging or production.

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.

### Expose the endpoints

Newly generated projects already include the email endpoint at `lib/src/auth/email_idp_endpoint.dart` and the migration that initializes the database, so running `serverpod start` is all that is needed.

If you are adding the auth module to an existing project, extend the abstract endpoint yourself. Create the file anywhere under your server's `lib/` directory (for example, `<project>_server/lib/src/endpoints/`); the generator picks it up:

```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, and 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).

### Use your own email provider

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.

Changing the email provider is done by replacing `ServerpodCloudEmailIdpConfig` with `EmailIdpConfigFromPasswords`, 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';
Expand All @@ -34,9 +73,7 @@ void run(List<String> 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.
Expand Down Expand Up @@ -73,27 +110,14 @@ 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, `<project>_server/lib/src/endpoints/`); the generator picks it up:

```dart
import 'package:serverpod_auth_idp_server/providers/email.dart';
#### Basic configuration options

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

- `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).
Both configurations hash passwords and verification codes with a secret pepper, which `EmailIdpConfigFromPasswords` reads from the `emailSecretHashPepper` key in `config/passwords.yaml` or the `SERVERPOD_PASSWORD_emailSecretHashPepper` environment variable. Newly generated projects already have a value for every run mode. To pass the pepper directly instead, use `EmailIdpConfig` with its `secretHashPepper` parameter.

:::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.
:::
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

Expand Down Expand Up @@ -122,6 +146,7 @@ EmailSignInWidget(
```

The widget automatically handles:

- Login with email and password.
- Registration with terms acceptance and email verification.
- Password reset flow with email verification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Below is a non-exhaustive list of some of the most common configuration options.

A pepper is a server-side secret that is added, along with a unique salt, to a password before it is hashed and stored. The pepper makes it harder for an attacker to crack password hashes if they have only gained access to the database.

The pepper is configured via the `secretHashPepper` property in `EmailIdpConfig`, as shown in the [server-side configuration](./setup#server-side-configuration) section. Its [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes.
The pepper is configured via the `secretHashPepper` property in `EmailIdpConfig`, or read from the `emailSecretHashPepper` password by `EmailIdpConfigFromPasswords`, as described in the [server-side configuration](./setup#server-side-configuration) section. Its [recommended pepper length](https://www.ietf.org/archive/id/draft-ietf-kitten-password-storage-04.html#name-storage-2) is 32 bytes.

:::warning
If the pepper is changed, all passwords in the database will need to be re-hashed with the new pepper, or the old pepper needs to be added as a fallback pepper. Store the pepper securely and never expose it to the client.
Expand Down
Loading