Skip to main content

Address verification

Ory allows users to verify email addresses or phone numbers associated with their accounts. This is important to prove that the user has access to the address they used to create their account. If verification is enabled, Ory Identities starts the verification process automatically when users sign up. Users can also verify their addresses manually.

The verification flow is supported in both browsers and API clients and can be summarized as the following state machine:

caution

Completing account verification doesn't guarantee that the account is used by the person who performed the verification. We recommend implementing additional security mechanisms to ensure that verified accounts aren't taken over by malicious actors, such as TOTP or FIDO2/WebAuthn.

Configuration

To configure account verification, go to AuthenticationEmail Verification in the Ory Console.

caution

For SMS verification to work, you'll also need to configure a courier channel with the ID set to sms via the CLI. See the courier documentation for more information.

Identity schema

To make an address verifiable, it must be marked as such in the identity schema. In most cases this is the email address the user provides when registering their account. Other fields inside the traits section are supported as well.

identity-schema.json
 {
"$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Person",
"type": "object",
"properties": {
"traits": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"ory.sh/kratos": {
"credentials": {
"password": {
"identifier": true
}
},
+ "verification": {
+ "via": "email"
+ }
}
}
},
"additionalProperties": false
}
}
}

Attempted verification notifications

When this option is on and users attempt to initiate verification for unregistered addresses, the system sends an attempted verification notification to the email address that was used in the attempt. This prevents account enumeration attacks as explained in this blog post by Troy Hunt.

info

By default, this feature is disabled in newly created Ory Network projects.

Follow these steps to enable sending attempted verification notifications:

Go to Ory ConsoleEmail Verification to enable and toggle Notify unknown recipients on.

Email templates

Ory Identities comes with default email templates for verification flows.

You can quickly replace the defaults and customize the messages to match the look and feel of your solution. Read the custom email template documentation to learn more.

Allow login only with verified email

To allow only the users with a verified email to sign in, follow these steps:

Go to AuthenticationEmail Verification in the Ory Console and enable Require Verified Address for Login.

Carry over verified status from Social Sign-In

Some Social Sign-In providers like Google return the verified status of the email address. To carry over the verified status from the Social Sign-In provider, return verified_addresses in your Social Sign-In Jsonnet snippet:

local claims = {
email_verified: false,
} + std.extVar('claims');

{
identity: {
traits: {
[if 'email' in claims && claims.email_verified then 'email' else null]: claims.email,
given_name: claims.given_name,
family_name: claims.family_name,
},
verified_addresses: std.prune([
// Carry over verified status from Social Sign-In provider.
if 'email' in claims && claims.email_verified then { via: 'email', value: claims.email },
]),
},
}

Please note that this only works if the verified address is also present in the identity's traits and marked as a verifiable email.

Example identity schema
{
$id: "https://example.com/person.schema.json",
$schema: "http://json-schema.org/draft-07/schema#",
title: "Person",
type: "object",
properties: {
traits: {
type: "object",
properties: {
email: {
format: "email",
type: "string",
"ory.sh/kratos": {
verification: {
via: "email",
},
},
},
},
required: ["subject"],
},
},
}

If the verified address is not present in the identity's traits, the verified status is not carried over.

Phone number verification

To send SMS messages, you need to have a trait in your identity schema that holds the phone number. The trait must be marked as a verifiable address via the verification extension. Here's an example of how to define such a trait in the identity schema:

{
"$id": "https://schemas.ory.sh/presets/kratos/quickstart/phone-password/identity.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Person",
"type": "object",
"properties": {
"traits": {
"type": "object",
"properties": {
"email": {
"type": "string",
"title": "E-Mail",
"format": "email",
"ory.sh/kratos": {
"credentials": {
"password": {
"identifier": true
}
},
"verification": {
"via": "email"
}
}
},
"phone": {
"type": "string",
"title": "Phone number",
"format": "tel",
"ory.sh/kratos": {
"verification": {
"via": "sms"
}
}
}
},
"additionalProperties": false
}
}
}

Make sure to configure an SMS channel in the Ory configuration. See the SMS documentation.

Choosing the right strategy

Ory supports two strategies for verifying your user's addresses.

When using one-time codes to verify a user's address, Ory Identities sends an email with a 6-digit code to the user. They must enter the code in a dedicated UI text field to verify their address.

The email also contains a link, that takes the user to the verification form with the code pre-filled in the appropriate form field. The only thing the user must do to verify their address is to submit the form.

If the user completes the verification after the link or code expired, they must provide the email address associated with their account to get a new verification email.

Comparison

"One-time code" (code) is the default, preferred, and recommended method by Ory.

Ory supports "magic links", but considers this method a legacy solution. Currently, the method is supported but should be considered deprecated and is set to be removed in future releases.

Consider using the code method as it mitigates many of the drawbacks of "magic links":

  • Some email virus scanners open links in emails to scan them. This invalidates the link and may prevent users from completing the flow even if they have the access to the defined address.
  • Flows initialized by apps on mobile phones or smart devices don't work with links.
  • Depending on the device settings, clicking a link from an email can open a different browser than the one used to initialize the flow. This can confuse your users.
caution

When you change the strategy from link to code in an existing project, you might need to adjust your UI. Make sure the flow works correctly with your UI implementation after changing the strategy.

Showing the verification flow after settings or registration

To show the verification flow directly after the user has registered, see the registration documentation.

For settings, see the settings documentation.

Code examples

The user interface for account verification is a page in your solution that renders the actual form elements for the user.

In contrast to other identity systems, Ory Identities (Ory Kratos) doesn't render this HTML directly. Instead, you need to implement the HTML code in your solution, which gives you complete flexibility and customizability in your user interface flows and designs. This part of your application then directly interfaces with Ory Identities through the API.

The API responds with a JSON document describing the form elements to render and actions the form should take upon submission, cancellation, etc. The following shows examples for a few different languages and frameworks.

Email Verification HTML Form