diff --git a/docs/docs/images/quickstart/quickstart-recover-i.png b/docs/docs/images/quickstart/quickstart-recover-i.png index 1ed7adb20633..54b53b973cef 100644 Binary files a/docs/docs/images/quickstart/quickstart-recover-i.png and b/docs/docs/images/quickstart/quickstart-recover-i.png differ diff --git a/docs/docs/images/quickstart/quickstart-recover-ii.png b/docs/docs/images/quickstart/quickstart-recover-ii.png index 6cd68d3c4cb3..f23f01825bac 100644 Binary files a/docs/docs/images/quickstart/quickstart-recover-ii.png and b/docs/docs/images/quickstart/quickstart-recover-ii.png differ diff --git a/docs/docs/images/quickstart/quickstart-recover-iii.png b/docs/docs/images/quickstart/quickstart-recover-iii.png index a61a1e111bf2..63f27203ef7b 100644 Binary files a/docs/docs/images/quickstart/quickstart-recover-iii.png and b/docs/docs/images/quickstart/quickstart-recover-iii.png differ diff --git a/docs/docs/images/quickstart/quickstart-recover-iv.png b/docs/docs/images/quickstart/quickstart-recover-iv.png index b3ff4a5c8f2e..f31e5df65727 100644 Binary files a/docs/docs/images/quickstart/quickstart-recover-iv.png and b/docs/docs/images/quickstart/quickstart-recover-iv.png differ diff --git a/docs/docs/images/quickstart/secureapp-dashboard.png b/docs/docs/images/quickstart/secureapp-dashboard.png index 7d7005589b37..e0201aad930e 100644 Binary files a/docs/docs/images/quickstart/secureapp-dashboard.png and b/docs/docs/images/quickstart/secureapp-dashboard.png differ diff --git a/docs/docs/images/quickstart/secureapp-login-ntrace.png b/docs/docs/images/quickstart/secureapp-login-ntrace.png index 3225adb713a2..2d198643275f 100644 Binary files a/docs/docs/images/quickstart/secureapp-login-ntrace.png and b/docs/docs/images/quickstart/secureapp-login-ntrace.png differ diff --git a/docs/docs/images/quickstart/secureapp-login.png b/docs/docs/images/quickstart/secureapp-login.png index 2b53ab489a22..0a89ed8cc941 100644 Binary files a/docs/docs/images/quickstart/secureapp-login.png and b/docs/docs/images/quickstart/secureapp-login.png differ diff --git a/docs/docs/images/quickstart/secureapp-registration-ntrace.png b/docs/docs/images/quickstart/secureapp-registration-ntrace.png index e0de38397bbd..7aac419ddd9f 100644 Binary files a/docs/docs/images/quickstart/secureapp-registration-ntrace.png and b/docs/docs/images/quickstart/secureapp-registration-ntrace.png differ diff --git a/docs/docs/images/quickstart/secureapp-registration-pwpolicy.png b/docs/docs/images/quickstart/secureapp-registration-pwpolicy.png index c23407de6418..d07b17d33d23 100644 Binary files a/docs/docs/images/quickstart/secureapp-registration-pwpolicy.png and b/docs/docs/images/quickstart/secureapp-registration-pwpolicy.png differ diff --git a/docs/docs/images/quickstart/secureapp-registration.png b/docs/docs/images/quickstart/secureapp-registration.png index 3e79a16101df..f24780b08825 100644 Binary files a/docs/docs/images/quickstart/secureapp-registration.png and b/docs/docs/images/quickstart/secureapp-registration.png differ diff --git a/docs/docs/images/quickstart/secureapp-verified-dashboard.png b/docs/docs/images/quickstart/secureapp-verified-dashboard.png deleted file mode 100644 index d9e1df5daa42..000000000000 Binary files a/docs/docs/images/quickstart/secureapp-verified-dashboard.png and /dev/null differ diff --git a/docs/docs/images/quickstart/ui-unverified-dashboard.png b/docs/docs/images/quickstart/ui-unverified-dashboard.png new file mode 100644 index 000000000000..60eff5c49272 Binary files /dev/null and b/docs/docs/images/quickstart/ui-unverified-dashboard.png differ diff --git a/docs/docs/quickstart.mdx b/docs/docs/quickstart.mdx index 29cdc576e3d4..14c17fbf5272 100644 --- a/docs/docs/quickstart.mdx +++ b/docs/docs/quickstart.mdx @@ -22,6 +22,12 @@ merely a guide to get you set up with some examples. allowfullscreen /> +:::info + +Video based on Ory Kratos 0.5.5 quickstart, so some routes a changed. + +::: + ## Use Case: Application Login and Registration This section gives you some context on what we want to achieve and what tools we @@ -29,10 +35,9 @@ need for that. You will also learn about the network set up we picked for this guide. This quickstart guide operates on the assumption that we are writing a NodeJS -app called **SecureApp**. This app is using nothing fancy - some ExpressJS and a -bit of HTML Templating using Handlebars. We do want to use TypeScript, but only -because it's more readable - not because we're doing anything out of the -ordinary! +app. This app is using nothing fancy - some ExpressJS and a bit of HTML +Templating using Handlebars. We do want to use TypeScript, but only because it's +more readable - not because we're doing anything out of the ordinary! You could pick any technology here, of course. This works with Swift, ReactJS, or Angular (client side) as well as with PHP, Ruby, Python, Java (server side) - @@ -40,8 +45,8 @@ you name it! We picked NodeJS + TypeScript because we believe it is the easiest to understand, and because JavaScript and NodeJS are universally understood and easy to install. -We know that SecureApp will need to have some type of dashboard and that it -needs users. Therefore, we need: +We know our app will need to have some type of dashboard and that it needs +users. Therefore, we need: - Login - Logout @@ -62,7 +67,7 @@ and of course: As you might already know, Ory Kratos is API-only; it does not have a UI or HTML templating engine. We will implement all the user-facing UIs like "dashboard", -"login", and "registration" in our NodeJS SecureApp! +"login", and "registration" in our NodeJS app! To ensure that no one can access the dashboard without prior authentication (login), we can use a small piece of code (here ExpressJS) to do that: @@ -80,9 +85,9 @@ and more so you don't have to. ::: -The SecureApp and Ory Kratos need to share cookies in order for anti-CSRF tokens -and login sessions to work. Because the quickstart runs on different ports on -`127.0.0.1` there is nothing we need to do to get this all working. In +The NodeJS app and Ory Kratos need to share cookies in order for anti-CSRF +tokens and login sessions to work. Because the quickstart runs on different +ports on `127.0.0.1` there is nothing we need to do to get this all working. In environments where you have multiple sub-domains or reverse proxies, the set up will be a bit more sophisticated. You can find more information about the different set up possibilities in the @@ -154,10 +159,9 @@ There are two important factors to get a fully functional system: ::: -You might notice that no database is being used in this example. Ory Kratos -supports SQLite, PostgreSQL, MySQL, and CockroachDB as database backends. For -the quickstart, we're mounting a persistent volume to store the SQLite database -in. +There is no database being used in this example. Ory Kratos supports SQLite, +PostgreSQL, MySQL, and CockroachDB as database backends. For the quickstart, +we're mounting a persistent volume to store the SQLite database in. Future guides will explain how to set up a production system. @@ -169,7 +173,7 @@ This demo makes use of several services: - Public ("Browser") API (port 4433) - Admin API (port 4434) - This is only made public so we can test via the CLI. -2. [SecureApp](http://github.com/ory/kratos-selfservice-ui-node) +2. [NodeJS Selfservice UI](http://github.com/ory/kratos-selfservice-ui-node) - Public (port 4455) - an example application written in NodeJS that implements the login, registration, logout, dashboard, and other UIs. 3. [MailSlurper](https://github.com/mailslurper) @@ -188,7 +192,7 @@ subgraph hn[Host Network] B-->|Can access URLs via 127.0.0.1:4455|OKPHN B-->|Can access URLs via 127.0.0.1:4433|PAPI B-->|Can access UI via 127.0.0.1:4436|SMTPUI - OKPHN([SecureApp exposed at :4455]) + OKPHN([Selfservice UI exposed at :4455]) SMTPUI([MailSlurper UI exposed at :4436]) PAPI([Ory Kratos Public API exposed at :4433]) end @@ -199,7 +203,7 @@ subgraph dn["Internal Docker Network (intranet)"] SA-->|Talks to and validates login sessions using|OK OK-->|Sends mail via|SMTP OK[Ory Kratos] - SA["SecureApp (Ory Kratos SelfService UI Node Example)"] + SA["Selfservice UI (Ory Kratos SelfService UI Node Example)"] SMTP["SMTP Server (MailSlurper)"] end `} @@ -211,10 +215,25 @@ Enough theory, it's time to get this thing going! Let's start by trying to open the dashboard - **go to [127.0.0.1:4455/welcome](http://127.0.0.1:4455/welcome)**. -You should notice that you're ending up at the login endpoint instead of the -dashboard: +You should end up at the dashboard: + +![Dashboard screen of your secured app](images/quickstart/ui-unverified-dashboard.png) -![Login screen of your secured app](images/quickstart/secureapp-login.png) +Under the section `Session Information` you can find the Ory Session details, as +there is no active session this is empty for now. + +:::note + +The rendered login form should be a standard HTML `
`. AJAX requests +require `credentials: 'include'`. This flow also works with Single Page Apps +(SPA) and frameworks like Angular or ReactJS. For more details about the +specific flows for SPAs head over to the [concept](concepts/index.md) chapter. + +::: + +Click `Sign In` to start a login flow. On the Sign In Screen you can see the +unique login `` e.g. `?flow=78e374d2-f36b-40ae-922d-e81f812ea897` +appended to the /login route in the URL. Looking at the network stack, you can see two redirects happening: @@ -222,37 +241,25 @@ Looking at the network stack, you can see two redirects happening: Here's a play-by-play of what happened: -1. SecureApp used the Ory Kratos JavaScript language client to guard the - `/dashboard` route. The Ory Kratos client checked the cookies from the - request and saw you were not logged in. -2. The route guard redirected you from `/dashboard` to `/auth/login`. Ory - Kratos' browser API requires a `` in order to log you in. It looked - for this ID in the URL as a query parameter but couldn't find it. -3. `/auth/login` redirected you to +1. `/login` redirected you to `http://127.0.0.1:4434/self-service/login/browser`, which is one of Ory Kratos' APIs used for logging in browser-based applications. -4. Kratos handled `/self-service/login/browser` which created and persisted a +2. Kratos handled `/self-service/login/browser` which created and persisted a new flow with `csrf_token`. Kratos would check no session exists, redirected - the browser to `/auth/login?flow=`. If session exists already, the + the browser to `/login?flow=`. If a session exists already, the browser will be redirected to `urls.default_redirect_url` unless the query parameter `?refresh=true` was set. -5. SecureApp handled the `/auth/login` route, found the `` in the URL +3. The login UI handled the `/login` route, found the `` in the URL query parameter, and used it to make an HTTP request to - `http://kratos:4434/self-service/login/flows?id=`. Notice the URI is - `kratos:4434` because SecureApp is making a server-side HTTP request via + `http://kratos:4433/self-service/login/flows?id=`. Notice the URI is + `kratos:4433` because SecureApp is making a server-side HTTP request via Docker's private network to Ory Kratos' Admin API. -6. Ory Kratos responded with data which SecureApp used to render the HTML login +4. Ory Kratos responded with data which SecureApp used to render the HTML login form. -:::note - -Your rendered login form should be a standard HTML ``. AJAX requests will -not work! - -::: - We can use `curl` to get an example of the payload that Ory Kratos responds -with. `GET` a valid `` and make a request to `/self-service/login/`: +with. `GET` a valid `` or copy it from your browser and make a request +to `/self-service/login/`: ```shell-session $ flowId=$(curl -s -X GET \ @@ -262,13 +269,13 @@ $ curl -s -X GET \ -H "Accept: application/json" \ "http://127.0.0.1:4433/self-service/login/flows?id=$flowId" | jq { - "id": "5b299430-0e68-441f-b1c5-a83657bdb25f", + "id": "f091ccf5-df85-493e-a9a3-de9b86925a45", "type": "api", - "expires_at": "2021-09-22T12:44:41.2436371Z", - "issued_at": "2021-09-22T12:34:41.2436371Z", + "expires_at": "2021-12-13T18:31:57.1189985Z", + "issued_at": "2021-12-13T18:21:57.1189985Z", "request_url": "http://127.0.0.1:4433/self-service/login/api", "ui": { - "action": "http://127.0.0.1:4433/self-service/login?flow=5b299430-0e68-441f-b1c5-a83657bdb25f", + "action": "http://127.0.0.1:4433/self-service/login?flow=f091ccf5-df85-493e-a9a3-de9b86925a45", "method": "POST", "nodes": [ { @@ -279,7 +286,8 @@ $ curl -s -X GET \ "type": "hidden", "value": "", "required": true, - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": {} @@ -292,7 +300,8 @@ $ curl -s -X GET \ "type": "text", "value": "", "required": true, - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -310,7 +319,8 @@ $ curl -s -X GET \ "name": "password", "type": "password", "required": true, - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -328,7 +338,8 @@ $ curl -s -X GET \ "name": "method", "type": "submit", "value": "password", - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -342,16 +353,13 @@ $ curl -s -X GET \ } ] }, - "created_at": "2021-09-22T12:34:41.244707Z", - "updated_at": "2021-09-22T12:34:41.244707Z", - "forced": false + "created_at": "2021-12-13T18:21:57.121894Z", + "updated_at": "2021-12-13T18:21:57.121894Z", + "refresh": false, + "requested_aal": "aal1" } ``` -This flow also works with Single Page Apps (SPA) and frameworks like Angular or -ReactJS. For more details about the specific flows (login, registration, logout, -etc.), head over to the [concept](concepts/index.md) chapter. - Let's move on to the next flow - registration! Click on "Register new account", which initiates a flow similar to the one we just used: @@ -372,15 +380,14 @@ $ flowId=$(curl -s -X GET \ $ curl -s -X GET \ -H "Accept: application/json" \ "http://127.0.0.1:4433/self-service/registration/flows?id=$flowId" | jq - { - "id": "4d1d11c8-12f0-4d29-8801-795c5072ed7a", + "id": "d62a3a8d-d3f3-4ca5-af54-0e8747b53b41", "type": "api", - "expires_at": "2021-09-22T18:10:11.0677811Z", - "issued_at": "2021-09-22T18:00:11.0677811Z", + "expires_at": "2021-12-13T19:55:06.9350485Z", + "issued_at": "2021-12-13T19:45:06.9350485Z", "request_url": "http://127.0.0.1:4433/self-service/registration/api", "ui": { - "action": "http://127.0.0.1:4433/self-service/registration?flow=4d1d11c8-12f0-4d29-8801-795c5072ed7a", + "action": "http://127.0.0.1:4433/self-service/registration?flow=d62a3a8d-d3f3-4ca5-af54-0e8747b53b41", "method": "POST", "nodes": [ { @@ -391,7 +398,8 @@ $ curl -s -X GET \ "type": "hidden", "value": "", "required": true, - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": {} @@ -402,7 +410,9 @@ $ curl -s -X GET \ "attributes": { "name": "traits.email", "type": "email", - "disabled": false + "required": true, + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -420,7 +430,8 @@ $ curl -s -X GET \ "name": "password", "type": "password", "required": true, - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -437,7 +448,8 @@ $ curl -s -X GET \ "attributes": { "name": "traits.name.first", "type": "text", - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -454,7 +466,8 @@ $ curl -s -X GET \ "attributes": { "name": "traits.name.last", "type": "text", - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -472,7 +485,8 @@ $ curl -s -X GET \ "name": "method", "type": "submit", "value": "password", - "disabled": false + "disabled": false, + "node_type": "input" }, "messages": [], "meta": { @@ -525,7 +539,59 @@ Next, click the verification link. You will end up at the dashboard, with a verified email address (check the `verified` and `verified_at` field in the JSON response): -![SecureApp Dashboard](images/quickstart/secureapp-verified-dashboard.png) +```json {31} +{ + "id": "5fe6b562-c5a6-4adf-a3a7-a1e588c11c66", + "active": true, + "expires_at": "2021-12-14T19:35:21.7271879Z", + "authenticated_at": "2021-12-13T19:35:21.7271879Z", + "authenticator_assurance_level": "aal1", + "authentication_methods": [ + { + "method": "password", + "completed_at": "2021-12-13T19:35:21.7271762Z" + } + ], + "issued_at": "2021-12-13T19:35:21.7271879Z", + "identity": { + "id": "0435468f-5b39-4f06-8257-af418412891d", + "schema_id": "default", + "schema_url": "http://127.0.0.1:4433/schemas/default", + "state": "active", + "state_changed_at": "2021-12-13T19:32:48.7715418Z", + "traits": { + "name": { + "first": "Foo", + "last": "Bar" + }, + "email": "foo@ory.sh" + }, + "verifiable_addresses": [ + { + "id": "9fccf5c1-c374-4a15-8f01-1fd5cb3bea55", + "value": "foo@ory.sh", + "verified": true, + "via": "email", + "status": "completed", + "verified_at": "2021-12-13T19:34:45.4343846Z", + "created_at": "2021-12-13T19:32:48.775138Z", + "updated_at": "2021-12-13T19:34:53.449022Z" + } + ], + "recovery_addresses": [ + { + "id": "0df6ddf6-780b-4c3c-ba31-4a349a2a1bc5", + "value": "foo@ory.sh", + "via": "email", + "created_at": "2021-12-13T19:32:48.775823Z", + "updated_at": "2021-12-13T19:34:53.449207Z" + } + ], + "created_at": "2021-12-13T19:32:48.773627Z", + "updated_at": "2021-12-13T19:32:48.773627Z" + } +} +``` To re-request the verification email, fill out the form at [127.0.0.1:4455/verification](http://127.0.0.1:4455/verification). @@ -536,7 +602,7 @@ To learn more about verification recovery, head over to the ### Account Recovery The quickstart has account recovery enabled. To recover an account, log out and -click on "Reset password": +click on "Recover Account": ![Click on recover account](images/quickstart/quickstart-recover-i.png)