(window.webpackJsonp=window.webpackJsonp||[]).push([[282],{346:function(e,t,i){"use strict";i.r(t),i.d(t,"frontMatter",(function(){return s})),i.d(t,"metadata",(function(){return l})),i.d(t,"toc",(function(){return c})),i.d(t,"default",(function(){return d}));var n=i(3),r=i(8),a=(i(0),i(452)),o=i(454),s={id:"verify-email-account-activation",title:"Email and Phone Verification and Account Activation"},l={unversionedId:"self-service/flows/verify-email-account-activation",id:"version-v0.1/self-service/flows/verify-email-account-activation",isDocsHomePage:!1,title:"Email and Phone Verification and Account Activation",description:"ORY Kratos allows users to verify their out-of-band (email, telephone number,",source:"@site/versioned_docs/version-v0.1/self-service/flows/verify-email-account-activation.mdx",slug:"/self-service/flows/verify-email-account-activation",permalink:"/kratos/docs/v0.1/self-service/flows/verify-email-account-activation",editUrl:"https://github.com/ory/kratos/edit/master/docs/versioned_docs/version-v0.1/self-service/flows/verify-email-account-activation.mdx",version:"v0.1",lastUpdatedBy:"hackerman",lastUpdatedAt:1586177162,formattedLastUpdatedAt:"4/6/2020",sidebar:"version-v0.1/docs",previous:{title:"User-Facing Errors",permalink:"/kratos/docs/v0.1/self-service/flows/user-facing-errors"},next:{title:"Overview",permalink:"/kratos/docs/v0.1/self-service/strategies/index"}},c=[{value:"Account Activation",id:"account-activation",children:[]},{value:"Setting Email Verification",id:"setting-email-verification",children:[{value:"Verify Email on User Registration",id:"verify-email-on-user-registration",children:[]}]},{value:"Self-Service Request or Resend Verification Link for Browser Applications",id:"self-service-request-or-resend-verification-link-for-browser-applications",children:[{value:"Server-Side Browser Applications",id:"server-side-browser-applications",children:[]},{value:"Client-Side Browser Applications",id:"client-side-browser-applications",children:[]}]},{value:"Email Verification for API Clients",id:"email-verification-for-api-clients",children:[]}],u={toc:c};function d(e){var t=e.components,i=Object(r.a)(e,["components"]);return Object(a.b)("wrapper",Object(n.a)({},u,i,{components:t,mdxType:"MDXLayout"}),Object(a.b)("p",null,"ORY Kratos allows users to verify their out-of-band (email, telephone number,\n...) communication channels. Verification can be initiated"),Object(a.b)("ul",null,Object(a.b)("li",{parentName:"ul"},"after registration or by performing a verification flow;"),Object(a.b)("li",{parentName:"ul"},"manually by the user.")),Object(a.b)("p",null,"Currently, ORY Kratos only supports verification of email addresses. Before\nsending out a verification E-Mail, ORY Kratos will check if the email address is\nalready known. Depending on the result, one of the two flows will be executed:"),Object(a.b)("ul",null,Object(a.b)("li",{parentName:"ul"},"Unknown email address: An email is sent to the address informing the recipient\nthat someone tried to verify this email address but that it is not known by\nthe system:  ",Object(a.b)("img",{alt:"Verification email for unknown address",src:Object(o.a)("img/docs/email-verify-unknown.png")}),";"),Object(a.b)("li",{parentName:"ul"},"Known email address: An email which includes a verification link is sent to\nthe address:",Object(a.b)("img",{alt:"Verification email for known address",src:Object(o.a)("img/docs/email-verify-known.png")}),";")),Object(a.b)("p",null,"This prevents Account Enumeration Attacks at is is not possible for a threat\nagent to determine if an account exists or not based on the verification flow."),Object(a.b)("p",null,"The emails are using templates that can be customised as explained in\n",Object(a.b)("a",{parentName:"p",href:"/kratos/docs/v0.1/concepts/email-sms#templates"},"Customizing E-Mail Templates"),". The\ntemplate IDs are:"),Object(a.b)("ul",null,Object(a.b)("li",{parentName:"ul"},"Unknown email address: ",Object(a.b)("inlineCode",{parentName:"li"},"verify_invalid")),Object(a.b)("li",{parentName:"ul"},"Known email address: ",Object(a.b)("inlineCode",{parentName:"li"},"verify_valids"))),Object(a.b)("h2",{id:"account-activation"},"Account Activation"),Object(a.b)("p",null,'Using this feature implements the so-called "account activation" with the\ndifference that ORY Kratos does not provide a feature that prevents sign in into\naccounts without verified addresses. The reason being that verification is\nproving that the user controls the given address, but it is not an\nauthentication mechanism.'),Object(a.b)("p",null,"You may however chose to limit what an identity without verified addresses is\nable to do in your application logic or API Gateways."),Object(a.b)("h2",{id:"setting-email-verification"},"Setting Email Verification"),Object(a.b)("p",null,"You must define at least one Identity Traits field as a verification field. You\ncan do so by defining the following section in your Identity Traits JSON Schema:"),Object(a.b)("pre",null,Object(a.b)("code",{parentName:"pre",className:"language-json5"},"{\n  // ...\n  properties: {\n    // This could also be an array or any other field name\n    email: {\n      type: 'string',\n      format: 'email',\n      'ory.sh/kratos': {\n        verification: {\n          // Currently, only email is supported\n          via: 'email',\n        },\n      },\n    },\n  },\n  // ...\n}\n")),Object(a.b)("p",null,"You can also combine this with the password strategy login identifier."),Object(a.b)("pre",null,Object(a.b)("code",{parentName:"pre",className:"language-json5"},"{\n  // ...\n  properties: {\n    // This could also be an array or any other field name\n    email: {\n      type: 'string',\n      format: 'email',\n      'ory.sh/kratos': {\n        credentials: {\n          password: {\n            identifier: true,\n          },\n        },\n        verification: {\n          // Currently, only email is supported\n          via: 'email',\n        },\n      },\n    },\n  },\n  // ...\n}\n")),Object(a.b)("p",null,"That way, the field ",Object(a.b)("inlineCode",{parentName:"p"},"email")," (or any field you define with these properties) will\nserve as both the login identifier as well as a verifiable email address."),Object(a.b)("h3",{id:"verify-email-on-user-registration"},"Verify Email on User Registration"),Object(a.b)("p",null,"To send an email after user registration, add the following sections to your ORY\nKratos config file:"),Object(a.b)("pre",null,Object(a.b)("code",{parentName:"pre",className:"language-yaml"},"# required\nurls:\n  # Similar to login_ui or profile_ui, this points to the user interface where the verificaiton\n  # user interface is implemented.\n  #\n  # For more information on this endpoint please head over to the next section\n  verify_ui: https://my-kratos-ui/verify\n\nselfservice:\n  registration:\n    after:\n      password:\n        # ....\n        - job: verify # This sends the verification email after successful registration\n        # ....\n")),Object(a.b)("h2",{id:"self-service-request-or-resend-verification-link-for-browser-applications"},"Self-Service Request or Resend Verification Link for Browser Applications"),Object(a.b)("p",null,"A user might want to resend a verification link because the link expired or did\nnot arrive in the inbox."),Object(a.b)("p",null,"The flow implementing this feature uses the already established\n",Object(a.b)("a",{parentName:"p",href:"/kratos/docs/v0.1/self-service/flows/index#network-flows-for-browsers"},"Network Flows for Browsers"),"."),Object(a.b)("h3",{id:"server-side-browser-applications"},"Server-Side Browser Applications"),Object(a.b)("p",null,"You can find an exemplary implementation for this flow on GitHub:"),Object(a.b)("ul",null,Object(a.b)("li",{parentName:"ul"},Object(a.b)("a",{parentName:"li",href:"https://github.com/ory/kratos-selfservice-ui-node/blob/master/src/routes/verify.ts"},"Verification HTTP Route")),Object(a.b)("li",{parentName:"ul"},Object(a.b)("a",{parentName:"li",href:"https://github.com/ory/kratos-selfservice-ui-node/blob/master/views/verify.hbs"},"Verification UI"))),Object(a.b)("p",null,"The ",Object(a.b)("a",{parentName:"p",href:"/kratos/docs/v0.1/self-service/flows/index#network-flows-for-browsers"},"Network Flows for Browsers")," works as\nfollows for Email Verification:"),Object(a.b)("ol",null,Object(a.b)("li",{parentName:"ol"},"An initial HTTP Request is made to\n",Object(a.b)("inlineCode",{parentName:"li"},"/self-service/browser/flows/verification/:via"),". Currently, only ",Object(a.b)("inlineCode",{parentName:"li"},"email")," is\nsupported as ",Object(a.b)("inlineCode",{parentName:"li"},":via"),"."),Object(a.b)("li",{parentName:"ol"},"ORY Kratos redirects the browser to the URL set in ",Object(a.b)("inlineCode",{parentName:"li"},"urls.verify_ui")," and\nappends the ",Object(a.b)("inlineCode",{parentName:"li"},"request")," URL Query Parameter (e.g.\n",Object(a.b)("inlineCode",{parentName:"li"},"https://example.org/verify?request=abcde"),")."),Object(a.b)("li",{parentName:"ol"},"The Endpoint at ",Object(a.b)("inlineCode",{parentName:"li"},"/profile")," makes a HTTP GET Request to\n",Object(a.b)("inlineCode",{parentName:"li"},"https://ory-kratos-admin.example-org.vpc/self-service/browser/flows/requests/verification?request=abcde"),"\nand fetches Verification Request JSON Payload that represent the individual\nfields that can be updated."),Object(a.b)("li",{parentName:"ol"},"The user fills out the form and sends a HTTP POST request to\n",Object(a.b)("inlineCode",{parentName:"li"},"https://example.org/.ory/kratos/public/self-service/browser/flows/verification/:via/complete?request=abcde"),".\nDepending on whether the address is known or not, a ",Object(a.b)("inlineCode",{parentName:"li"},"verify_valid")," or\n",Object(a.b)("inlineCode",{parentName:"li"},"verify_invalid")," message will be sent to the given address.")),Object(a.b)("p",null,"An exemplary payload for a verification request looks as follows:"),Object(a.b)("pre",null,Object(a.b)("code",{parentName:"pre",className:"language-json"},'{\n  "id": "9c3e945c-096a-42ec-8617-caecda9e9263",\n  "expires_at": "2020-02-18T16:11:25.3112038Z",\n  "issued_at": "2020-02-18T15:11:25.3112824Z",\n  "request_url": "http://127.0.0.1:4455/self-service/browser/flows/verification/email",\n  "form": {\n    "action": "http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/verification/email/complete?request=9c3e945c-096a-42ec-8617-caecda9e9263",\n    "method": "POST",\n    "fields": [\n      {\n        "name": "csrf_token",\n        "type": "hidden",\n        "required": true,\n        "value": "fMusJj65BxNtrog/DYryN4sZmuLA85WkbAh4yP9pT1lAQTIAPTVGJTmmLL66Y0HEbIpKEU5gTr5qJoRXHsBoSw=="\n      },\n      {\n        "name": "to_verify",\n        "type": "email",\n        "required": true\n      }\n    ]\n  },\n  "via": "email",\n  "success": false\n}\n')),Object(a.b)("h3",{id:"client-side-browser-applications"},"Client-Side Browser Applications"),Object(a.b)("p",null,"Because Client-Side Browser Applications do not have access to ORY Kratos' Admin\nAPI, they must use the ORY Kratos Public API instead. The flow for a Client-Side\nBrowser Application is almost the exact same as the one for Server-Side\nApplications, with the small difference that\n",Object(a.b)("inlineCode",{parentName:"p"},"https://example.org/.ory/kratos/public/self-service/browser/flows/requests/verification?request=abcde"),"\nwould be called via AJAX instead of making a request to\n",Object(a.b)("inlineCode",{parentName:"p"},"https://ory-kratos-admin.example-org.vpc/self-service/browser/flows/requests/verification?request=abcde"),"."),Object(a.b)("blockquote",null,Object(a.b)("p",{parentName:"blockquote"},"To prevent brute force, guessing, session injection, and other attacks, it is\nrequired that cookies are working for this endpoint. The cookie set in the\ninitial HTTP request made to\n",Object(a.b)("inlineCode",{parentName:"p"},"https://example.org/.ory/kratos/public/self-service/browser/flows/verification/:via"),"\nMUST be set and available when calling this endpoint!"),Object(a.b)("p",{parentName:"blockquote"},"When making AJAX requests from JavaScript, make sure to set\n",Object(a.b)("inlineCode",{parentName:"p"},"{ withCredentials: true }")," (name and layout may vary between libraries).")),Object(a.b)("h2",{id:"email-verification-for-api-clients"},"Email Verification for API Clients"),Object(a.b)("p",null,"Will be addressed in a future release."))}d.isMDXComponent=!0},452:function(e,t,i){"use strict";i.d(t,"a",(function(){return d})),i.d(t,"b",(function(){return p}));var n=i(0),r=i.n(n);function a(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function o(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,n)}return i}function s(e){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?o(Object(i),!0).forEach((function(t){a(e,t,i[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(i)):o(Object(i)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(i,t))}))}return e}function l(e,t){if(null==e)return{};var i,n,r=function(e,t){if(null==e)return{};var i,n,r={},a=Object.keys(e);for(n=0;n<a.length;n++)i=a[n],t.indexOf(i)>=0||(r[i]=e[i]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)i=a[n],t.indexOf(i)>=0||Object.prototype.propertyIsEnumerable.call(e,i)&&(r[i]=e[i])}return r}var c=r.a.createContext({}),u=function(e){var t=r.a.useContext(c),i=t;return e&&(i="function"==typeof e?e(t):s(s({},t),e)),i},d=function(e){var t=u(e.components);return r.a.createElement(c.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},b=r.a.forwardRef((function(e,t){var i=e.components,n=e.mdxType,a=e.originalType,o=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=u(i),b=n,p=d["".concat(o,".").concat(b)]||d[b]||f[b]||a;return i?r.a.createElement(p,s(s({ref:t},c),{},{components:i})):r.a.createElement(p,s({ref:t},c))}));function p(e,t){var i=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=i.length,o=new Array(a);o[0]=b;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:n,o[1]=s;for(var c=2;c<a;c++)o[c]=i[c];return r.a.createElement.apply(null,o)}return r.a.createElement.apply(null,i)}b.displayName="MDXCreateElement"},454:function(e,t,i){"use strict";i.d(t,"b",(function(){return a})),i.d(t,"a",(function(){return o}));var n=i(16),r=i(455);function a(){var e=Object(n.default)().siteConfig,t=(e=void 0===e?{}:e).baseUrl,i=void 0===t?"/":t,a=e.url;return{withBaseUrl:function(e,t){return function(e,t,i,n){var a=void 0===n?{}:n,o=a.forcePrependBaseUrl,s=void 0!==o&&o,l=a.absolute,c=void 0!==l&&l;if(!i)return i;if(i.startsWith("#"))return i;if(Object(r.b)(i))return i;if(s)return t+i;var u=i.startsWith(t)?i:t+i.replace(/^\//,"");return c?e+u:u}(a,i,e,t)}}}function o(e,t){return void 0===t&&(t={}),(0,a().withBaseUrl)(e,t)}},455:function(e,t,i){"use strict";function n(e){return!0===/^(\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!n(e)}i.d(t,"b",(function(){return n})),i.d(t,"a",(function(){return r}))}}]);