Skip to main content

User registration

info

Please read the Self-Service Flows overview before continuing with this document.

There are two Registration Flow types supported in Ory Identities:

  • 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 Registration Flow can be summarized as the following state machine:

Two registration methods are supported:

  • password for signing up with an email / username and password;
  • oidc for signing up using a social sign in provider such as Google or Facebook (check out the set up guide).

You can configure which methods to use in the Ory Identities config:

config.yml
selfservice:
methods:
password:
enabled: true
oidc:
enabled: true
# ...

Initialize registration flow

The first step is to initialize the Registration Flow. This allows pre-registration hooks to run, set up Anti-CSRF tokens, and more.

INFO

Ory and your UI must be on the hosted on same top level domain. You can't host Ory and your UI on separate top level domains:

  • ory.bar.com and app.bar.com will work;
  • ory.bar.com and bar.com will work;
  • ory.bar.com and not-bar.com will not work.

Registration for server-side browser clients

The Registration Flow for browser clients relies on HTTP redirects between Ory Identities, your Registration UI, and the end-user's browser:

The Authentication 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.

To initialize the Registration Flow, point the Browser to the initialization endpoint:

curl -s -i -X GET \
-H "Accept: text/html" \
https://playground.projects.oryapis.com/self-service/registration/browser

HTTP/2 303
date: Fri, 09 Jul 2021 09:35:26 GMT
content-type: text/html; charset=utf-8
content-length: 128
location: https://playground.projects.oryapis.com/hosted/registration?flow=6c2ae96c-8486-42f0-91f9-f654eccd09fb
cache-control: private, no-cache, no-store, must-revalidate
set-cookie: aHR0cHM6Ly9wbGF5Z3JvdW5kLnByb2plY3RzLm9yeWFwaXMuY29tL2FwaS9rcmF0b3MvcHVibGlj_csrf_token=JDYmr2vbucEi5hjc9/tjOxz0yORCcfFmjIgPDobyD9o=; 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

<a href="https://playground.projects.oryapis.com/hosted/registration?flow=6c2ae96c-8486-42f0-91f9-f654eccd09fb">See Other</a>.

The server responds with a HTTP 303 redirect to the Registration UI, appending the ?flow=<flow-id> query parameter (see the curl example) to the configured registration URL.

You can configure which login URL to use in the Ory Identities config:

config.yml
selfservice:
flows:
registration:
# becomes http://127.0.0.1:4455/auth/registration?flow=df607aa1-d555-4b2a-b3e4-0f5a1d2fe6f3
ui_url: http://127.0.0.1:4455/auth/registration

Registration for client-side (AJAX) browser clients

The Registration 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 Registration Flow, call the registration initialization endpoint and set Accept: application/json:

curl -v -s -X GET \
-H "Accept: application/json" \
https://playground.projects.oryapis.com/self-service/registration/browser | jq

> GET /self-service/registration/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/registration/browser",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/registration?flow=4074acf9-5025-469b-be9c-9bc776b4a862",
"method": "POST",
"nodes": [ /* ... */ ]
}
}

Registration for API clients and clients without browsers

DANGER

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 Registration 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" \
https://playground.projects.oryapis.com/self-service/registration/api | jq

{
"id": "c7ed95c7-2710-436c-a7d0-09ac771a3e8b",
"type": "api",
"expires_at": "2021-07-09T10:41:34.883536226Z",
"issued_at": "2021-07-09T09:41:34.883536226Z",
"request_url": "http://playground.projects.oryapis.com/self-service/registration/api",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/registration?flow=c7ed95c7-2710-436c-a7d0-09ac771a3e8b",
"method": "POST",
"method": "POST",
"method": "POST",
"nodes": [ /* ... */ ]
}
}

Registration form payloads

Fetching the Registration Flow (REST API Reference) is usually only required for browser clients but also works for Registration Flows initialized by API clients. All you need is a valid Registration Flow ID:

flowId=$(curl -s -X GET \
-H "Accept: application/json" \
https://playground.projects.oryapis.com/self-service/registration/api | jq -r '.id')

curl -s -X GET \
-H "Accept: application/json" \
"https://playground.projects.oryapis.com/self-service/registration/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": [ /* ... */ ]
}
}

Registration with username/email and password

Before you start

When the password method is enabled, it will be part of the methods payload in the Registration Flow. Ory Identities uses the Identity Schema defined in identity.default_schema_id to generate a list of form fields and add it to the Registration Flow. Assuming we're using the Identity Schema from the Quickstart

