User settings and profile updates
Please read the Self-Service Flows overview before continuing with this document.
Ory Kratos allows users to update their own settings and profile information using two principal flows:
- Flows where the user sits in front of the Browser and the application is
- a server-side application (Node.js, Java, ...)
- a client-side application (React.js, Angular, ...)
- Flows where API interaction is required (Mobile app, Smart TV, ...)
The Settings Flow is composed of several high-level steps summarized in this state diagram:
Three settings methods are supported:
password
for updating the password used to sign in;oidc
for un-/linking from social sign in providers such as Google or Facebook;profile
for updating an identity's traits (for example change the first name). The updated traits must be valid against the Identity Schema defined for its identity traits.
- Ory Cloud
- Ory Kratos
Only the password and profile method are enabled.
You can configure which methods to use in the Ory Kratos config:
selfservice:
methods:
password:
enabled: true
oidc:
enabled: true
profile:
enabled: true
# ...
Updating privileged fields
Most Settings Flow Methods allow the user to update fields which are considered protected:
- The
password
method allows updating the password, which is a protected field; - The
profile
method allows updating protected fields such as- the username or email address used to sign in;
- the recovery email address;
- The
oidc
method allows linking and unlinking from Google, Facebook, Github, ... which is considered a privileged action (check out the set up guide).
selfservice:
flows:
settings:
# Sessions older than a minute requires the user to sign in again before
# the password is changed.
privileged_session_max_age: 1m
- Ory Cloud
- Ory Kratos
If any of these fields are changed, the Ory Kratos Login Session must not be older than the configured
privileged_session_max_age
value.
If any of these fields are changed, the Ory Kratos Login Session must not be older than the configured
privileged_session_max_age
value:
selfservice:
flows:
settings:
# Sessions older than a minute requires the user to sign in again before
# the password is changed.
privileged_session_max_age: 1m
If the Ory Kratos Login Session is older than the specified amount, the user is prompted to re-authenticate similar to the GitHub sudo mode:
This end-user experience works only for Browser-based Settings Flows. API-based flows will simply return a 403 Forbidden status message which require you to request a new Ory Kratos Login session using the API-based Login Flow.
Initialize settings flow
severity
Ory Kratos and your UI must be on the hosted on same top level domain! You can not host Ory Kratos and your UI on separate top level domains:
kratos.bar.com
andui.bar.com
will work;kratos.bar.com
andbar.com
will work;kratos.bar.com
andnot-ar.com
will not work.
The first step is to initialize the settings flow. This allows pre-settings hooks to run, set up Anti-CSRF tokens, and more. Each
Settings Flow also has a state
field which can either be success
or show_form
:
Keep in mind that initializing a Settings Flow requires a valid Ory Session Token (for API-based flows) or Ory Session Cookie (for Browser-based flows)!
Before we start with the examples below, let's create a user using the API-based Registration Flow. This will yield a session token which then use to perform the Settings Flow on this page:
username=dev+docs.$(date +%s)@ory.sh
password=$(openssl rand -base64 12)
actionUrl=$(curl -s -H "Accept: application/json" \
'https://playground.projects.oryapis.com/self-service/registration/api' | jq -r '.ui.action')
session=$(curl -s -X POST -H "Accept: application/json" -H "Content-Type: application/json" \
--data '{ "traits.email": "'$username'", "password": "'$password'", "method": "password" }' \
"$actionUrl")
sessionToken=$(echo $session | jq -r '.session_token')
echo $sessionToken
User and profile settings for server-side browser clients
The settings flow for browser clients relies on HTTP redirects between Ory Kratos, your Settings UI, and the end-user's browser:
The Flow UI (your application!) is responsible for rendering the actual Login and Registration HTML Forms. You can of course implement one app for rendering all the Login, Registration, ... screens, and another app (think "Service Oriented Architecture", "Micro-Services" or "Service Mesh") is responsible for rendering your Dashboards, Management Screens, and so on.
Before we start, we need to log in the user we created:
# We use this cookie jar to initiate the settings flow in the next step!
cookieJar=$(mktemp)
# Initialize the flow
flow=$( \
curl -s -H "Accept: application/json" --cookie $cookieJar --cookie-jar $cookieJar \
'https://playground.projects.oryapis.com/self-service/login/browser' \
)
# Get the action URL
actionUrl=$(echo $flow | jq -r '.ui.action')
# Get the CSRF Token
csrfToken=$(echo $flow | jq -r '.ui.nodes[] | select(.attributes.name=="csrf_token") | .attributes.value')
# Complete the login (with the user we created before)
session=$( \
curl -s --cookie $cookieJar --cookie-jar $cookieJar -X POST \
-H "Accept: application/json" -H "Content-Type: application/json" \
--data '{ "identifier": "'$username'", "password": "'$password'", "method": "password", "csrf_token": "'$csrfToken'" }' \
"$actionUrl" \
)
echo $session | jq
To initialize the Settings Flow, point the Browser to the initialization endpoint:
curl -s -i -X GET \
--cookie $cookieJar --cookie-jar $cookieJar \
-H "Accept: text/html" \
https://playground.projects.oryapis.com/self-service/settings/browser
HTTP/2 303
date: Fri, 09 Jul 2021 11:07:48 GMT
content-type: text/html; charset=utf-8
content-length: 120
location: https://playground.projects.oryapis.com/hosted/settings?flow=95efce11-0bd2-4f55-abce-180ced8b69d7
cache-control: private, no-cache, no-store, must-revalidate
vary: Origin
vary: Cookie
strict-transport-security: max-age=15724800; includeSubDomains
<a href="https://playground.projects.oryapis.com/hosted/settings?flow=95efce11-0bd2-4f55-abce-180ced8b69d7">See Other</a>.
The server responds with a HTTP 303 redirect to the Settings UI, appending the ?flow=<flow-id>
query parameter (see the curl
example) to the configured settings URL.
- Ory Cloud
- Ory Kratos
Ory Cloud offers a default UI implementation. Visit Bring Your Own UI to learn how to implement a custom UI.
You can configure which login URL to use in the Ory Kratos config:
selfservice:
flows:
settings:
# becomes http://127.0.0.1:4455/auth/settings?flow=df607aa1-d555-4b2a-b3e4-0f5a1d2fe6f3
ui_url: http://127.0.0.1:4455/auth/settings
User and Profile Settings for Client-Side (AJAX) Browser Clients
The Settings Flow for client-side browser clients relies on AJAX requests.
severity
This flow requires AJAX and you need to ensure that all cookies are sent using the appropriate CORS and includeCredentials
configurations. Additionally, Ory Kratos and your app must be hosted on the same domain.
To initialize the Settings Flow, point the Browser to the initialization endpoint:
curl -v -s -X GET \
--cookie $cookieJar --cookie-jar $cookieJar \
-H "Accept: application/json" \
https://playground.projects.oryapis.com/self-service/settings/browser | jq
> GET /self-service/settings/browser HTTP/2
> Host: playground.projects.oryapis.com
> User-Agent: curl/7.64.1
> Accept: application/json
< HTTP/2 200
< date: Fri, 09 Jul 2021 09:36:34 GMT
< content-type: application/json; charset=utf-8
< content-length: 1241
< cache-control: private, no-cache, no-store, must-revalidate
< set-cookie: aHR0cHM6Ly9wbGF5Z3JvdW5kLnByb2plY3RzLm9yeWFwaXMuY29tL2FwaS9rcmF0b3MvcHVibGlj_csrf_token=wSDoLSdDqNJv2uWVWdv5euaQo9UimCFS1GhXokTLU3o=; Path=/api/kratos/public; Domain=playground.projects.oryapis.com; Max-Age=31536000; HttpOnly; Secure; SameSite=None
< vary: Origin
< vary: Cookie
< strict-transport-security: max-age=15724800; includeSubDomains
<
{
"id": "4074acf9-5025-469b-be9c-9bc776b4a862",
"type": "browser",
"expires_at": "2021-07-09T10:36:34.04310083Z",
"issued_at": "2021-07-09T09:36:34.04310083Z",
"request_url": "http://playground.projects.oryapis.com/self-service/settings/browser",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/settings?flow=4074acf9-5025-469b-be9c-9bc776b4a862",
"method": "POST",
"nodes": [ /* ... */ ]
}
}
User and profile settings updates for API clients and clients without browsers
warning
Never use API flows to implement Browser applications! Using API flows in Single-Page-Apps as well as server-side apps opens up several potential attack vectors, including Login and other CSRF attacks.
The Settings Flow for API clients doesn't use HTTP Redirects and can be summarized as follows:
To initialize the API flow, the client calls the API-flow initialization endpoint (REST API Reference) which returns a JSON response:
curl -s -X GET \
-H "Accept: application/json" \
-H "Authorization: bearer $sessionToken" \
https://playground.projects.oryapis.com/self-service/settings/api | jq
{
"id": "20d5c364-663f-47e6-bd06-2944aa288f55",
"type": "api",
"expires_at": "2021-07-09T12:10:36.109455077Z",
"issued_at": "2021-07-09T11:10:36.109455077Z",
"request_url": "http://playground.projects.oryapis.com/self-service/settings/api",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/settings?flow=20d5c364-663f-47e6-bd06-2944aa288f55",
"method": "POST",
"nodes": [ /* ... */ ]
},
"identity": {
"id": "7130f345-8506-4c13-869b-d0e8341ff585",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"state": "active",
"state_changed_at": "2021-07-09T11:06:02.23703Z",
"traits": {
"email": "dev+docs.1625828760@ory.sh"
},
"verifiable_addresses": [
{
"id": "a5c0a49b-aa8d-44fd-ae20-361136a7260e",
"value": "dev+docs.1625828760@ory.sh",
"verified": false,
"via": "email",
"status": "sent",
"verified_at": null,
"created_at": "2021-07-09T11:06:02.244136Z",
"updated_at": "2021-07-09T11:06:02.244136Z"
}
],
"recovery_addresses": [
{
"id": "ac4b8521-905c-4492-9b9c-c877d94ca7db",
"value": "dev+docs.1625828760@ory.sh",
"via": "email",
"created_at": "2021-07-09T11:06:02.249405Z",
"updated_at": "2021-07-09T11:06:02.249405Z"
}
],
"created_at": "2021-07-09T11:06:02.239075Z",
"updated_at": "2021-07-09T11:06:02.239075Z"
},
"state": "show_form"
}
Settings flow payloads
Fetching the Settings Flow (REST API Reference) is usually only required for browser clients but also works for Settings Flows initialized by API clients. All you need is a valid flow ID:
flowId=$(curl -s -X GET \
-H "Accept: application/json" \
-H "Authorization: bearer $sessionToken" \
https://playground.projects.oryapis.com/self-service/settings/api | jq -r '.id')
curl -s -X GET \
-H "Accept: application/json" \
-H "Authorization: bearer $sessionToken" \
"https://playground.projects.oryapis.com/self-service/settings/flows?id=$flowId" | jq
{
"id": "260196cc-cd99-40b8-a9b1-8afc06c08afc",
"type": "api",
"expires_at": "2021-07-09T11:05:43.388907Z",
"issued_at": "2021-07-09T10:05:43.388907Z",
"request_url": "http://playground.projects.oryapis.com/self-service/registration/api",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/registration?flow=260196cc-cd99-40b8-a9b1-8afc06c08afc",
"method": "POST",
"nodes": [ /* ... */ ]
}
}
Update Profile
When the profile
method is enabled, it will be part of the methods
payload in the Settings Flow:
curl -s -X GET \
-H "Authorization: Bearer $sessionToken" \
-H "Accept: application/json" \
https://playground.projects.oryapis.com/self-service/settings/api | jq -r '.ui.nodes[] | select(.group=="profile")'
{
"type": "input",
"group": "profile",
"attributes": {
"name": "traits.email",
"type": "email",
"value": "dev+docs.1625828760@ory.sh",
"disabled": false
},
"messages": [],
"meta": {
"label": {
"id": 1070002,
"text": "E-Mail",
"type": "info"
}
}
}
{
"type": "input",
"group": "profile",
"attributes": {
"name": "method",
"type": "submit",
"value": "profile",
"disabled": false
},
"messages": [],
"meta": {
"label": {
"id": 1070003,
"text": "Save",
"type": "info"
}
}
}
The form fields depend on the Identity Schema.
Update password
Please read the Username / Email & Password Credentials Documentation first.
When the password
method is enabled, it will be part of the methods
payload in the Settings Flow:
curl -s -X GET \
-H "Authorization: Bearer $sessionToken" \
-H "Accept: application/json" \
https://playground.projects.oryapis.com/self-service/settings/api | jq -r '.ui.nodes[] | select(.group=="password")'
{
"type": "input",
"group": "password",
"attributes": {
"name": "password",
"type": "password",
"required": true,
"disabled": false
},
"messages": [],
"meta": {
"label": {
"id": 1070001,
"text": "Password",
"type": "info"
}
}
}
{
"type": "input",
"group": "password",
"attributes": {
"name": "method",
"type": "submit",
"value": "password",
"disabled": false
},
"messages": [],
"meta": {
"label": {
"id": 1070003,
"text": "Save",
"type": "info"
}
}
}
Link and unlink from Google, Facebook, GitHub, ..., OpenID Connect / OAuth 2.0
Check out the social sign-in documentation and learn how to set up this method!
When the oidc
method is enabled, it will be part of the methods
payload in the Settings Flow:
curl -s -X GET \
-H "Authorization: Bearer $sessionToken" \
-H "Accept: application/json" \
'https://playground.projects.oryapis.com/self-service/settings/flows?id=14cbf9a7-0c71-46e9-b3b9-806cb7859145' | \
jq -r '.ui.nodes[] | select(.group=="oidc")'
{
"type": "input",
"group": "oidc",
"attributes": {
"name": "link",
"type": "submit",
"value": "github",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1050002,
"text": "Link github",
"type": "info",
"context": {
"provider": "github"
}
}
}
}
{
"type": "input",
"group": "oidc",
"attributes": {
"name": "unlink",
"type": "submit",
"value": "google",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1050003,
"text": "Unlink google",
"type": "info",
"context": {
"provider": "google"
}
}
}
}
Social Sign In is not possible for API Clients. It will be possible in a future version, which is partially tracked as kratos#273
Settings form validation
The form payloads are then submitted to Ory Kratos which follows up with:
- An HTTP 303 See Other redirect pointing to the Registration UI for Browser Clients;
- An
application/json
response for API Clients and Client-Side Browser applications (for example Single Page Apps).
When validation errors happen, browser clients receive a HTTP 303 See Other redirect to the Settings Flow UI, containing the
Settings Flow ID which includes the error payloads. For API Clients, the server typically responds with HTTP 400 Bad Request
application/json
and the Settings Flow in the response payload as JSON.
Update profile
To complete the profile update, the end-user fills out the presented profile form (for example updates their first name or email
address). Possible validation errors include JSON Schema validation errors (for example "format": "email"
not respected):
- Browser UI
- Not An Email
curl -s -X GET \
-H "Authorization: Bearer $sessionToken" \
-H "Accept: application/json" \
'https://playground.projects.oryapis.com/self-service/settings/flows?id=f71743cd-700d-4a30-9275-8edc90de07cc' | \
jq -r '.ui.nodes[] | select(.group=="profile")'
{
"type": "input",
"group": "profile",
"attributes": {
"name": "traits.email",
"type": "email",
"value": "notanemail",
"disabled": false
},
"messages": [
{
"id": 4000001,
"text": "\"notanemail\" isn't valid \"email\"",
"type": "error"
}
],
"meta": {
"label": {
"id": 1070002,
"text": "E-Mail",
"type": "info"
}
}
}
{
"type": "input",
"group": "profile",
"attributes": {
"name": "traits.name.first",
"type": "text",
"value": "",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "First Name",
"type": "info"
}
}
}
{
"type": "input",
"group": "profile",
"attributes": {
"name": "traits.name.last",
"type": "text",
"value": "",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "Last Name",
"type": "info"
}
}
}
{
"type": "input",
"group": "profile",
"attributes": {
"name": "method",
"type": "submit",
"value": "profile",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070003,
"text": "Save",
"type": "info"
}
}
}
Update password
To change the password, the end-user fills out the presented form and provides a new password. Possible validation errors include not providing the password or providing a password which doesn't match the password policy:
- Browser UI
- Missing Password
- Password Policy Violation
curl -s -X GET \
-H "Authorization: Bearer $sessionToken" \
-H "Accept: application/json" \
'https://playground.projects.oryapis.com/self-service/settings/flows?id=f71743cd-700d-4a30-9275-8edc90de07cc' | \
jq -r '.ui.nodes[] | select(.group=="password")'
{
"type": "input",
"group": "password",
"attributes": {
"name": "password",
"type": "password",
"required": true,
"disabled": false
},
"messages": [
{
"id": 4000001,
"text": "length must be >= 1, but got 0",
"type": "error"
}
],
"meta": {
"label": {
"id": 1070001,
"text": "Password",
"type": "info"
}
}
}
{
"type": "input",
"group": "password",
"attributes": {
"name": "method",
"type": "submit",
"value": "password",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070003,
"text": "Save",
"type": "info"
}
}
}
curl -s -X GET \
-H "Authorization: Bearer $sessionToken" \
-H "Accept: application/json" \
'https://playground.projects.oryapis.com/self-service/settings/flows?id=f71743cd-700d-4a30-9275-8edc90de07cc' | \
jq -r '.ui.nodes[] | select(.group=="password")'
{
"type": "input",
"group": "password",
"attributes": {
"name": "password",
"type": "password",
"required": true,
"disabled": false
},
"messages": [
{
"id": 4000005,
"text": "The password can't be used because the password has been found in data breaches and must no longer be used.",
"type": "error",
"context": {
"reason": "the password has been found in data breaches and must no longer be used."
}
}
],
"meta": {
"label": {
"id": 1070001,
"text": "Password",
"type": "info"
}
}
}
{
"type": "input",
"group": "password",
"attributes": {
"name": "method",
"type": "submit",
"value": "password",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070003,
"text": "Save",
"type": "info"
}
}
}
Un-/linking from/with Google, Facebook, GitHub, ..., OpenID Connect / OAuth 2.0
To link or unlink from an OpenID Connect or OAuth2 provider such as Google, GitHub, Facebook, the user either clicks the unlink or link button depending on the interaction.
There are no expected validation errors except for an error where the profile (for example Google) to be linked is already linked with another identity in the system.
Successful settings update
Completing the settings update behaves differently for Browser and API Clients.
Server-side browser clients
When the profile update is completed successfully, Ory Kratos responds with a HTTP 303 Redirect to the Settings UI which now
contains the success state (state: success
) as well as the updated identity:
curl -s -X GET \
--cookie $cookieJar --cookie-jar $cookieJar \
-H "Accept: application/json" \
'https://playground.projects.oryapis.com/self-service/settings/flows?id=f71743cd-700d-4a30-9275-8edc90de07cc' | \
jq
{
"id": "f71743cd-700d-4a30-9275-8edc90de07cc",
"type": "browser",
"expires_at": "2021-04-28T12:39:36.804397011Z",
"issued_at": "2021-04-28T11:39:36.804397011Z",
"request_url": "https://playground.projects.oryapis.com/self-service/settings/browser",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/settings?flow=f71743cd-700d-4a30-9275-8edc90de07cc",
"method": "POST",
"nodes": [
{
"type": "input",
"group": "default",
"attributes": {
"name": "csrf_token",
"type": "hidden",
"value": "ZujkLxomQjFczI0iVkG7E8+yGQ3ouIF2E9msj9gvHPjZPs+wnptmG2Qeg6RVNVh1NktGMfwYBP9AqzYna2m0nw==",
"required": true,
"disabled": false
},
"messages": null,
"meta": {}
},
{
"type": "input",
"group": "profile",
"attributes": {
"name": "traits.email",
"type": "email",
"value": "notanemail",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "E-Mail",
"type": "info"
}
}
},
{
"type": "input",
"group": "profile",
"attributes": {
"name": "traits.name.first",
"type": "text",
"value": "",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "First Name",
"type": "info"
}
}
},
{
"type": "input",
"group": "profile",
"attributes": {
"name": "traits.name.last",
"type": "text",
"value": "",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "Last Name",
"type": "info"
}
}
},
{
"type": "input",
"group": "profile",
"attributes": {
"name": "method",
"type": "submit",
"value": "profile",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070003,
"text": "Save",
"type": "info"
}
}
},
{
"type": "input",
"group": "password",
"attributes": {
"name": "password",
"type": "password",
"required": true,
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070001,
"text": "Password",
"type": "info"
}
}
},
{
"type": "input",
"group": "password",
"attributes": {
"name": "method",
"type": "submit",
"value": "password",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070003,
"text": "Save",
"type": "info"
}
}
}
],
"messages": [
{
"id": 1050001,
"text": "Your changes have been saved!",
"type": "info"
}
]
},
"identity": {
"id": "5b23b651-c186-4398-8717-f15ac72cbc7e",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "example.user@ory.sh"
},
"verifiable_addresses": [
{
"id": "d2214ea2-8b0e-49c0-a9e0-9998ea4527aa",
"value": "example.user@ory.sh",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "29ef1378-0f13-4f2e-a9cf-683320771d5b",
"value": "example.user@ory.sh",
"via": "email"
}
]
},
"state": "success"
}
You may also configure a redirect URL instead which would send the end-user to that configured URL.
Client-side browser clients
When the update is completed successfully, Ory Kratos response with a HTTP 200 OK message containing the updated identity:
password=ByS8NWuFSkDgMjbe
# Initialize the flow
flow=$( \
curl -s -H "Accept: application/json" --cookie $cookieJar --cookie-jar $cookieJar \
'https://playground.projects.oryapis.com/self-service/settings/browser' \
)
# Get the action URL
actionUrl=$(echo $flow | jq -r '.ui.action')
# Get the CSRF Token
csrfToken=$(echo $flow | jq -r '.ui.nodes[] | select(.attributes.name=="csrf_token") | .attributes.value')
# Complete the login (with the user we created before)
session=$( \
curl -s --cookie $cookieJar --cookie-jar $cookieJar -X POST \
-H "Accept: application/json" -H "Content-Type: application/json" \
--data '{"password": "'$password'", "method": "password", "csrf_token": "'$csrfToken'" }' \
"$actionUrl" \
)
{
"id": "f71743cd-700d-4a30-9275-8edc90de07cc",
"type": "browser",
"expires_at": "2021-04-28T12:39:36.804397011Z",
"issued_at": "2021-04-28T11:39:36.804397011Z",
"request_url": "https://playground.projects.oryapis.com/self-service/settings/browser",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/settings?flow=f71743cd-700d-4a30-9275-8edc90de07cc",
"method": "POST",
"nodes": [
// ...
],
"messages": [
{
"id": 1050001,
"text": "Your changes have been saved!",
"type": "info"
}
]
},
"identity": {
"id": "5b23b651-c186-4398-8717-f15ac72cbc7e",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "example.user@ory.sh"
},
"verifiable_addresses": [
{
"id": "d2214ea2-8b0e-49c0-a9e0-9998ea4527aa",
"value": "example.user@ory.sh",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "29ef1378-0f13-4f2e-a9cf-683320771d5b",
"value": "example.user@ory.sh",
"via": "email"
}
]
},
"state": "success"
}
API clients and clients without browsers
For API clients, Ory Kratos responds with a JSON payload which includes the updated identity:
password=ByS8NWuFSkDgMjbe
actionUrl=$(curl -s -H "Accept: application/json" \
-H "Authorization: bearer $sessionToken" \
'https://playground.projects.oryapis.com/self-service/settings/api' | jq -r '.ui.action')
curl -s -X POST -H "Accept: application/json" -H "Content-Type: application/json" \
-H "Authorization: bearer $sessionToken" \
-d '{"password": "'$password'", "method": "password"}' \
"$actionUrl" | jq
{
"id": "f71743cd-700d-4a30-9275-8edc90de07cc",
"type": "browser",
"expires_at": "2021-04-28T12:39:36.804397011Z",
"issued_at": "2021-04-28T11:39:36.804397011Z",
"request_url": "https://playground.projects.oryapis.com/self-service/settings/browser",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/settings?flow=f71743cd-700d-4a30-9275-8edc90de07cc",
"method": "POST",
"nodes": [
// ...
],
"messages": [
{
"id": 1050001,
"text": "Your changes have been saved!",
"type": "info"
}
]
},
"identity": {
"id": "5b23b651-c186-4398-8717-f15ac72cbc7e",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "example.user@ory.sh"
},
"verifiable_addresses": [
{
"id": "d2214ea2-8b0e-49c0-a9e0-9998ea4527aa",
"value": "example.user@ory.sh",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "29ef1378-0f13-4f2e-a9cf-683320771d5b",
"value": "example.user@ory.sh",
"via": "email"
}
]
},
"state": "success"
}
Code Examples for Node.js, React.js, Go, ...
The Settings User Interface is a route (page / site) in your application (server, native app, single page app) that should render a settings form.
In stark contrast to other Identity Systems, Ory Kratos doesn't render this HTML. Instead, you need to implement the HTML code in your application (for example Node.js + Express.js, Java, PHP, React.js, ...), which gives you extreme flexibility and customizability in your user interface flows and designs.
You will use the Settings Flow JSON response to render the settings form UI, which could looks as follows depending on your programming language and web framework:
- Browser UI
- Golang (API Flow)
- Express.js
- React.js
- React Native
- Settings View
- Generic Form View
- Example Input Form Element
- Generic Form View
- Example Input Form Element
Hooks
Ory Kratos allows you to configure hooks that run before and after a profile update was successful. For more information about hooks please read the Hook Documentation.