(window.webpackJsonp=window.webpackJsonp||[]).push([[349],{415:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return u})),t.d(n,"metadata",(function(){return p})),t.d(n,"toc",(function(){return f})),t.d(n,"default",(function(){return m}));var a=t(3),o=t(8),i=(t(0),t(553)),s=t(572),r=t(575),l=t(700),c=t(573),d=t(574),u={id:"self-service",title:"Self-Service Flows",sidebar_label:"Concepts and Overview"},p={unversionedId:"self-service",id:"version-v0.6/self-service",isDocsHomePage:!1,title:"Self-Service Flows",description:"Ory Kratos implements flows that users perform themselves as opposed to",source:"@site/versioned_docs/version-v0.6/self-service.mdx",sourceDirName:".",slug:"/self-service",permalink:"/kratos/docs/self-service",editUrl:"https://github.com/ory/kratos/edit/master/docs/versioned_docs/version-v0.6/self-service.mdx",version:"v0.6",lastUpdatedBy:"aeneasr",lastUpdatedAt:1619690398,formattedLastUpdatedAt:"4/29/2021",sidebar_label:"Concepts and Overview",frontMatter:{id:"self-service",title:"Self-Service Flows",sidebar_label:"Concepts and Overview"},sidebar:"version-v0.6/docs",previous:{title:"Threat Models and Security Profiles",permalink:"/kratos/docs/concepts/security"},next:{title:"User Registration",permalink:"/kratos/docs/self-service/flows/user-registration"}},f=[{value:"Performing Login, Registration, Settings, ... Flows",id:"performing-login-registration-settings--flows",children:[]},{value:"Browser Flows",id:"browser-flows",children:[{value:"Initialization and Redirect to UI",id:"initialization-and-redirect-to-ui",children:[]},{value:"Form Rendering",id:"form-rendering",children:[]},{value:"Form Submission and Payload Validation",id:"form-submission-and-payload-validation",children:[]}]},{value:"API Flows",id:"api-flows",children:[{value:"Initialization",id:"initialization",children:[]},{value:"Form Rendering",id:"form-rendering-1",children:[]},{value:"Form Submission and Payload Validation",id:"form-submission-and-payload-validation-1",children:[]}]}],b={toc:f};function m(e){var n=e.components,t=Object(o.a)(e,["components"]);return Object(i.b)("wrapper",Object(a.a)({},b,t,{components:n,mdxType:"MDXLayout"}),Object(i.b)("p",null,"Ory Kratos implements flows that users perform themselves as opposed to\nadministrative intervention. Facebook and Google both provide self-service\nregistration and profile management features as you are able to make changes to\nyour profile and sign up yourself."),Object(i.b)("p",null,"Most believe that user management systems are easy to implement because picking\nthe right password hashing algorithm and sending an account verification code is\na solvable challenge. The real complexity however hides in the details and\nattack vectors of self-service flows. Most data leaks happen because someone is\nable to exploit"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"registration: with attack vectors such as account enumeration (), ...;"),Object(i.b)("li",{parentName:"ul"},"login: phishing, account enumeration, leaked password databases, brute-force,\n...;"),Object(i.b)("li",{parentName:"ul"},"user settings: account enumeration, account takeover, ...;"),Object(i.b)("li",{parentName:"ul"},"account recovery: social engineering attacks, account takeover, spoofing, and\nso on.")),Object(i.b)("p",null,"There are also many other areas you need to think about, such as:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Mobile, Smart TV, ... authentication"),Object(i.b)("li",{parentName:"ul"},'Linking and unlinking social profiles (e.g. "Sign in with Google" or "Connect\nwith Google") to existing accounts')),Object(i.b)("p",null,"Ory Kratos applies best practices established by experts (National Institute of\nSciences NIST, Internet Engineering Task Force IETF, Microsoft Research, Google\nResearch, Troy Hunt, ...) and implements the following flows:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/user-registration"},"Registration")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/user-login"},"Login")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/user-logout"},"Logout")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/user-settings"},"User Settings")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/account-recovery"},"Account Recovery")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/verify-email-account-activation"},"Address Verification")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/user-facing-errors"},"User-Facing Error")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/kratos/docs/self-service/flows/2fa-mfa-multi-factor-authentication"},"2FA / MFA"))),Object(i.b)("p",null,'Some flows break down into "flow methods" which implement some of the flow\'s\nbusiness logic:'),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"The ",Object(i.b)("inlineCode",{parentName:"li"},"password"),' method implements the login and registration with "email or/and\nusername and password" method, and "change your password" user settings\nmethod.'),Object(i.b)("li",{parentName:"ul"},"The ",Object(i.b)("inlineCode",{parentName:"li"},"oidc"),' (OpenID Connect, OAuth2, Social Sign In) method implements "Sign in\nwith ..." login and registration method and "un/link another social account"\nuser settings method.'),Object(i.b)("li",{parentName:"ul"},"The ",Object(i.b)("inlineCode",{parentName:"li"},"profile"),' method implements the "update your profile", "change your\nfirst/last name, ..." user settings method).'),Object(i.b)("li",{parentName:"ul"},"The ",Object(i.b)("inlineCode",{parentName:"li"},"link"),' method implements the "click this link to reset your password"\naccount recovery method.')),Object(i.b)("p",null,"Some flows additionally implement the ability\n",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/self-service/hooks"},"to run hooks")," which allow users to be immediately\nsigned in after registration, notify another system on successful registration\n(e.g. Mailchimp), and so on."),Object(i.b)("h2",{id:"performing-login-registration-settings--flows"},"Performing Login, Registration, Settings, ... Flows"),Object(i.b)("p",null,"There are two flow types supported in Ory Kratos:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Flows where the user sits in front of the Browser (e.g. website, single page\napp, ...)"),Object(i.b)("li",{parentName:"ul"},"Flows where API interaction is required (e.g. mobile app, Smart TV, ...)")),Object(i.b)("p",null,"All Self-Service Flows (",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/self-service/flows/user-login"},"User Login"),",\n",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/self-service/flows/user-registration"},"User Registration"),",\n",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/self-service/flows/user-settings"},"Profile Management"),",\n",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/self-service/flows/account-recovery"},"Account Recovery"),",\n",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/self-service/flows/verify-email-account-activation"},"Email or Phone verification"),")\nsupport these two flow types and use the same data models but do use different\nAPI endpoints."),Object(i.b)(s.a,{mdxType:"ApiWarning"}),Object(i.b)("h2",{id:"browser-flows"},"Browser Flows"),Object(i.b)("p",null,"Browser-based flows make use of three core HTTP technologies:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"HTTP Redirects"),Object(i.b)("li",{parentName:"ul"},"HTTP POST (",Object(i.b)("inlineCode",{parentName:"li"},"application/x-www-urlencoded"),") and REST GET requests."),Object(i.b)("li",{parentName:"ul"},"HTTP Cookies to prevent CSRF and Session Hijaking attack vectors.")),Object(i.b)("p",null,"The browser flow is the easiest and most secure to set up and integrated with.\nOry Kratos takes care of all required session and CSRF cookies and ensures that\nall security requirements are fulfilled."),Object(i.b)("p",null,"The browser flow has three stages:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Initialization and redirect to UI;"),Object(i.b)("li",{parentName:"ul"},"Form rendering;"),Object(i.b)("li",{parentName:"ul"},"Form submission and payload validation.")),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",{parentName:"div",className:"admonition-heading"},Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",{parentName:"h5",className:"admonition-icon"},Object(i.b)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},Object(i.b)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"note")),Object(i.b)("div",{parentName:"div",className:"admonition-content"},Object(i.b)("p",{parentName:"div"},"The payloads, examples, ports, and IPs shown here are the ones used if you run\nthe ",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/quickstart"},"Quickstart"),". If you have not checked it out yet, please do\nso before reading this document."))),Object(i.b)(c.a,{flows:["login","settings","..."],mdxType:"SelfServiceBrowserFlow"}),Object(i.b)("h3",{id:"initialization-and-redirect-to-ui"},"Initialization and Redirect to UI"),Object(i.b)("p",null,"First, the Browser opens the flow's initialization endpoint\n(e.g.",Object(i.b)("inlineCode",{parentName:"p"},"/self-service/login/browser"),", ",Object(i.b)("inlineCode",{parentName:"p"},"/self-service/registration/browser"),", ...):"),Object(i.b)(r.a,{items:l.e,mdxType:"CodeTabs"}),Object(i.b)("p",null,'The initialization endpoint creates a flow object and stores it in the database.\nThe flow object has an ID and contains additional information about the flow\nsuch as the login methods (e.g. "username/password" and "Sign in with Google")\nand their form data.'),Object(i.b)("p",null,"Once stored, the Browser is HTTP 302 redirected to the flow's configured UI URL\n(e.g. ",Object(i.b)("inlineCode",{parentName:"p"},"selfservice.flows.login.ui_url"),"), appending the flow ID as the ",Object(i.b)("inlineCode",{parentName:"p"},"flow")," URL\nQuery Parameter. Also included will be might be some cookies such as Anti-CSRF\ncookies."),Object(i.b)("p",null,"The response will look along the lines of:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre"},'$ curl -s -v -X GET \\\n  -H "Accept: text/html" \\\n  http://127.0.0.1:4433/self-service/login/browser\n\n# Response Headers\n< HTTP/1.1 302 Found\n< Cache-Control: 0\n< Content-Type: text/html; charset=utf-8\n< Location: http://127.0.0.1:4455/auth/login?flow=f6209031-38d5-48bc-b6a5-118e8a24d1fe\n< Set-Cookie: csrf_token=qhMCbVX6iDyw1x/701zlINVFFqfkZrq1t/Z27Z1uFDw=; Path=/.ory/kratos/public/; Domain=127.0.0.1; Max-Age=31536000; HttpOnly\n< Vary: Cookie\n< Date: Mon, 17 Aug 2020 13:54:52 GMT\n< Content-Length: 97\n')),Object(i.b)("h3",{id:"form-rendering"},"Form Rendering"),Object(i.b)("p",null,"The Browser opens the URL (here\n",Object(i.b)("inlineCode",{parentName:"p"},"http://127.0.0.1:4455/auth/login?flow=f6209031-38d5-48bc-b6a5-118e8a24d1fe"),')\nwhich renders the HTML form which for example shows the "username and password"\nfield, the "Update your email address" field, or other flow forms. This HTML\nform is rendered be the\n',Object(i.b)("a",{parentName:"p",href:"/kratos/docs/concepts/ui-user-interface#self-service-user-interface-ssui"},"Self-Service UI"),"\nwhich you fully control."),Object(i.b)("p",null,"The endpoint responsible for the UI URL uses the ",Object(i.b)("inlineCode",{parentName:"p"},"flow")," URL Query Parameter\n(here ",Object(i.b)("inlineCode",{parentName:"p"},"...?flow=f6209031-38d5-48bc-b6a5-118e8a24d1fe"),") to call the flow\ninformation endpoint (e.g.\n",Object(i.b)("inlineCode",{parentName:"p"},"http://127.0.0.1:4434/self-service/login/flows?id=f6209031-38d5-48bc-b6a5-118e8a24d1fe"),")\nand fetch the flow data - so for example the login form and any validation\nerrors. This endpoint is available at both Ory Kratos's Public and Admin\nEndpoints. For example, the Self-Service UI responsible for rendering the Login\nHTML Form would make a request along the lines of:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre"},'# The endpoint uses Ory Kratos\' REST API to fetch information about the request\n$ curl -s -X GET \\\n    -H "Accept: application/json" \\\n    "http://127.0.0.1:4434/self-service/login/flows?id=f6209031-38d5-48bc-b6a5-118e8a24d1fe" | jq\n')),Object(i.b)("p",null,"The result includes login methods, their fields, and additional information\nabout the flow:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-json"},'{\n  "id": "f6209031-38d5-48bc-b6a5-118e8a24d1fe",\n  "type": "browser",\n  "expires_at": "2021-04-28T09:00:57.10254633Z",\n  "issued_at": "2021-04-28T08:50:57.10254633Z",\n  "request_url": "http://127.0.0.1:4433/self-service/login/browser",\n  "ui": {\n    "action": "http://127.0.0.1:4433/self-service/login?flow=f6209031-38d5-48bc-b6a5-118e8a24d1fe",\n    "method": "POST",\n    "nodes": [\n      {\n        "type": "input",\n        "group": "default",\n        "attributes": {\n          "name": "csrf_token",\n          "type": "hidden",\n          "value": "pUhD8lmSNNRnX/tuy6yAM317SfdiPOwetYUKnx23iTHnySErkBGJwaF1t3cEqNtxF3uC7W5A/dwP5l5VDYFRSA==",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {}\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password_identifier",\n          "type": "text",\n          "value": "",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070004,\n            "text": "ID",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password",\n          "type": "password",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070001,\n            "text": "Password",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "method",\n          "type": "submit",\n          "value": "password",\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1010001,\n            "text": "Sign in",\n            "type": "info",\n            "context": {}\n          }\n        }\n      }\n    ]\n  },\n  "forced": false\n}\n')),Object(i.b)("p",null,"For more details, check out the individual flow documentation."),Object(i.b)("p",null,"The flow UI then renders the given methods. For the example above, a suitable\nHTML Form would look along the lines of:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-html"},'<form\n  action="http://127.0.0.1:4433/self-service/login?flow=f6209031-38d5-48bc-b6a5-118e8a24d1fe"\n  method="POST"\n>\n  <input\n    name="csrf_token"\n    type="hidden"\n    value="pUhD8lmSNNRnX/tuy6yAM317SfdiPOwetYUKnx23iTHnySErkBGJwaF1t3cEqNtxF3uC7W5A/dwP5l5VDYFRSA=="\n  />\n  <fieldset>\n    <label>\n      <input name="password_identifier" type="text" value="" placeholder="ID" />\n      <span>ID</span>\n    </label>\n  </fieldset>\n  <fieldset>\n    <label>\n      <input name="password" type="password" value="" placeholder="Password" />\n      <span>Password</span>\n    </label>\n  </fieldset>\n  <button name="method" type="submit" value="password">Sign in</button>\n</form>\n')),Object(i.b)("h3",{id:"form-submission-and-payload-validation"},"Form Submission and Payload Validation"),Object(i.b)("p",null,"The user completes the flow by submitting the form. The form action always\npoints to Ory Kratos directly. The business logic for the flow method will then\nvalidate the form payload and return to the UI URL on validation errors. The UI\nthen fetches the information about the flow again"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre"},'# The endpoint uses Ory Kratos\' REST API to fetch information about the request\n$ curl -s -X GET \\\n    -H "Accept: application/json" \\\n    "http://127.0.0.1:4433/self-service/login/flows?id=f6209031-38d5-48bc-b6a5-118e8a24d1fe" | jq\n')),Object(i.b)("p",null,"which now includes validation errors and other potential messages:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-json5"},"{\n  id: 'f6209031-38d5-48bc-b6a5-118e8a24d1fe',\n  type: 'browser',\n  expires_at: '2021-04-28T09:00:57.10254633Z',\n  issued_at: '2021-04-28T08:50:57.10254633Z',\n  request_url: 'http://127.0.0.1:4433/self-service/login/browser',\n  ui: {\n    action: 'http://127.0.0.1:4433/self-service/login?flow=f6209031-38d5-48bc-b6a5-118e8a24d1fe',\n    method: 'POST',\n    nodes: [\n      // ...\n      {\n        type: 'input',\n        group: 'password',\n        attributes: {\n          name: 'password_identifier',\n          type: 'text',\n          value: '',\n          required: true,\n          disabled: false\n        },\n        messages: [\n          {\n            id: 4000001,\n            text: 'length must be >= 1, but got 0',\n            type: 'error'\n          }\n        ],\n        meta: {\n          label: {\n            id: 1070004,\n            text: 'ID',\n            type: 'info'\n          }\n        }\n      },\n      {\n        type: 'input',\n        group: 'password',\n        attributes: {\n          name: 'password',\n          type: 'password',\n          required: true,\n          disabled: false\n        },\n        messages: [\n          {\n            id: 4000001,\n            text: 'length must be >= 1, but got 0',\n            type: 'error'\n          }\n        ],\n        meta: {\n          label: {\n            id: 1070001,\n            text: 'Password',\n            type: 'info'\n          }\n        }\n      }\n      // ...\n    ]\n  },\n  forced: false\n}\n")),Object(i.b)("p",null,"If a system error (e.g. broken configuration file) occurs, the browser is\nredirected to the ",Object(i.b)("a",{parentName:"p",href:"/kratos/docs/self-service/flows/user-facing-errors"},"Error UI"),"."),Object(i.b)("p",null,"If the form payload is valid, the flow completes with a success. The result here\ndepends on the flow itself - the login flow for example redirects the user to a\nspecified redirect URL and sets a session cookie. The registration flow also\nredirects to a specified redirect URL but only creates the user in the database\nand might issue a session cookie if configured to do so."),Object(i.b)("h2",{id:"api-flows"},"API Flows"),Object(i.b)(s.a,{mdxType:"ApiWarning"}),Object(i.b)("p",null,"API flows have three stages:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Initialization ",Object(i.b)("strong",{parentName:"li"},"without redirect")),Object(i.b)("li",{parentName:"ul"},"Form rendering using e.g. native iOS, Android, ... components"),Object(i.b)("li",{parentName:"ul"},"Form submission as ",Object(i.b)("inlineCode",{parentName:"li"},"application/json")," and payload validation")),Object(i.b)("p",null,"The high-level sequence diagram for API flows looks as follows:"),Object(i.b)(d.a,{mdxType:"SelfServiceApiFlow"}),Object(i.b)("h3",{id:"initialization"},"Initialization"),Object(i.b)("p",null,"The client (e.g. mobile application) makes a request to the flow's\ninitialization endpoint (e.g.",Object(i.b)("inlineCode",{parentName:"p"},"/self-service/login/api"),",\n",Object(i.b)("inlineCode",{parentName:"p"},"/self-service/registration/api"),", ...):"),Object(i.b)(r.a,{items:l.d,mdxType:"CodeTabs"}),Object(i.b)("p",null,'The initialization endpoint creates a flow object and stores it in the database.\nThe flow object has an ID and contains additional information about the flow\nsuch as the login methods (e.g. "username/password" and "Sign in with Google")\nand their form data.'),Object(i.b)("h3",{id:"form-rendering-1"},"Form Rendering"),Object(i.b)("p",null,"While the Browser flow redirects the client and uses cookies to protect against\nCSRF and session hijacking attacks, the API flow answers with a fresh flow\nformatted as ",Object(i.b)("inlineCode",{parentName:"p"},"application/json")," right away. The client would then use that\ninformation to render the UI. In React Native, this may look like the following\nsnippet:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-tsx"},"import React, { useState, useEffect } from 'react'\nimport { Text, TextInput, View } from 'react-native'\nimport { PublicApi, LoginFlow } from '@ory/kratos-client'\n\nconst kratos = new PublicApi('http://127.0.0.1:4455/.ory/kratos/public')\n\nexport default function Login () {\n  const [flow, setFlow] = useState<LoginFlow | undefined>(undefined)\n\n  useEffect(() => {\n    kratos.initializeSelfServiceAPILoginFlow().then(({ data: flow }) => {\n      setFlow(flow)\n    })\n  }, [])\n\n  if (!flow) {\n    return null\n  }\n\n  // This is a non-functional, code example. It is missing state management and so on.\n  // The idea is to show how initializing such a flow would look like in an API scenario.\n  return (\n    <View>\n      <Text>Login</Text>\n\n      {flow.ui.nodes.map((node) => {\n        switch (node.type) {\n          case 'input':\n            return <TextInput value={node.attributes.value} /* placeholder, name, ... *//>\n          default:\n            // ...\n        }\n      })}\n    </>\n  )\n}\n")),Object(i.b)("p",null,"If needed, the client can re-request the flow using the same HTTP Request as the\nbrowser flow at the Public API endpoint:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-shell",metastring:"script",script:!0},'curl -s -X GET \\\n    -H "Accept: application/json" \\\n    "http://127.0.0.1:4433/self-service/login/flows?id=41ebf1e9-79f5-4b97-b643-04bfc405f8ad" | jq\n\n{\n  "id": "41ebf1e9-79f5-4b97-b643-04bfc405f8ad",\n  "type": "api",\n  # ...\n')),Object(i.b)("h3",{id:"form-submission-and-payload-validation-1"},"Form Submission and Payload Validation"),Object(i.b)("p",null,"The request is then completed by sending the form formatted as\n",Object(i.b)("inlineCode",{parentName:"p"},"application/json")," to the action endpoint"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-shell"},'flow=$(curl -s -X GET -H "Accept: application/json" "http://127.0.0.1:4433/self-service/login/api")\nactionUrl=$(echo $flow | jq -r \'.ui.action\')\n\necho $actionUrl\n# http://127.0.0.1:4433/self-service/login?flow=6394ffa4-235f-4c1a-a200-e62f89862015\n\ncurl -s -X POST -H  "Accept: application/json" -H "Content-Type: application/json" \\\n    -d \'{"password_identifier": "i-do-not-exist@user.org", "password": "the-wrong-password", "method": "password"}\' \\\n    "$actionUrl" | jq\n')),Object(i.b)("p",null,"which in this case fails with a 400 Bad Request error and the following payload:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-json"},'{\n  "id": "6394ffa4-235f-4c1a-a200-e62f89862015",\n  "type": "api",\n  "expires_at": "2021-04-28T09:12:48.462374732Z",\n  "issued_at": "2021-04-28T09:02:48.462374732Z",\n  "request_url": "http://127.0.0.1:4433/self-service/login/api",\n  "ui": {\n    "action": "http://127.0.0.1:4433/self-service/login?flow=6394ffa4-235f-4c1a-a200-e62f89862015",\n    "method": "POST",\n    "messages": [\n      {\n        "id": 4000006,\n        "text": "The provided credentials are invalid, check for spelling mistakes in your password or username, email address, or phone number.",\n        "type": "error",\n        "context": {}\n      }\n    ],\n    "nodes": [\n      {\n        "type": "input",\n        "group": "default",\n        "attributes": {\n          "name": "csrf_token",\n          "type": "hidden",\n          "value": "",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {}\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password_identifier",\n          "type": "text",\n          "value": "i-do-not-exist@user.org",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070004,\n            "text": "ID",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password",\n          "type": "password",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070001,\n            "text": "Password",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "method",\n          "type": "submit",\n          "value": "password",\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1010001,\n            "text": "Sign in",\n            "type": "info",\n            "context": {}\n          }\n        }\n      }\n    ]\n  },\n  "forced": false\n}\n')),Object(i.b)("p",null,"On success, that endpoint would typically return a HTTP 200 Status OK response\nwith the success ",Object(i.b)("inlineCode",{parentName:"p"},"application/json")," response payload in the body."))}m.isMDXComponent=!0},554:function(e,n,t){"use strict";var a=t(0),o=t.n(a),i=t(576),s=t.n(i),r=t(57),l=t.n(r),c=t(570),d=t.n(c);s.a.initialize({startOnLoad:!0,logLevel:"fatal",securityLevel:"strict",arrowMarkerAbsolute:!1,theme:"neutral",flowchart:{useMaxWidth:!0,htmlLabels:!0,rankSpacing:65,nodeSpacing:30,curve:"basis"},sequence:{useMaxWidth:!0},gantt:{useMaxWidth:!0}});n.a=function(e){var n,t=e.chart,i=Object(a.useState)(!1),r=i[0],c=i[1],u=Object(a.useState)(void 0),p=u[0],f=u[1],b=Object(a.useState)("mermaid-"+Math.random().toString(36).substr(2,-1))[0],m=function(){return c(!r)};return Object(a.useEffect)((function(){s.a.render(b,t,(function(e){f(e)}))}),[]),o.a.createElement(o.a.Fragment,null,o.a.createElement("div",{onClick:m,className:d()(l.a.graph,l.a.pointer),dangerouslySetInnerHTML:{__html:p}}),o.a.createElement("div",{onClick:m,className:d()(l.a.overlay,l.a.pointer,l.a.graph,(n={},n[l.a.visible]=r,n))},o.a.createElement("div",{onClick:function(e){return e.stopPropagation()},className:d()(l.a.backdrop,l.a.graph),dangerouslySetInnerHTML:{__html:p}})))}},558:function(e,n,t){"use strict";var a=t(0),o=t.n(a),i=t(563),s=t(555),r=t(58),l=t.n(r);var c=37,d=39;n.a=function(e){var n=e.lazy,t=e.block,r=e.defaultValue,u=e.values,p=e.groupId,f=e.className,b=Object(i.a)(),m=b.tabGroupChoices,h=b.setTabGroupChoices,g=Object(a.useState)(r),w=g[0],v=g[1],y=a.Children.toArray(e.children),j=[];if(null!=p){var O=m[p];null!=O&&O!==w&&u.some((function(e){return e.value===O}))&&v(O)}var k=function(e){var n=e.currentTarget,t=j.indexOf(n),a=u[t].value;v(a),null!=p&&(h(p,a),setTimeout((function(){var e,t,a,o,i,s,r,c;(e=n.getBoundingClientRect(),t=e.top,a=e.left,o=e.bottom,i=e.right,s=window,r=s.innerHeight,c=s.innerWidth,t>=0&&i<=c&&o<=r&&a>=0)||(n.scrollIntoView({block:"center",behavior:"smooth"}),n.classList.add(l.a.tabItemActive),setTimeout((function(){return n.classList.remove(l.a.tabItemActive)}),2e3))}),150))},T=function(e){var n,t;switch(e.keyCode){case d:var a=j.indexOf(e.target)+1;t=j[a]||j[0];break;case c:var o=j.indexOf(e.target)-1;t=j[o]||j[j.length-1]}null===(n=t)||void 0===n||n.focus()};return o.a.createElement("div",{className:"tabs-container"},o.a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:Object(s.a)("tabs",{"tabs--block":t},f)},u.map((function(e){var n=e.value,t=e.label;return o.a.createElement("li",{role:"tab",tabIndex:w===n?0:-1,"aria-selected":w===n,className:Object(s.a)("tabs__item",l.a.tabItem,{"tabs__item--active":w===n}),key:n,ref:function(e){return j.push(e)},onKeyDown:T,onFocus:k,onClick:k},t)}))),n?Object(a.cloneElement)(y.filter((function(e){return e.props.value===w}))[0],{className:"margin-vert--md"}):o.a.createElement("div",{className:"margin-vert--md"},y.map((function(e,n){return Object(a.cloneElement)(e,{key:n,hidden:e.props.value!==w})}))))}},559:function(e,n,t){"use strict";var a=t(0),o=t.n(a);n.a=function(e){var n=e.children,t=e.hidden,a=e.className;return o.a.createElement("div",{role:"tabpanel",hidden:t,className:a},n)}},562:function(e,n,t){"use strict";t.d(n,"a",(function(){return P}));var a=t(3),o=t(0),i=t.n(o),s=t(555),r={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","at-rule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},l={Prism:t(21).a,theme:r};function c(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function d(){return(d=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a])}return e}).apply(this,arguments)}var u=/\r\n|\r|\n/,p=function(e){0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},f=function(e,n){var t=e.length;return t>0&&e[t-1]===n?e:e.concat(n)},b=function(e,n){var t=e.plain,a=Object.create(null),o=e.styles.reduce((function(e,t){var a=t.languages,o=t.style;return a&&!a.includes(n)||t.types.forEach((function(n){var t=d({},e[n],o);e[n]=t})),e}),a);return o.root=t,o.plain=d({},t,{backgroundColor:null}),o};function m(e,n){var t={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&-1===n.indexOf(a)&&(t[a]=e[a]);return t}var h=function(e){function n(){for(var n=this,t=[],a=arguments.length;a--;)t[a]=arguments[a];e.apply(this,t),c(this,"getThemeDict",(function(e){if(void 0!==n.themeDict&&e.theme===n.prevTheme&&e.language===n.prevLanguage)return n.themeDict;n.prevTheme=e.theme,n.prevLanguage=e.language;var t=e.theme?b(e.theme,e.language):void 0;return n.themeDict=t})),c(this,"getLineProps",(function(e){var t=e.key,a=e.className,o=e.style,i=d({},m(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),s=n.getThemeDict(n.props);return void 0!==s&&(i.style=s.plain),void 0!==o&&(i.style=void 0!==i.style?d({},i.style,o):o),void 0!==t&&(i.key=t),a&&(i.className+=" "+a),i})),c(this,"getStyleForToken",(function(e){var t=e.types,a=e.empty,o=t.length,i=n.getThemeDict(n.props);if(void 0!==i){if(1===o&&"plain"===t[0])return a?{display:"inline-block"}:void 0;if(1===o&&!a)return i[t[0]];var s=a?{display:"inline-block"}:{},r=t.map((function(e){return i[e]}));return Object.assign.apply(Object,[s].concat(r))}})),c(this,"getTokenProps",(function(e){var t=e.key,a=e.className,o=e.style,i=e.token,s=d({},m(e,["key","className","style","token"]),{className:"token "+i.types.join(" "),children:i.content,style:n.getStyleForToken(i),key:void 0});return void 0!==o&&(s.style=void 0!==s.style?d({},s.style,o):o),void 0!==t&&(s.key=t),a&&(s.className+=" "+a),s})),c(this,"tokenize",(function(e,n,t,a){var o={code:n,grammar:t,language:a,tokens:[]};e.hooks.run("before-tokenize",o);var i=o.tokens=e.tokenize(o.code,o.grammar,o.language);return e.hooks.run("after-tokenize",o),i}))}return e&&(n.__proto__=e),n.prototype=Object.create(e&&e.prototype),n.prototype.constructor=n,n.prototype.render=function(){var e=this.props,n=e.Prism,t=e.language,a=e.code,o=e.children,i=this.getThemeDict(this.props),s=n.languages[t];return o({tokens:function(e){for(var n=[[]],t=[e],a=[0],o=[e.length],i=0,s=0,r=[],l=[r];s>-1;){for(;(i=a[s]++)<o[s];){var c=void 0,d=n[s],b=t[s][i];if("string"==typeof b?(d=s>0?d:["plain"],c=b):(d=f(d,b.type),b.alias&&(d=f(d,b.alias)),c=b.content),"string"==typeof c){var m=c.split(u),h=m.length;r.push({types:d,content:m[0]});for(var g=1;g<h;g++)p(r),l.push(r=[]),r.push({types:d,content:m[g]})}else s++,n.push(d),t.push(c),a.push(0),o.push(c.length)}s--,n.pop(),t.pop(),a.pop(),o.pop()}return p(r),l}(void 0!==s?this.tokenize(n,a,s,t):[a]),className:"prism-code language-"+t,style:void 0!==i?i.root:{},getLineProps:this.getLineProps,getTokenProps:this.getTokenProps})},n}(o.Component);var g=t(567),w=t.n(g),v={plain:{color:"#bfc7d5",backgroundColor:"#292d3e"},styles:[{types:["comment"],style:{color:"rgb(105, 112, 152)",fontStyle:"italic"}},{types:["string","inserted"],style:{color:"rgb(195, 232, 141)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation","selector"],style:{color:"rgb(199, 146, 234)"}},{types:["variable"],style:{color:"rgb(191, 199, 213)"}},{types:["class-name","attr-name"],style:{color:"rgb(255, 203, 107)"}},{types:["tag","deleted"],style:{color:"rgb(255, 85, 114)"}},{types:["operator"],style:{color:"rgb(137, 221, 255)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["keyword"],style:{fontStyle:"italic"}},{types:["doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}},{types:["url"],style:{color:"rgb(221, 221, 221)"}}]},y=t(565),j=t(557),O=function(){var e=Object(j.useThemeConfig)().prism,n=Object(y.a)().isDarkTheme,t=e.theme||v,a=e.darkTheme||t;return n?a:t},k=t(571),T=t(59),N=t.n(T),x=/{([\d,-]+)}/,S=function(e){void 0===e&&(e=["js","jsBlock","jsx","python","html"]);var n={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},python:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},t=["highlight-next-line","highlight-start","highlight-end"].join("|"),a=e.map((function(e){return"(?:"+n[e].start+"\\s*("+t+")\\s*"+n[e].end+")"})).join("|");return new RegExp("^\\s*(?:"+a+")\\s*$")};function P(e){var n=e.children,t=e.className,r=e.metastring,c=e.title,d=Object(j.useThemeConfig)().prism,u=Object(o.useState)(!1),p=u[0],f=u[1],b=Object(o.useState)(!1),m=b[0],g=b[1];Object(o.useEffect)((function(){g(!0)}),[]);var v=Object(j.parseCodeBlockTitle)(r)||c,y=Object(o.useRef)(null),T=[],P=O(),C=Array.isArray(n)?n.join(""):n;if(r&&x.test(r)){var I=r.match(x)[1];T=w()(I).filter((function(e){return e>0}))}var A=t&&t.replace(/language-/,"");!A&&d.defaultLanguage&&(A=d.defaultLanguage);var E=C.replace(/\n$/,"");if(0===T.length&&void 0!==A){for(var F,L="",R=function(e){switch(e){case"js":case"javascript":case"ts":case"typescript":return S(["js","jsBlock"]);case"jsx":case"tsx":return S(["js","jsBlock","jsx"]);case"html":return S(["js","jsBlock","html"]);case"python":case"py":return S(["python"]);default:return S()}}(A),B=C.replace(/\n$/,"").split("\n"),q=0;q<B.length;){var U=q+1,_=B[q].match(R);if(null!==_){switch(_.slice(1).reduce((function(e,n){return e||n}),void 0)){case"highlight-next-line":L+=U+",";break;case"highlight-start":F=U;break;case"highlight-end":L+=F+"-"+(U-1)+","}B.splice(q,1)}else q+=1}T=w()(L),E=B.join("\n")}var H=function(){!function(e,{target:n=document.body}={}){const t=document.createElement("textarea"),a=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const o=document.getSelection();let i=!1;o.rangeCount>0&&(i=o.getRangeAt(0)),n.append(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length;let s=!1;try{s=document.execCommand("copy")}catch{}t.remove(),i&&(o.removeAllRanges(),o.addRange(i)),a&&a.focus()}(E),f(!0),setTimeout((function(){return f(!1)}),2e3)};return i.a.createElement(h,Object(a.a)({},l,{key:String(m),theme:P,code:E,language:A}),(function(e){var n,t=e.className,o=e.style,r=e.tokens,l=e.getLineProps,c=e.getTokenProps;return i.a.createElement("div",{className:N.a.codeBlockContainer},v&&i.a.createElement("div",{style:o,className:N.a.codeBlockTitle},v),i.a.createElement("div",{className:Object(s.a)(N.a.codeBlockContent,A)},i.a.createElement("div",{tabIndex:0,className:Object(s.a)(t,N.a.codeBlock,"thin-scrollbar",(n={},n[N.a.codeBlockWithTitle]=v,n))},i.a.createElement("div",{className:N.a.codeBlockLines,style:o},r.map((function(e,n){1===e.length&&""===e[0].content&&(e[0].content="\n");var t=l({line:e,key:n});return T.includes(n+1)&&(t.className=t.className+" docusaurus-highlight-code-line"),i.a.createElement("div",Object(a.a)({key:n},t),e.map((function(e,n){return i.a.createElement("span",Object(a.a)({key:n},c({token:e,key:n})))})))})))),i.a.createElement("button",{ref:y,type:"button","aria-label":Object(k.b)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),className:Object(s.a)(N.a.copyButton),onClick:H},p?i.a.createElement(k.a,{id:"theme.CodeBlock.copied",description:"The copied button label on code blocks"},"Copied"):i.a.createElement(k.a,{id:"theme.CodeBlock.copy",description:"The copy button label on code blocks"},"Copy"))))}))}},563:function(e,n,t){"use strict";var a=t(0),o=t(564);n.a=function(){var e=Object(a.useContext)(o.a);if(null==e)throw new Error("`useUserPreferencesContext` is used outside of `Layout` Component.");return e}},564:function(e,n,t){"use strict";var a=t(0),o=Object(a.createContext)(void 0);n.a=o},565:function(e,n,t){"use strict";var a=t(0),o=t(566);n.a=function(){var e=Object(a.useContext)(o.a);if(null==e)throw new Error("`useThemeContext` is used outside of `Layout` Component. See https://docusaurus.io/docs/api/themes/configuration#usethemecontext.");return e}},566:function(e,n,t){"use strict";var a=t(0),o=t.n(a).a.createContext(void 0);n.a=o},567:function(e,n){function t(e){let n,t=[];for(let a of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(a))t.push(parseInt(a,10));else if(n=a.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,a,o,i]=n;if(a&&i){a=parseInt(a),i=parseInt(i);const e=a<i?1:-1;"-"!==o&&".."!==o&&"\u2025"!==o||(i+=e);for(let n=a;n!==i;n+=e)t.push(n)}}return t}n.default=t,e.exports=t},572:function(e,n,t){"use strict";var a=t(0),o=t.n(a);n.a=function(){return o.a.createElement("div",{className:"admonition admonition-warning alert alert--danger"},o.a.createElement("div",{className:"admonition-heading"},o.a.createElement("h5",null,o.a.createElement("span",{className:"admonition-icon"},o.a.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"},o.a.createElement("path",{"fill-rule":"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))),"warning")),o.a.createElement("div",{className:"admonition-content"},o.a.createElement("p",null,"Never use API flows to implement Browser applications!"),o.a.createElement("p",null,"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.")))}},573:function(e,n,t){"use strict";var a=t(0),o=t.n(a),i=t(554);n.a=function(e){return o.a.createElement(o.a.Fragment,null,o.a.createElement(i.a,{chart:(n=e,t=n.flows,a=void 0===t?["login","registration","settings","..."]:t,s=n.interactions,r=void 0===s?['"Log in"','"Sign Up"','"Update Email"',"..."]:s,l=n.success,c=void 0===l?"Perform flow-specific action (e.g. create user, set session cookie, ...)":l,d=a.length>1?"<"+a.join("|")+">":""+a.join("|"),"\nsequenceDiagram\n\n  participant B as Browser\n  participant K as Ory Kratos\n  participant A as Flow UI\n\n  B->>K: Follow link to /self-service/"+d+"/browser\n  K--\x3e>K: Create and store new "+a.join(", ")+" flow\n  K->>B: HTTP 302 Found <selfservice.flows."+d+".ui_url>?flow=<flow-id>\n\n  B->>A: Opens <selfservice.flows.<"+a.join("|")+">.ui_url>?flow=<flow-id>\n  A--\x3e>K: Fetches data to render forms using /selfservice/"+d+"/flows?id=<flow-id>\n  B--\x3e>A: Fills out forms, clicks e.g. "+r.join(", ")+"\n  B->>K: Submits form\n  K--\x3e>K: Validates and processes form payloads\n\n  alt Form payload is valid\n    K->>B: "+c+"\n  else Form payload invalid\n    K--\x3e>K: Update and store flow (e.g. add form validation errors)\n    K--\x3e>B: HTTP 302 Found <selfservice.flows."+d+".ui_url>?flow=<flow-id>\n    B->>A: Opens <selfservice.flows."+d+"?flow=<flow-id>\n    A--\x3e>K: Fetches data to render form fields and errors\n    B->>K: Repeat flow with input data, submit, validate, ...\n  end\n")}),o.a.createElement("p",null,"The ",o.a.createElement("em",null,"Flow UI")," (",o.a.createElement("strong",null,"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.'));var n,t,a,s,r,l,c,d}},574:function(e,n,t){"use strict";var a=t(0),o=t.n(a),i=t(554);n.a=function(e){return o.a.createElement(i.a,{chart:(n=e,t=n.flows,a=void 0===t?["login","registration","settings","..."]:t,s=n.interactions,r=void 0===s?['"Log in"','"Sign Up"','"Update Email"',"..."]:s,l=n.success,c=void 0===l?"Perform flow-specific action (e.g. create user, set session cookie, ...)":l,d=a.length>1?"<"+a.join("|")+">":""+a.join("|"),"\nsequenceDiagram\n  participant B as API Client\n  participant K as Ory Kratos\n\n  B->>K: REST GET /self-service/"+d+"/api\n  K--\x3e>K: Create and store new "+a.join(", ")+" flow\n  K->>B: HTTP 200 OK with flow as application/json payload\n  B--\x3e>B: Render form using e.g. Native iOS UI Elements\n  B--\x3e>B: User fills out forms, clicks e.g. "+r+"\n  B->>K: REST POST to e.g. /self-service/"+d+"?flow=...>\n  K--\x3e>K: Validates and processes payload\n  alt Form payload is valid\n    K->>B: "+c+"\n  else Form payload invalid\n    K--\x3e>K: Update and store flow (e.g. add form validation errors)\n    K->>B: Respond with e.g. HTTP 400 Bad Request and updated flow as payload\n    B--\x3e>B: Render form and validation errors using e.g. Native iOS UI Elements\n    B--\x3e>K: Repeat flow with input data, submit, validate, ...\n  end\n")});var n,t,a,s,r,l,c,d}},575:function(e,n,t){"use strict";var a=t(558),o=t(559),i=t(0),s=t.n(i),r=t(562);n.a=function(e){var n=e.items;return s.a.createElement(a.a,{defaultValue:Object.keys(n)[0],values:Object.keys(n).map((function(e){return{label:n[e].label,value:e}}))},Object.keys(n).map((function(e){return s.a.createElement(o.a,{key:e,value:e},n[e].code?s.a.createElement(r.a,{className:"language-"+n[e].language,children:n[e].code}):s.a.createElement("img",{src:n[e].image,alt:n[e].alt}))})))}},577:function(e,n,t){var a={"./locale":561,"./locale.js":561};function o(e){var n=i(e);return t(n)}function i(e){if(!t.o(a,e)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return a[e]}o.keys=function(){return Object.keys(a)},o.resolve=i,e.exports=o,o.id=577},700:function(e,n,t){"use strict";t.d(n,"e",(function(){return a})),t.d(n,"a",(function(){return o})),t.d(n,"d",(function(){return i})),t.d(n,"c",(function(){return s})),t.d(n,"b",(function(){return r}));var a={curl:{label:"Raw HTTP",language:"shell",code:t(701).default},html:{label:"HTML",language:"html",code:t(702).default},jsx:{label:"ReactJS",language:"js",code:t(703).default},node:{label:"ExpressJS",language:"html",code:t(704).default},angular:{label:"Angular",language:"js",code:t(705).default}},o={curl:{label:"Raw HTTP",language:"shell",code:t(706).default},js:{label:"JavaScript SDK",language:"js",code:t(707).default},go:{label:"Go SDK",language:"go",code:t(708).default}},i={curl:{label:"Raw HTTP",language:"shell",code:t(709).default},js:{label:"TypeScript",language:"ts",code:t(710).default},go:{label:"Go",language:"go",code:t(711).default}},s={browser:{label:"Browser UI",image:t(712).default,alt:"User Login HTML Form with validation errors"},missing:{label:"Missing Email",language:"shell",code:t(713).default},wrong:{label:"Wrong Credentials",language:"shell",code:t(714).default}},r={missing:{label:"Missing ID Token",language:"shell",code:t(715).default}}},701:function(e,n,t){"use strict";t.r(n),n.default='curl -s -v -X GET \\\n  -H "Accept: text/html"  \\\n  http://127.0.0.1:4433/self-service/login/browser\n\n> GET /self-service/login/browser HTTP/1.1\n> Host: 127.0.0.1:4433\n> User-Agent: curl/7.64.1\n> Accept: text/html\n>\n< HTTP/1.1 302 Found\n< Cache-Control: 0\n< Content-Type: text/html; charset=utf-8\n< Location: http://127.0.0.1:4455/auth/login?flow=df607aa1-d555-4b2a-b3e4-0f5a1d2fe6f3\n< Set-Cookie: csrf_token=y4Ocu6V83BapwJwbPw/pnlRHHw40DZbjq5iuDrxl0Ds=; Path=/; Domain=127.0.0.1; Max-Age=31536000; HttpOnly\n<\n<a href="http://127.0.0.1:4455/auth/login?flow=df607aa1-d555-4b2a-b3e4-0f5a1d2fe6f3">Found</a>.\n'},702:function(e,n,t){"use strict";t.r(n),n.default='<a href="http://127.0.0.1:4433/self-service/login/browser">Log in</a>\n\n\x3c!-- or --\x3e\n\n<script>\n  const initLogin = () => {\n    window.location.href = \'http://127.0.0.1:4433/self-service/login/browser\'\n  }\n<\/script>\n\n<a onClick="initLogin">Sign in</a>\n'},703:function(e,n,t){"use strict";t.r(n),n.default="import React from 'react'\n\nconst MyComponent = () => (\n  <a href=\"http://127.0.0.1:4433/self-service/login/browser\">Sign in</a>\n)\n"},704:function(e,n,t){"use strict";t.r(n),n.default="express.get('/login', function (req, res) {\n  res.redirect(302, 'http://127.0.0.1:4433/self-service/login/browser')\n})\n"},705:function(e,n,t){"use strict";t.r(n),n.default='<a href="http://127.0.0.1:4433/self-service/login/browser">Log in</a>\n'},706:function(e,n,t){"use strict";t.r(n),n.default='$ curl -H "Accept: application/json" -s \\\n    \'http://127.0.0.1:4434/self-service/login/flows?id=42e26bc5-8014-400c-b463-dc5c3738c242\' | jq\n\n{\n  "id": "42e26bc5-8014-400c-b463-dc5c3738c242",\n  "type": "browser",\n  "expires_at": "2021-04-28T10:04:44.506336771Z",\n  "issued_at": "2021-04-28T09:54:44.506336771Z",\n  "request_url": "http://127.0.0.1:4433/self-service/login/browser",\n  "ui": {\n    "action": "http://127.0.0.1:4433/self-service/login?flow=42e26bc5-8014-400c-b463-dc5c3738c242",\n    "method": "POST",\n    "nodes": [\n      {\n        "type": "input",\n        "group": "default",\n        "attributes": {\n          "name": "csrf_token",\n          "type": "hidden",\n          "value": "8RygCHIdyMXVc3jxIAf/6uAuv/jBJLo5mt6nXdcB/JOzncLRu5510BNZNOjvA6Soii504s1Yq/sgvfOXxzck6g==",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {}\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password_identifier",\n          "type": "text",\n          "value": "",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070004,\n            "text": "ID",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password",\n          "type": "password",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070001,\n            "text": "Password",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "method",\n          "type": "submit",\n          "value": "password",\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1010001,\n            "text": "Sign in",\n            "type": "info",\n            "context": {}\n          }\n        }\n      }\n    ]\n  },\n  "forced": false\n}\n'},707:function(e,n,t){"use strict";t.r(n),n.default="import { Configuration, PublicApi } from '@ory/kratos-client';\nconst kratos = new PublicApi(new Configuration({ basePath: 'http://127.0.0.1:4433/' }));\n\nconst flowId = '' // usually something like: req.query.flow\n\nreturn kratos.getSelfServiceLoginFlow(flowId)\n  .then(({ status, data: flow, ...response }) => {\n    console.log(flow) // see the Raw HTTP tab for the payload\n  })\n"},708:function(e,n,t){"use strict";t.r(n),n.default='package samples\n\nimport (\n  "fmt"\n\n  "github.com/ory/kratos-client-go"\n)\n\nfunc NewKratosClient(endpoint string) *kratos.APIClient {\n  conf := kratos.NewConfiguration()\n  conf.Servers = kratos.ServerConfigurations{{URL: endpoint}}\n  return kratos.NewAPIClient(conf)\n}\n\nfunc main() {\n  ctx := context.Background()\n  flowID := "" // Usually something like: res.Request.URL.Query().Get("flow")\n\n  c := NewKratosClient("http://127.0.0.1:4433/")\n  flow, _, err := c.PublicApi.GetSelfServiceLoginFlow().Id(flowID).Execute()\n  if err != nil {\n    // ...\n  }\n\n  fmt.Printf("%+v", flow)\n}\n'},709:function(e,n,t){"use strict";t.r(n),n.default='$ curl -s -X GET \\\n    -H "Accept: application/json"  \\\n    http://127.0.0.1:4433/self-service/login/api | jq\n\n{\n  "id": "cc24b30b-c0a8-46f5-a929-304371e92e46",\n  "type": "api",\n  "expires_at": "2021-04-28T10:02:34.102190388Z",\n  "issued_at": "2021-04-28T09:52:34.102190388Z",\n  "request_url": "http://127.0.0.1:4433/self-service/login/api",\n  "ui": {\n    "action": "http://127.0.0.1:4433/self-service/login?flow=cc24b30b-c0a8-46f5-a929-304371e92e46",\n    "method": "POST",\n    "nodes": [\n      {\n        "type": "input",\n        "group": "default",\n        "attributes": {\n          "name": "csrf_token",\n          "type": "hidden",\n          "value": "",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {}\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password_identifier",\n          "type": "text",\n          "value": "",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070004,\n            "text": "ID",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "password",\n          "type": "password",\n          "required": true,\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1070001,\n            "text": "Password",\n            "type": "info"\n          }\n        }\n      },\n      {\n        "type": "input",\n        "group": "password",\n        "attributes": {\n          "name": "method",\n          "type": "submit",\n          "value": "password",\n          "disabled": false\n        },\n        "messages": null,\n        "meta": {\n          "label": {\n            "id": 1010001,\n            "text": "Sign in",\n            "type": "info",\n            "context": {}\n          }\n        }\n      }\n    ]\n  },\n  "forced": false\n}\n'},710:function(e,n,t){"use strict";t.r(n),n.default="import { Configuration, PublicApi } from '@ory/kratos-client';\nconst kratos = new PublicApi(new Configuration({ basePath: 'http://127.0.0.1:4433/' }));\n\nkratos.initializeSelfServiceLoginViaAPIFlow()\n  .then(({ data: flow }) => {\n    console.log(flow) // see the Raw HTTP tab for the payload\n  })\n"},711:function(e,n,t){"use strict";t.r(n),n.default='package api\n\nimport (\n  "fmt"\n\n  "github.com/ory/kratos-client-go"\n)\n\nfunc NewKratosClient(endpoint string) *kratos.APIClient {\n  conf := kratos.NewConfiguration()\n  conf.Servers = kratos.ServerConfigurations{{URL: endpoint}}\n  return kratos.NewAPIClient(conf)\n}\n\nfunc main() {\n  c := NewKratosClient("http://127.0.0.1:4433/")\n  flow, _, err := c.PublicApi.InitializeSelfServiceLoginViaAPIFlow(context.Background()).Execute()\n  if err != nil {\n    // ...\n  }\n\n  fmt.Printf("%+v", flow)\n}\n'},712:function(e,n,t){"use strict";t.r(n),n.default=t.p+"assets/images/browser-error-b6509d4065a4bfb5ab01e37a0389a65f.png"},713:function(e,n,t){"use strict";t.r(n),n.default='$ curl -H "Accept: application/json" -s \\\n    \'http://127.0.0.1:4433/self-service/login/flows?id=a2d6e166-5153-42a6-8943-ef99eba8ab2e\' \\\n    | jq -r \'.ui.nodes[] | select(.attributes.name=="password_identifier")\'\n\n{\n  "type": "input",\n  "group": "password",\n  "attributes": {\n    "name": "password_identifier",\n    "type": "text",\n    "value": "",\n    "required": true,\n    "disabled": false\n  },\n  "messages": [\n    {\n      "id": 4000001,\n      "text": "length must be >= 1, but got 0",\n      "type": "error"\n    }\n  ],\n  "meta": {\n    "label": {\n      "id": 1070004,\n      "text": "ID",\n      "type": "info"\n    }\n  }\n}\n'},714:function(e,n,t){"use strict";t.r(n),n.default='$ curl -H "Accept: application/json" -s \\\n    \'http://127.0.0.1:4433/self-service/login/flows?id=a2d6e166-5153-42a6-8943-ef99eba8ab2e\' \\\n    | jq -r \'.ui.messages\'\n\n[\n  {\n    "id": 4000006,\n    "text": "The provided credentials are invalid, check for spelling mistakes in your password or username, email address, or phone number.",\n    "type": "error",\n    "context": {}\n  }\n]\n'},715:function(e,n,t){"use strict";t.r(n),n.default='$ curl -s -H "Accept: application/json" \\\n    \'http://127.0.0.1:4433/self-service/login/flows?id=76cec270-1719-4c9e-b09a-4af8281d511e\' \\\n    | jq -r \'.ui.messages\'\n\n[\n  {\n    "id": 4000001,\n    "text": "Authentication failed because no id_token was returned. Please accept the \\"openid\\" permission and try again.",\n    "type": "error"\n  }\n]\n'}}]);