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:
Schema compilation
The JSON Schema is compiled with the Ory extension runner registered.
Trait validation
Identity traits are validated against the compiled schema using the JSON Schema validation engine.
Extension execution
The Ory extension runners process credentials, verification, and recovery configurations.
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:
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
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" }
}
}