https://raw.githubusercontent.com/ory/kratos/master/contrib/quickstart/kratos/email-password/identity.schema.json

the response would look as such:

curl -H "Accept: application/json" -s \
'https://playground.projects.oryapis.com/self-service/registration/flows?id=388ae8da-4c44-4765-bfa8-669963d388f5' | jq

{
"id": "388ae8da-4c44-4765-bfa8-669963d388f5",
"type": "browser",
"expires_at": "2021-04-28T09:29:23.713785401Z",
"issued_at": "2021-04-28T09:19:23.713785401Z",
"request_url": "https://playground.projects.oryapis.com/self-service/registration/browser",
"ui": {
"action": "https://playground.projects.oryapis.com/self-service/registration?flow=388ae8da-4c44-4765-bfa8-669963d388f5",
"method": "POST",
"nodes": [
{
"type": "input",
"group": "default",
"attributes": {
"name": "csrf_token",
"type": "hidden",
"value": "Z9pXCAGz2oK/9Ch8x4U1ehEAKHWVngQTPFDFTlYtbK8lWzXRyDBnl3neZGUIgW44ewDjb5niFdGGM5GERhu01g==",
"required": true,
"disabled": false
},
"messages": null,
"meta": {}
},
{
"type": "input",
"group": "password",
"attributes": {
"name": "traits.email",
"type": "email",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "E-Mail",
"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": "traits.name.first",
"type": "text",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "First Name",
"type": "info"
}
}
},
{
"type": "input",
"group": "password",
"attributes": {
"name": "traits.name.last",
"type": "text",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1070002,
"text": "Last Name",
"type": "info"
}
}
},
{
"type": "input",
"group": "password",
"attributes": {
"name": "method",
"type": "submit",
"value": "password",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1040001,
"text": "Sign up",
"type": "info",
"context": {}
}
}
}
]
}
}

Registration with Google, Facebook, GitHub, ..., OpenID Connect / OAuth 2.0

Before you start

Check out the social sign-in documentation and learn how to set up this method!

The Social Sign Up Method (oidc) enables you to use

If enabled, the method contains an oidc key with the configured sign in providers as submit fields:

curl -H "Accept: application/json" -s \
'https://playground.projects.oryapis.com/self-service/registration/flows?id=c1f4dfd1-3559-4cd3-b6f6-4a83689a41bd' | jq

{
"id": "c1f4dfd1-3559-4cd3-b6f6-4a83689a41bd",
"type": "browser",
"expires_at": "2021-04-28T10:25:35.011063Z",
"issued_at": "2021-04-28T09:25:35.011063Z",
"request_url": "https://playground.projects.oryapis.com/self-service/registration/browser",
"ui": {
"action": "http://127.0.0.1:4455/self-service/registration?flow=c1f4dfd1-3559-4cd3-b6f6-4a83689a41bd",
"method": "POST",
"nodes": [
{
"type": "input",
"group": "default",
"attributes": {
"name": "csrf_token",
"type": "hidden",
"value": "PJO66RnYyYLyksS/bjlveGnmZARtqPvibgJI/0EX3DPZf0Oq0Ln+5KtTHVfcxMDSbXjx32hU9GwpfbwA2eLFWA==",
"required": true,
"disabled": false
},
"messages": null,
"meta": {}
},
{
"type": "input",
"group": "oidc",
"attributes": {
"name": "provider",
"type": "submit",
"value": "github",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1040002,
"text": "Sign up with github",
"type": "info",
"context": {
"provider": "github"
}
}
}
},
{
"type": "input",
"group": "oidc",
"attributes": {
"name": "provider",
"type": "submit",
"value": "google",
"disabled": false
},
"messages": null,
"meta": {
"label": {
"id": 1040002,
"text": "Sign up with google",
"type": "info",
"context": {
"provider": "google"
}
}
}
}
]
}
}

Registration form validation

The form payloads are then submitted to Ory Identities 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).

Registration with username/email and password

To complete the registration process, the end-user fills out the form which must include a field marked as the identifier (ory.sh/kratos.credentials.password.identifier: true) in the Identity JSON Schema, for example:

 {
"$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
+ }
+ }
+ }
}
},
"required": [
"email"
],
"additionalProperties": false
}
}
}

