Skip to main content
Identity schemas define the structure and validation rules for user data in Ory Kratos. They use JSON Schema to specify which fields are required, what data types are allowed, and how credentials are associated with identities.

Schema structure

An identity schema is a JSON Schema document that defines the traits of an identity. Traits represent user data such as email addresses, usernames, phone numbers, and custom fields.

Basic schema example

{
  "$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": {
          "type": "string",
          "format": "email",
          "title": "Email",
          "ory.sh/kratos": {
            "credentials": {
              "password": {
                "identifier": true
              }
            },
            "verification": {
              "via": "email"
            },
            "recovery": {
              "via": "email"
            }
          }
        },
        "name": {
          "type": "object",
          "properties": {
            "first": {
              "type": "string",
              "title": "First Name"
            },
            "last": {
              "type": "string",
              "title": "Last Name"
            }
          }
        }
      },
      "required": ["email"],
      "additionalProperties": false
    }
  }
}

Ory schema extension

Kratos extends JSON Schema with a custom ory.sh/kratos extension that enables identity-specific features.

Extension properties

The extension supports the following configurations:
Configure which fields serve as identifiers for different credential types:
"ory.sh/kratos": {
  "credentials": {
    "password": {
      "identifier": true
    },
    "webauthn": {
      "identifier": true
    },
    "passkey": {
      "display_name": true
    },
    "totp": {
      "account_name": true
    },
    "code": {
      "identifier": true,
      "via": "email"
    }
  }
}
Specify how a field can be verified:
"ory.sh/kratos": {
  "verification": {
    "via": "email"
  }
}
Supported values: email, sms
Configure account recovery options:
"ory.sh/kratos": {
  "recovery": {
    "via": "email"
  }
}
Supported values: email, code
Define organization matchers for multi-tenant setups:
"ory.sh/kratos": {
  "organizations": {
    "matcher": "email_domain"
  }
}

Schema validation

Kratos validates identity traits against the schema during:
  • Identity creation via Admin API
  • Self-service registration
  • Profile updates
  • Identity import operations

Validation process

The validation process follows these steps:
1

Schema compilation

The JSON Schema is compiled with the Ory extension runner registered.
2

Trait validation

Identity traits are validated against the compiled schema using the JSON Schema validation engine.
3

Extension execution

The Ory extension runners process credentials, verification, and recovery configurations.
4

Error handling

Validation errors are returned with detailed information about which fields failed validation and why.

Validation example

Here’s how validation is performed in the code:
identity/validator.go
func (v *Validator) Validate(ctx context.Context, i *Identity) error {
    schema, err := v.schemaLoader.Load(ctx, i.SchemaID)
    if err != nil {
        return err
    }

    if err := schema.Validate(i.Traits); err != nil {
        return err
    }

    return nil
}

Multiple schemas

Kratos supports multiple identity schemas, allowing different user types or tenant configurations.

Configuration

Define multiple schemas in your Kratos configuration:
identity:
  default_schema_id: default
  schemas:
    - id: default
      url: file:///etc/config/kratos/identity.schema.json
    - id: customer
      url: file:///etc/config/kratos/customer.schema.json
    - id: employee
      url: file:///etc/config/kratos/employee.schema.json

Specifying schema during creation

When creating an identity, specify the schema ID:
kratos create identity \
  --schema-id customer \
  --traits '{"email":"[email protected]"}'

Traits structure

The identity object in Kratos contains:
{
  "id": "9f425a8d-7efc-4768-8f23-7647a74fdf13",
  "schema_id": "default",
  "schema_url": "https://example.com/schemas/default",
  "traits": {
    "email": "[email protected]",
    "name": {
      "first": "John",
      "last": "Doe"
    }
  },
  "state": "active",
  "created_at": "2023-01-15T09:30:00Z",
  "updated_at": "2023-01-15T09:30:00Z"
}
The traits field is stored as json.RawMessage and validated against the schema on every update.

Best practices

  • Always use additionalProperties: false to prevent arbitrary data from being stored
  • Mark sensitive fields appropriately in your schema
  • Use format validators like email, uri, date-time for built-in validation
  • Keep schemas backward compatible when updating existing deployments

Performance considerations

  • Schemas are cached after compilation
  • Avoid deeply nested object structures
  • Use references ($ref) for reusable schema components
  • Minimize the number of validation rules for better performance

Common patterns

Email and username

"email": {
  "type": "string",
  "format": "email",
  "minLength": 3,
  "maxLength": 320,
  "ory.sh/kratos": {
    "credentials": {
      "password": { "identifier": true },
      "code": { "identifier": true, "via": "email" }
    },
    "verification": { "via": "email" },
    "recovery": { "via": "email" }
  }
},
"username": {
  "type": "string",
  "minLength": 3,
  "maxLength": 32,
  "pattern": "^[a-zA-Z0-9_-]+$",
  "ory.sh/kratos": {
    "credentials": {
      "password": { "identifier": true }
    }
  }
}

Phone number

"phone": {
  "type": "string",
  "pattern": "^\\+[1-9]\\d{1,14}$",
  "ory.sh/kratos": {
    "credentials": {
      "code": { "identifier": true, "via": "sms" }
    },
    "recovery": { "via": "sms" }
  }
}

Build docs developers (and LLMs) love