Validate Ory Kratos Identity Traits with JSON Schema
Enforce user profile structure in Ory Kratos self-service registration and settings using identity JSON Schemas.
09 Jan 2026, 12:31 UTC

Start with the schema, not the form
If your Ory Kratos registration accepts any JSON object in identity traits, downstream services must guess whether fields exist or have valid values. The useful takeaway: point each identity at a JSON Schema and let Kratos reject invalid traits server-side before the identity is created or updated.
An identity is Kratos's representation of a user. Traits are the attributes stored on that identity, such as email address or preferred language. The schema_id field references the JSON Schema that those traits must satisfy.
Worked example: registration schema
Define the schema as a JSON document. This example requires an email address, allows an optional display name, and restricts locale and membership tier to known values.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"email": { "type": "string", "format": "email" },
"display_name": { "type": "string", "minLength": 1, "maxLength": 100 },
"locale": { "type": "string", "enum": [ "en", "de", "fr" ] },
"membership_tier": { "type": "string", "enum": [ "free", "pro" ] }
},
"required": [ "email" ],
"additionalProperties": false
}
Host the schema at a URL reachable by Kratos, then reference it in your Kratos identity configuration. Exact configuration keys vary by version and deployment, so check your release notes.
# Placeholder; adapt to your Kratos version
identity:
schemas:
- id: https://schemas.example.com/identity/v1.json
url: https://schemas.example.com/identity/v1.json
Submit an identity through the Admin API
Run this from a machine with network access to the Kratos Admin API. You need an admin API token or valid session cookie, depending on your deployment. Replace placeholders in angle brackets.
curl -X POST /admin/identities \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{
"schema_id": "https://schemas.example.com/identity/v1.json",
"traits": {
"email": "[contact removed]",
"display_name": "Example User",
"locale": "en",
"membership_tier": "free"
}
}'
Expected check: a valid payload creates the identity. A payload missing email should be rejected with a server-side schema validation error before the identity exists. Do not assume a specific error message; inspect the response from your Kratos version.
Risk: the Admin API can create or modify identities. Protect the admin token and limit network exposure.
Version traits by changing schema_id
To add a required field, publish a new schema and update schema_id in the registration or settings flow. New registrations and settings updates use the new schema. Existing identities retain their original schema_id and are not automatically revalidated. If existing users must supply the new field, migrate their profiles or keep the field optional.
Limits and common mistakes
- Traits are for profile attributes, not secrets. Do not store passwords, API keys, or personal secrets in traits; use Kratos credentials for secrets.
- Adding a required field can break settings flows for existing users unless they can update their profile or the field remains optional.
- Client-side form validation is not a substitute. Kratos enforces the schema server-side, so invalid submissions from a custom UI are still rejected.
- Self-hosted Kratos must be able to reach the schema URL. If Kratos cannot fetch the schema, identity operations may fail.
- additionalProperties: false rejects any trait not listed in the schema, which can break flows that send unexpected extra fields.
- JSON Schema format keywords such as email may not be enforced unless your Kratos version enables format validation. Check your release notes.
Verify before you roll out
- Publish a schema with required email and optional display_name.
- Submit a registration missing email. Confirm the request is rejected server-side.
- Use the Admin API to retrieve the created identity and confirm schema_id and traits match the schema.
- Attempt a settings update with a disallowed enum value. Confirm the request is rejected.
- If you upgrade Kratos, compare schema URL handling and self-service defaults against the previous release.
Rollback for schema changes
Changing schema_id is a configuration change. If the new schema breaks registration, restore the previous schema_id in your Kratos configuration and reload or restart the Kratos process. Existing identities created under the new schema remain valid unless you explicitly migrate them.
Bottom line
Use JSON Schema to make Kratos the source of truth for identity trait shape. Validate at registration and settings time, version by schema_id, and never treat traits as a credential store.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.