If the registration payload is invalid (for example the password doesn't match the password policy, the email is missing, ...), the password method includes the validation errors:

User Registration HTML Form with validation errors

When validation errors happen, browser clients receive a HTTP 303 See Other redirect to the Registration UI, containing the Registration Flow ID which includes the error payloads.

For API Clients, the server typically responds with HTTP 400 Bad Request and the Registration Flow in the response payload as JSON.

Registration with Google, Facebook, GitHub, ..., OpenID Connect / OAuth 2.0

Completing the oidc method requires the user to go through an OAuth 2.0 or OpenID Connect flow which involves logging into the upstream identity provider (for example Google) and giving consent.

note

If the user has already sign up with the given provider before, the user will simply be logged in and no new Ory Identities Identity will be created.

A possible validation error is a missing ID Token:

curl -s -H "Accept: application/json" \
'https://playground.projects.oryapis.com/self-service/registration/flows?id=76cec270-1719-4c9e-b09a-4af8281d511e' \
| jq -r '.ui.messages'

[
{
"id": 4000001,
"text": "Authentication failed because no id_token was returned. Please accept the \"openid\" permission and try again.",
"type": "error"
}
]

What may also happen is that the Identity Schema JSON includes a field which is required but wasn't provided by the upstream identity provider (for example Google). In those cases, the end-user's browser is returned to the registration screen with the form validation errors.

Let's assume the Identity Schema JSON requires a website trait

 {
"$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
}
}
}
},
+ "website": {
+ "type": "string"
+ }
},
"required": [
"email",
+ "website"
],
"additionalProperties": false
}
}
}

which wasn't provided by the upstream identity provider. This can happen when the user refuses to accept a certain scope (for example "Allow Ory Identities access to my website") or if the provider simply doesn't have this data (for example the upstream identity provider doesn't collect the user's website).

In that case the end-user ends up at the registration screen and is prompted to provide the missing or invalid fields:

User Registration HTML Form with missing or invalid fields when performing an OpenID Connect flow

Successful registration

Completing the registration behaves differently for Browser and API Clients. The Registration Flow doesn't issue a Ory Identities Login Session automatically which prevents Account Enumeration Attacks. If these types of attacks aren't your concern, you can add the session hook which will issue a session after successful registration:

config.yml
selfservice:
flows:
registration:
after:
password:
hooks:
- hook: session
oidc:
hooks:
- hook: session # Always enable this for oidc flows or the user experience suffers significantly!
info

It's very important to add the "session" hook to the after oidc registration hooks. Otherwise your users need to use the login flow again to be able to get a session. Account Enumeration Attacks with OpenID Connect sign in flows are typically not an issue if you follow the guidelines in the social sign-in documentation!

Server-side browser clients

When the registration is completed successfully, Ory Identities responds with a HTTP 303 Redirect to the configured redirect URL.

With auto-login on registration

If the session after hook is enabled, a Set-Cookie HTTP Header is set alongside the HTTP 303 redirect which contains the Ory Session Cookie:

HTTP/1.1 303 See Other
Cache-Control: 0
Location: http://127.0.0.1:4455/
Set-Cookie: csrf_token=b8OebRPTPr5ow23mA5gIZmFNLeuMbv8pZz1jT1Ex7ys=; Path=/; Domain=127.0.0.1; Max-Age=31536000; HttpOnly
Set-Cookie: ory_kratos_session=MTU5OTE2ODc2N3xEdi1CQkFFQ180SUFBUkFCRUFBQVJfLUNBQUVHYzNSeWFXNW5EQThBRFhObGMzTnBiMjVmZEc5clpXNEdjM1J5YVc1bkRDSUFJR055VlROMGRteHhSakJrUzBkbmRUUjBlVFY1V0RCRWFVTnJXVmR6V25oaHx2DICsB6IMbaHSQwnYITUZqr7Qx7CxUlnaneJWH495wQ==; Path=/; Expires=Fri, 04 Sep 2020 21:32:47 GMT; Max-Age=86400; HttpOnly; SameSite=Lax
Vary: Cookie
Date: Thu, 03 Sep 2020 21:32:47 GMT
Content-Length: 0

Now, whenever the browser is making a request (with cookies) to the http://127.0.0.1/sessions/whoami endpoint, the session will be returned:

curl -s -H "Cookie: ory_kratos_session=MTU5OTE2ODc2N3xEdi1CQkFFQ180SUFBUkFCRUFBQVJfLUNBQUVHYzNSeWFXNW5EQThBRFhObGMzTnBiMjVmZEc5clpXNEdjM1J5YVc1bkRDSUFJR055VlROMGRteHhSakJrUzBkbmRUUjBlVFY1V0RCRWFVTnJXVmR6V25oaHx2DICsB6IMbaHSQwnYITUZqr7Qx7CxUlnaneJWH495wQ==" \
https://playground.projects.oryapis.com/sessions/whoami | jq

{
"id": "ede90ce6-2420-435a-a745-3d8ab1a9636c",
"active": true,
"expires_at": "2020-09-04T21:32:47.5642404Z",
"authenticated_at": "2020-09-03T21:32:47.5881038Z",
"issued_at": "2020-09-03T21:32:47.5642688Z",
"identity": {
"id": "d96e86d9-bc33-4aa5-b865-4ade8a3974b3",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "foouser@ory.sh",
"name": {
"first": "foo",
"last": "user"
}
},
"verifiable_addresses": [
{
"id": "81bbdeae-6333-42f2-877e-26c78acb6ea5",
"value": "foouser@ory.sh",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "596c1db4-ccaa-4f4e-9623-cb7e768026ad",
"value": "foouser@ory.sh",
"via": "email"
}
]
}
}

Client-side browser clients

When the registration is completed successfully, Ory Identities responds with a HTTP 200 OK message which contains the identity:

{
"identity": {
"id": "d8baf63b-7ce6-4275-82b9-9ac6d97e5037",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "registration-api@user.org"
},
"verifiable_addresses": [
{
"id": "87defb49-ad69-461c-b5f6-56c1ec39dd39",
"value": "registration-api@user.org",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "232793b8-8d60-427d-89e6-d0a97a7a172c",
"value": "registration-api@user.org",
"via": "email"
}
]
}
}

With auto-login on registration

If the session after hook is enabled, a Set-Cookie HTTP Header is set alongside the HTTP 303 redirect which contains the Ory Session Cookie:

HTTP/1.1 303 See Other
Cache-Control: 0
Location: http://127.0.0.1:4455/
Set-Cookie: csrf_token=b8OebRPTPr5ow23mA5gIZmFNLeuMbv8pZz1jT1Ex7ys=; Path=/; Domain=127.0.0.1; Max-Age=31536000; HttpOnly
Set-Cookie: ory_kratos_session=MTU5OTE2ODc2N3xEdi1CQkFFQ180SUFBUkFCRUFBQVJfLUNBQUVHYzNSeWFXNW5EQThBRFhObGMzTnBiMjVmZEc5clpXNEdjM1J5YVc1bkRDSUFJR055VlROMGRteHhSakJrUzBkbmRUUjBlVFY1V0RCRWFVTnJXVmR6V25oaHx2DICsB6IMbaHSQwnYITUZqr7Qx7CxUlnaneJWH495wQ==; Path=/; Expires=Fri, 04 Sep 2020 21:32:47 GMT; Max-Age=86400; HttpOnly; SameSite=Lax
Vary: Cookie

As well as information about the session:

{
"session": {
"id": "6d5ef6f4-ea54-4310-a762-473499835a48",
"active": true,
"expires_at": "2020-09-08T10:12:34.792802227Z",
"authenticated_at": "2020-09-07T10:12:34.797538934Z",
"issued_at": "2020-09-07T10:12:34.792813032Z",
"identity": {
"id": "8a7755df-1aac-4477-a53c-3f16fa059113",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "registration-session-api@user.org"
},
"verifiable_addresses": [
{
"id": "95139fe8-3360-4b08-adf6-4cc9b4555d86",
"value": "registration-session-api@user.org",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "e6987729-b6fa-48d5-aa15-c0a57edfdfc4",
"value": "registration-session-api@user.org",
"via": "email"
}
]
}
},
"identity": {
"id": "8a7755df-1aac-4477-a53c-3f16fa059113",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "registration-session-api@user.org"
},
"verifiable_addresses": [
{
"id": "95139fe8-3360-4b08-adf6-4cc9b4555d86",
"value": "registration-session-api@user.org",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "e6987729-b6fa-48d5-aa15-c0a57edfdfc4",
"value": "registration-session-api@user.org",
"via": "email"
}
]
}
}

API clients

For API clients, Ory Identities responds with a JSON payload which includes the signed up identity:

# Inits a Registration Flow
actionUrl=$(\
curl -s -X GET -H "Accept: application/json" \
"https://playground.projects.oryapis.com/self-service/registration/api" \
| jq -r '.ui.action'\
)

# Complete Registration Flow with password method
curl -s -X POST -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"traits.email": "registration-api@user.org", "password": "fhAzi860a", "method": "password"}' \
"$actionUrl" | jq

{
"identity": {
"id": "d8baf63b-7ce6-4275-82b9-9ac6d97e5037",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "registration-api@user.org"
},
"verifiable_addresses": [
{
"id": "87defb49-ad69-461c-b5f6-56c1ec39dd39",
"value": "registration-api@user.org",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "232793b8-8d60-427d-89e6-d0a97a7a172c",
"value": "registration-api@user.org",
"via": "email"
}
]
}
}

With auto-login on registration

If the session after hook is enabled, the Ory Session Cookie and Ory Session Token are included in the response:

actionUrl=$(\
curl -s -X GET -H "Accept: application/json" \
"https://playground.projects.oryapis.com/self-service/registration/api" \
| jq -r '.ui.action'\
)

curl -s -X POST -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"traits.email": "registration-api@user.org", "password": "fhAzi860a", "method": "password"}' \
"$actionUrl" | jq

{
"session_token": "9kmrgslvw8ZCyEtSZqOmxEtnfBJIvB31",
"session": {
"id": "6d5ef6f4-ea54-4310-a762-473499835a48",
"active": true,
"expires_at": "2020-09-08T10:12:34.792802227Z",
"authenticated_at": "2020-09-07T10:12:34.797538934Z",
"issued_at": "2020-09-07T10:12:34.792813032Z",
"identity": {
"id": "8a7755df-1aac-4477-a53c-3f16fa059113",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "registration-session-api@user.org"
},
"verifiable_addresses": [
{
"id": "95139fe8-3360-4b08-adf6-4cc9b4555d86",
"value": "registration-session-api@user.org",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "e6987729-b6fa-48d5-aa15-c0a57edfdfc4",
"value": "registration-session-api@user.org",
"via": "email"
}
]
}
},
"identity": {
"id": "8a7755df-1aac-4477-a53c-3f16fa059113",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"traits": {
"email": "registration-session-api@user.org"
},
"verifiable_addresses": [
{
"id": "95139fe8-3360-4b08-adf6-4cc9b4555d86",
"value": "registration-session-api@user.org",
"verified": false,
"via": "email",
"status": "pending",
"verified_at": null
}
],
"recovery_addresses": [
{
"id": "e6987729-b6fa-48d5-aa15-c0a57edfdfc4",
"value": "registration-session-api@user.org",
"via": "email"
}
]
}
}

Code examples for Node.js, React.js, Go, ...

The Registration User Interface is a route (page / site) in your application (server, native app, single page app) that should render a registration form.

In stark contrast to other Identity Systems, Ory Identities 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 Registration Flow JSON response to render the registration form UI, which could looks as follows depending on your programming language and web framework:

User Registration HTML Form

Hooks

Ory Identities allows you to configure hooks that run before and after a Registration Flow. This may be helpful if you'd like to restrict registration to IPs coming from your internal network or other logic.

For more information about hooks please read the Hook Documentation.

API examples

Registering new user information

Using the /self-service/registration with POST allows the creation of new user information

actionUrl=$(curl -s -X GET  -H "Accept: application/json" \
https:/playground.projects.oryapis.com/self-service/registration/api \
| jq -r '.ui.action')

curl -s -X POST -H "Content-Type: application/json" \
-d '{"traits.email": "iminvisibleagain@google.com", "password": "__MY__PASSWORD__", "method": "password"}' \
"$actionUrl" | jq

On successful response will get JSON response like the following:

{
"session_token": "UA8rB8ydXyMyiIWcX8VeSWjUB7Z21YF1",
"session": {
"id": "5a55e850-6eea-4e34-a716-c2f5dbea6db6",
"active": true,
"expires_at": "2021-07-15T08:41:26.339781706Z",
"authenticated_at": "2021-07-14T08:41:26.379062124Z",
"issued_at": "2021-07-14T08:41:26.339798436Z",
"identity": {
"id": "bd1fbe06-7273-462c-ad8c-d077bfc370b9",
"schema_id": "default",
"schema_url": "https://playground.projects.oryapis.com/schemas/default",
"state": "active",
"state_changed_at": "2021-07-14T08:41:26.29470737Z",
"traits": {
"email": "iminvisibleagain@google.com"
},
// ...
}
}
}