{"id":304447,"date":"2020-05-28T21:00:41","date_gmt":"2020-05-28T21:00:41","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=304447"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=304447","title":{"rendered":"\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u2014 CUSTOM SETUP \/ AWS Amplify + React Native"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/504344\/\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/406\/65e\/0e9\/40665e0e973bdd2a10416e9113667856.png\" alt=\"cognito\"><\/p>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0442\u0435\u043c, \u0441\u0440\u0435\u0434\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432 \u043c\u043e\u0435\u0433\u043e \u043a\u0430\u043d\u0430\u043b\u0430 <a href=\"https:\/\/www.youtube.com\/channel\/UCOxewePwIQATdHTD3yZ2UZw\" rel=\"nofollow\">\u0414\u0438\u043c\u043a\u0430 \u0420\u0435\u0430\u043a\u0442\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439<\/a> \u2014 \u044d\u0442\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 React Native. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0441\u0432\u0435\u0442\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043b\u043e\u043d\u0433\u0440\u0438\u0434 \u0438 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u043a\u043e\u0434\u0438\u0442\u044c, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\/\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"autentifikaciya\">\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0441\u0443\u0431\u044a\u0435\u043a\u0442\u0430 \u0438 \u0442\u043e\u0433\u043e, \u0437\u0430 \u043a\u043e\u0433\u043e \u043e\u043d \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0435\u0431\u044f \u0432\u044b\u0434\u0430\u0442\u044c, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u043a\u043e\u0439 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 (\u043e\u0442\u043f\u0435\u0447\u0430\u0442\u043a\u0438 \u043f\u0430\u043b\u044c\u0446\u0435\u0432, \u0446\u0432\u0435\u0442 \u0440\u0430\u0434\u0443\u0436\u043a\u0438, \u0433\u043e\u043b\u043e\u0441 \u0438 \u0442 \u0434.), \u0432 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u2014 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043e\u0447\u0442\u044b \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<p>  <\/p>\n<h2 id=\"avtorizaciya\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u0439 \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0440\u0430\u043d\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439<\/p>\n<p>  <\/p>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/0bb\/0db\/ae4\/0bb0dbae460bb468dca68cf1955f2ee7.png\" alt=\"cognito\"><\/p>\n<p>  <\/p>\n<p>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u043e\u0442\u044a\u0435\u043c\u043b\u0435\u043c\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0417\u043d\u0430\u043d\u0438\u0435 \u0442\u043e\u0433\u043e, \u043a\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043a\u0430\u043a\u0438\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0438 \u0432\u043e\u0448\u043b\u0438 \u043b\u0438 \u043e\u043d\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0432\u043e\u0448\u0435\u0434\u0448\u0435\u0433\u043e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>  <\/p>\n<p>\u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0438\u0445 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u0435\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u0437\u0430\u0434\u0430\u0447, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439. \u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439, \u043a\u0430\u043a OAUTH (\u043e\u0442\u043a\u0440\u044b\u0442\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f), MFA (\u043c\u043d\u043e\u0433\u043e\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f) \u0438 TOTP (\u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0430\u0440\u043e\u043b\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438).<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0440\u0430\u0441\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441 \u043d\u0443\u043b\u044f. \u041e\u0434\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043d\u0435\u0434\u0435\u043b\u0438 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u043c\u0435\u0441\u044f\u0446\u044b, \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a Auth0, Okta \u0438 Amazon Cognito, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442 \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0441.<\/p>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0432\u044b \u0443\u0437\u043d\u0430\u0435\u0442\u0435, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 React Native \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Amazon Cognito \u0441 AWS Amplify.<\/p>\n<p>  <\/p>\n<h2 id=\"amazon-cognito\">Amazon Cognito<\/h2>\n<p>  <\/p>\n<p>\u044d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043e\u0442 AWS. Cognito \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0443\u044e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. Cognito \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043e \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0441 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430\u043c\u0438 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439, \u0442\u0430\u043a\u0438\u043c\u0438 \u043a\u0430\u043a Facebook, Google \u0438 Amazon.<\/p>\n<p>  <\/p>\n<p>Cognito \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439: \u043f\u0443\u043b\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043f\u0443\u043b\u043e\u0432 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<h2 id=\"user-pools\">User Pools<\/h2>\n<p>  <\/p>\n<p>\u043f\u0443\u043b\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432\u0441\u0435\u0445 \u0432\u0430\u0448\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043e \u0441\u043e\u0442\u0435\u043d \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u042d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441. \u041a\u0430\u043a \u0431\u0435\u0441\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043f\u0443\u043b\u044b \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f, \u043d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u044f\u0441\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443. \u041f\u0443\u043b\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u2014 \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u0432\u0445\u043e\u0434\u044f\u0442 \u0432 \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c, \u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>  <\/p>\n<h2 id=\"identity-pools\">Identity pools<\/h2>\n<p>  <\/p>\n<p>\u043f\u0443\u043b\u044b \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0432\u0430\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0432\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u0432 \u0432\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c AWS. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043b\u044f\u043c\u0431\u0434\u0430-\u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043c\u043e\u0433 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e API. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0443\u043b\u0430 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0439. \u0412 \u043f\u0443\u043b\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432\u0445\u043e\u0434\u0438\u0442 \u0442\u043e, \u0447\u0442\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u044d\u0442\u0438\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 Cognito \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 Facebook \u0438\u043b\u0438 Google.<\/p>\n<p>  <\/p>\n<p>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u043a\u043e\u0433\u0434\u0430 \u043f\u0443\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 Amazon Cognito \u0438 \u043f\u0443\u043b \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435.<\/p>\n<p>  <\/p>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0441\u0445\u0435\u043c\u0443 \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f Amazon Cognito. \u0417\u0434\u0435\u0441\u044c \u0446\u0435\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0443 AWS.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/92a\/a49\/ac8\/92aa49ac8b44cab68794e7ae562306c1.png\" alt=\"cognito\"><\/p>\n<p>  <\/p>\n<ol>\n<li>\n<p>\u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0443\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u043f\u0443\u043b\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/li>\n<li>\n<p>\u0417\u0430\u0442\u0435\u043c \u0432\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u043f\u0443\u043b\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 AWS \u0447\u0435\u0440\u0435\u0437 \u043f\u0443\u043b \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0439.<\/p>\n<p>  <\/li>\n<li>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0442\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 AWS \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c AWS, \u0442\u0430\u043a\u0438\u043c \u043a\u0430\u043a Amazon S3 \u0438\u043b\u0438 DynamoDB.<\/p>\n<p>  <\/li>\n<\/ol>\n<p>  <\/p>\n<p>Cognito User Pools \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0441\u043b\u0443\u0436\u0431\u044b \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u043c\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u0430\u043c\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0442\u0430\u043a\u0438\u0435 \u0432\u0435\u0449\u0438, \u043a\u0430\u043a:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u0412\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u0412\u044b\u0445\u043e\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u0421\u043c\u0435\u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 MFA<\/li>\n<li>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f Amazon Cognito \u0441 AWS Amplify<\/li>\n<\/ul>\n<p>  <\/p>\n<p>AWS Amplify \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Amazon Cognito \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438. \u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u044b Amazon Cognito \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 AWS Amplify. \u0421\u043e\u0437\u0434\u0430\u0432 \u0441\u043b\u0443\u0436\u0431\u0443 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 CLI, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, signUp, signIn \u0438 signOut) \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f JavaScript \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Amplify JavaScript.<\/p>\n<p>  <\/p>\n<p>Amplify \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0446\u0435\u043b\u044b\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u0433\u043e \u0437\u0430 \u043f\u0430\u0440\u0443 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0441\u0440\u0435\u0434, \u043a\u0430\u043a React, React Native, Vue \u0438 Angular.<\/p>\n<p>  <\/p>\n<h2 id=\"vy-sprosite-i-skolko-zhe-eto-vse-stoit\">\u0412\u044b \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u0435 \u0438 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0436\u0435 \u044d\u0442\u043e \u0432\u0441\u0435 \u0441\u0442\u043e\u0438\u0442?<\/h2>\n<p>  <\/p>\n<h4 id=\"platite-tolko-za-to-chem-polzuetes-nikakih-minimalnyh-platezhey\">\u041f\u043b\u0430\u0442\u0438\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430 \u0442\u043e, \u0447\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435\u0441\u044c. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/h4>\n<p>  <\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Amazon Cognito Identity \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0443\u043b\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0432\u044b \u043f\u043b\u0430\u0442\u0438\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043c\u0435\u0441\u044f\u0446 (MAU). MAU \u2014 \u044d\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u044f\u0446\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438: \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e, \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f. \u041f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0432 \u044d\u0442\u043e\u043c \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u043d\u043e\u043c \u043c\u0435\u0441\u044f\u0446\u0435 \u043d\u0435 \u043e\u043f\u043b\u0430\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e70\/069\/e27\/e70069e27d465ab06839eed77ac06c60.png\" alt=\"cognito\"><\/p>\n<p>  <\/p>\n<p>CODING TIME \u200d\u200d<\/p>\n<p>  <\/p>\n<p>\u0427\u0430\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 AWS Amplify: <a href=\"https:\/\/teleg.run\/awsamplify\" rel=\"nofollow\">Telegram<\/a><\/p>\n<p>  <\/p>\n<h1 id=\"chast-i\">\u0427\u0430\u0441\u0442\u044c I<\/h1>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442o\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c UI \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043e\u0442 AWS Amplify, \u0430 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0435\u0433\u043e \u0441 \u043d\u0443\u043b\u044f.<\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 <a href=\"https:\/\/github.com\/react-native-village\/messaga\/tree\/Part1\" rel=\"nofollow\">GitHub<\/a>.<\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/youtu.be\/9uOGS7Pw1fo\" rel=\"nofollow\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/a85\/330\/557\/a85330557d5a036dd7641c8dcaa8d8a8.gif\" alt=\"AWS Amplify\"><\/a><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/308\/34a\/22a\/30834a22ac5c4b8f15a03eaf1a4bf1de.png\" alt=\"Cognito\"><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/942\/0e0\/a51\/9420e0a51c7b345d8fa5d5e29d760ea0.png\" alt=\"Step01\"><\/p>\n<p>  <\/p>\n<h2 id=\"sozdaem-novyy-proekt-\">\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \ufe0f<\/h2>\n<p>  <\/p>\n<pre><code class=\"bash\">react-native init auth<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 <\/p>\n<p>  <\/p>\n<p>iOS<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd auth &amp;&amp; react-native run-ios<\/code><\/pre>\n<p>  <\/p>\n<p>Android<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd auth &amp;&amp; react-native run-android<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/631\/e00\/e86\/631e00e866d9fc3d76c43b97781ae3b4.png\" alt=\"Step02\"><\/p>\n<p>  <\/p>\n<h2 id=\"podklyuchaem-ikonki\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0438\u043a\u043e\u043d\u043a\u0438<\/h2>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0438\u043a\u043e\u043d\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c AWS Amplify, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0438\u0445 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/github.com\/oblador\/react-native-vector-icons#installation\" rel=\"nofollow\">\u044d\u0442\u043e\u0439<\/a> \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438.<br \/>  \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 App.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import Icon from 'react-native-vector-icons\/FontAwesome5'  const App = () =&gt; {   return (     &lt;&gt;       &lt;Icon name=&quot;comments&quot; size={30} color=&quot;#900&quot; \/&gt;     &lt;\/&gt;   ) }<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/9eb\/aa1\/4a1\/9ebaa14a1b87631ab663427182eb87cd.png\" alt=\"Step03\"><\/p>\n<p>  <\/p>\n<h2 id=\"registriruem-svoy-aws-account\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u0432\u043e\u0439 AWS account<\/h2>\n<p>  <\/p>\n<p>\u0420\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/aws-amplify.github.io\/docs\/\" rel=\"nofollow\">\u044d\u0442\u043e\u0439<\/a> \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438 \u043f\u043e \u0432\u0438\u0434\u0435\u043e\u0443\u0447\u0435\u0431\u043d\u0438\u043a\u0443 \u0447\u0435\u043a\u0430\u0435\u043c \u0432\u0441\u0435 5 \u0448\u0430\u0433\u043e\u0432.<\/p>\n<p>  <\/p>\n<h4 id=\"vnimanie\">\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435!!!<\/h4>\n<p>  <\/p>\n<p>\u041f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0430\u044f \u043a\u0430\u0440\u0442\u0430, \u0433\u0434\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u0435\u0435 1$ <\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043c \u0436\u0435 \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438 \u0441\u0442\u0430\u0432\u0438\u043c Amplify Command Line Interface (CLI)<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/af4\/70f\/d98\/af470fd981fa96a00da9992a9a7e6924.png\" alt=\"Step04\"><\/p>\n<p>  <\/p>\n<h2 id=\"inicializaciya-aws-amplify-v-proekt-react-native\">\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f AWS Amplify \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 React Native<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 React Native \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 AWS Amplify \u043f\u0440\u043e\u0435\u043a\u0442<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">amplify init<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u0432\u0435\u0447\u0430\u0435\u043c \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u044b:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/991\/4b9\/b2a\/9914b9b2ad986b066c0c7996337a3f67.png\" alt=\"amplify init\"><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f <\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d23\/840\/9a4\/d238409a47778024c1f12cd93691c3ab.png\" alt=\"Step05\"><\/p>\n<p>  <\/p>\n<h2 id=\"podklyuchaem-plagin-autentifikacii\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043b\u0430\u0433\u0438\u043d \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/h2>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043e\u0431\u043b\u0430\u043a\u0435, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438 \u0432\u043e\u0439\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u043e\u0439<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">amplify add auth<\/code><\/pre>\n<p>  <\/p>\n<p>\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u042d\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 auth \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0432 \u0432\u0430\u0448 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 ampify\/backend\/auth<\/p>\n<p>  <\/p>\n<h4 id=\"vybiraem-profil-kotoryy-my-hotim-ispolzovat-default-enter-i-kak-polzovateli-budut-vhodit-v-sistemu-emailza-sms-spisyvayut-dengi\">\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. default. Enter \u0438 \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. Email(\u0417\u0430 SMS \u0441\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442 \u0434\u0435\u043d\u044c\u0433\u0438).<\/h4>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/ff3\/add\/83f\/ff3add83ff4ab1194c6ff8f9401b06bb.png\" alt=\"amplify init\"><\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043e\u0431\u043b\u0430\u043a\u043e <\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">amplify push<\/code><\/pre>\n<p>  <\/p>\n<p>All resources are updated in the cloud<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/34b\/ec2\/c86\/34bec2c860805fdf4daca2f36ec985fe.png\" alt=\"Step06\"><\/p>\n<p>  <\/p>\n<h2 id=\"podklyuchaem-aws-amplify-v-proekt-react-native-\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c AWS Amplify \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 React Native \ufe0f<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0432 <a href=\"https:\/\/aws-amplify.github.io\/docs\/js\/react\" rel=\"nofollow\">\u044d\u0442\u043e\u0439<\/a> \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438, \u0430 \u043a\u043e\u0440\u043e\u0442\u043a\u043e \u0438 \u043f\u043e \u043f\u0440\u044f\u043c\u043e\u0439 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">yarn add aws-amplify @aws-amplify\/core aws-amplify-react-native amazon-cognito-identity-js @react-native-community\/netinfo<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u043f\u0430\u043f\u043a\u0443 ios \u0438 \u0441\u0442\u0430\u0432\u0438\u043c \u043f\u043e\u0434\u044b<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd ios &amp;&amp; pod install &amp;&amp; cd ..<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/ae8\/966\/d5e\/ae8966d5e8590e6dbb72da5c187d859d.png\" alt=\"Step07\"><\/p>\n<p>  <\/p>\n<h2 id=\"redaktiruem-strukturu-proekta\">\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \/src \u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c \u0442\u0443\u0434\u0430 \u0444\u0430\u0439\u043b App.js, \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u044f \u0435\u0433\u043e \u0432 index.js<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0430\u0432\u0438\u043c \u0438\u043c\u043f\u043e\u0440\u0442 \u0432 \/auth\/index.js \u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import { AppRegistry, YellowBox } from 'react-native' import App from '.\/src' import { name as appName } from '.\/app.json'  YellowBox.ignoreWarnings([   'Warning: AsyncStorage',     'Warning: componentWillReceiveProps',   'RCTRootView cancelTouches',   'not authenticated',   'Sending `onAnimatedValueUpdate`' ])  \/\/window.LOG_LEVEL = 'DEBUG'  AppRegistry.registerComponent(appName, () =&gt; App)<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/9c9\/355\/eab\/9c9355eabb59b5a4c4f36b4336c5febd.png\" alt=\"Step08\"><\/p>\n<p>  <\/p>\n<h2 id=\"minimalnaya-konfiguraciya-proekta-i-modul-authenticator\">\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043c\u043e\u0434\u0443\u043b\u044c Authenticator<\/h2>\n<p>  <\/p>\n<p>Amplify.configure \u2014 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<p>  <\/p>\n<p>Authenticator \u2014 \u041c\u043e\u0434\u0443\u043b\u044c <a href=\"https:\/\/aws-amplify.github.io\/docs\/js\/authentication#using-components-in-react--react-native\" rel=\"nofollow\">AWS Amplify Authentication<\/a> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 API-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u044f\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React from 'react' import {StatusBar} from 'react-native' import Amplify from '@aws-amplify\/core' import {Authenticator} from 'aws-amplify-react-native' import awsconfig from '..\/aws-exports'  Amplify.configure({   ...awsconfig,   Analytics: {     disabled: true,   }, })  const App = () =&gt; {   return (     &lt;&gt;       &lt;StatusBar barStyle=&quot;dark-content&quot; \/&gt;       &lt;Authenticator usernameAttributes=&quot;email&quot; \/&gt;     &lt;\/&gt;   ) }  export default App<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u0433\u0434\u0435 \u043d\u0430\u0441 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442 UI \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/cb4\/2b1\/d66\/cb42b1d66b77c5721e1d204bedc1a03d.png\" alt=\"Cognito\"><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/560\/ec1\/171\/560ec1171f5bc79a6dde22f0f344cb58.png\" alt=\"Step09\"><\/p>\n<p>  <\/p>\n<h2 id=\"pravim-inputy-v-appjs\">\u041f\u0440\u0430\u0432\u0438\u043c \u0438\u043d\u043f\u0443\u0442\u044b \u0432 App.js<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c signUpConfig<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">const signUpConfig = {   hideAllDefaults: true,   signUpFields: [     {       label: 'Email',       key: 'email',       required: true,       displayOrder: 1,       type: 'string',     },     {       label: 'Password',       key: 'password',       required: true,       displayOrder: 2,       type: 'password',     },   ], }  &lt;Authenticator    usernameAttributes=&quot;email&quot;    signUpConfig={signUpConfig} \/&gt;<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/df8\/22a\/e04\/df822ae04334378b0b39d6bd70bf2513.png\" alt=\"Step10\"><\/p>\n<p>  <\/p>\n<h2 id=\"menyaem-temu-ui\">\u041c\u0435\u043d\u044f\u0435\u043c \u0442\u0435\u043c\u0443 UI<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0442\u043e\u0447\u043a\u0443 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u043d\u0430\u0448\u0438\u0445 \u0431\u0443\u0434\u0443\u0449\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \/src\/components\/index.js \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">export * from '.\/AmplifyTheme'<\/code><\/pre>\n<p>  <\/p>\n<p>\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0430\u043c \u0444\u0430\u0439\u043b \/src\/components\/AmplifyTheme\/index.js \u0442\u0435\u043c\u044b \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import { StyleSheet } from 'react-native'  export const deepSquidInk = '#152939' export const linkUnderlayColor = '#FFF' export const errorIconColor = '#30d0fe'  const AmplifyTheme = StyleSheet.create({   container: {     flex: 1,     flexDirection: 'column',     alignItems: 'center',     justifyContent: 'space-around',     paddingTop: 20,     width: '100%',     backgroundColor: '#FFF'   },   section: {     flex: 1,     width: '100%',     padding: 30   },   sectionHeader: {     width: '100%',     marginBottom: 32   },   sectionHeaderText: {     color: deepSquidInk,     fontSize: 20,     fontWeight: '500'   },   sectionFooter: {     width: '100%',     padding: 10,     flexDirection: 'row',     justifyContent: 'space-between',     marginTop: 15,     marginBottom: 20   },   sectionFooterLink: {     fontSize: 14,     color: '#30d0fe',     alignItems: 'baseline',     textAlign: 'center'   },   navBar: {     marginTop: 35,     padding: 15,     flexDirection: 'row',     justifyContent: 'flex-end',     alignItems: 'center'   },   navButton: {     marginLeft: 12,     borderRadius: 4   },   cell: {     flex: 1,     width: '50%'   },   errorRow: {     flexDirection: 'row',     justifyContent: 'center'   },   errorRowText: {     marginLeft: 10   },   photo: {     width: '100%'   },   album: {     width: '100%'   },   button: {     backgroundColor: '#30d0fe',     alignItems: 'center',     padding: 16   },   buttonDisabled: {     backgroundColor: '#85E4FF',     alignItems: 'center',     padding: 16   },   buttonText: {     color: '#fff',     fontSize: 14,     fontWeight: '600'   },   formField: {     marginBottom: 22   },   input: {     padding: 16,     borderWidth: 1,     borderRadius: 3,     borderColor: '#C4C4C4'   },   inputLabel: {     marginBottom: 8   },   phoneContainer: {     display: 'flex',     flexDirection: 'row',     alignItems: 'center'   },   phoneInput: {     flex: 2,     padding: 16,     borderWidth: 1,     borderRadius: 3,     borderColor: '#C4C4C4'   },   picker: {     flex: 1,     height: 44   },   pickerItem: {     height: 44   } })  export { AmplifyTheme }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0442\u0435\u043c\u0443 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Authenticator src\/index.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import {AmplifyTheme} from '.\/components'  &lt;Authenticator   usernameAttributes=&quot;email&quot;   signUpConfig={signUpConfig}   theme={AmplifyTheme} \/&gt;<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/517\/b5d\/e5c\/517b5de5c8e725435ea10c86dfbaad27.png\" alt=\"AmplifyTheme\"><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/81f\/03c\/c4c\/81f03cc4cf1c819f35f562367e6975d1.png\" alt=\"Step11\"><\/p>\n<p>  <\/p>\n<h2 id=\"podklyuchaem-lokalizaciyu\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a <\/p>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \/src\/components\/index.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">export * from '.\/Localei18n'<\/code><\/pre>\n<p>  <\/p>\n<p>C\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0430\u043c \u0444\u0430\u0439\u043b \/src\/components\/Localei18n\/index.js \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import { NativeModules, Platform } from 'react-native' import { I18n } from '@aws-amplify\/core'  let langRegionLocale = 'en_US'  \/\/ If we have an Android phone if (Platform.OS === 'android') {   langRegionLocale = NativeModules.I18nManager.localeIdentifier || '' } else if (Platform.OS === 'ios') {   langRegionLocale = NativeModules.SettingsManager.settings.AppleLocale || '' }  const authScreenLabels = {   en: {     'Sign Up': 'Create new account',     'Sign Up Account': 'Create a new account'   },   ru: {     'Sign Up': '\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442',     'Forgot Password': '\u0417\u0430\u0431\u044b\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c?',     'Sign In Account': '\u0412\u043e\u0439\u0434\u0438\u0442\u0435 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443',     'Enter your email': '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 email',     'Enter your password': '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c',     Password: '\u041f\u0430\u0440\u043e\u043b\u044c',     'Sign In': '\u0412\u0445\u043e\u0434',     'Please Sign In \/ Sign Up': '\u0412\u043e\u0439\u0442\u0438 \/ \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442',     'Sign in to your account': '\u0412\u043e\u0439\u0434\u0438\u0442\u0435 \u0432 \u0441\u0432\u043e\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442',     'Create a new account': 'C\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0441\u0432\u043e\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442',     'Confirm a Code': '\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043a\u043e\u0434',     'Confirm Sign Up': '\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e',     'Resend code': '\u0415\u0449\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u0434',     'Back to Sign In': '\u0412\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u0432\u0445\u043e\u0434\u0443',     Confirm: '\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c',     'Confirmation Code': '\u041a\u043e\u0434 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f',     'Sign Out': '\u0412\u044b\u0445\u043e\u0434'   } }  \/\/ &quot;en_US&quot; -&gt; &quot;en&quot;, &quot;es_CL&quot; -&gt; &quot;es&quot;, etc const languageLocale = langRegionLocale.substring(0, 2) I18n.setLanguage(languageLocale) I18n.putVocabularies(authScreenLabels)  const Localei18n = () =&gt; null  export { Localei18n }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Localei18n \u0432 src\/index.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import {    AmplifyTheme,    Localei18n } from '.\/components'  &lt;Localei18n \/&gt; &lt;Authenticator   usernameAttributes=&quot;email&quot;   signUpConfig={signUpConfig}   theme={AmplifyTheme} \/&gt;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442, \u0433\u0434\u0435 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0435\u0449\u0435 \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b\u0430\u0441\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u0435\u043d\u044f\u0435\u043c \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u044f\u0437\u044b\u043a \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u0438\u0439<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/7a9\/2dc\/012\/7a92dc0124f6ed4c2ffa5f9b66373277.png\" alt=\"Localei18n\"><\/p>\n<p>  <\/p>\n<h2 id=\"done\">Done<\/h2>\n<p>  <\/p>\n<h1 id=\"chast-ii\">\u0427\u0430\u0441\u0442\u044c II<\/h1>\n<p>  <\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 UI \u043e\u0442 Amplify \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 UX \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u0430<\/p>\n<p>  <\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445 \u0432 <a href=\"https:\/\/aws-amplify.github.io\/docs\/js\/react#note-on-jwt-storage\" rel=\"nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> Amplify \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e:<\/p>\n<p>  <\/p>\n<blockquote><p>Data is stored unencrypted when using standard storage adapters (localStorage in the browser and AsyncStorage on React Native). Amplify gives you the option to use your own storage object to persist data. With this, you could write a thin wrapper around libraries like:<br \/>  react-native-keychain<br \/>  react-native-secure-storage<br \/>  Expo\u2019s secure store<\/p><\/blockquote>\n<p>\u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u043d\u0435 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435, \u0430 \u044d\u0442\u043e \u0440\u0438\u0441\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c\u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0435\u0448\u0438\u043c \u044d\u0442\u0438 \u0434\u0432\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 <a href=\"https:\/\/github.com\/react-native-village\/aws-amplify-react-hooks\/tree\/master\/examples\/reactNativeCRUDv2\" rel=\"nofollow\">GitHub<\/a>.<\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/youtu.be\/CM_M5cNLmK4\" rel=\"nofollow\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/a85\/330\/557\/a85330557d5a036dd7641c8dcaa8d8a8.gif\" alt=\"AWS Amplify\"><\/a><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/942\/0e0\/a51\/9420e0a51c7b345d8fa5d5e29d760ea0.png\" alt=\"Step01\"><\/p>\n<p>  <\/p>\n<h2 id=\"ui-kit\">UI Kit<\/h2>\n<p>  <\/p>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 UI Kit, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u0432\u043e\u0438\u043c \u0438\u043b\u0438 \u043b\u044e\u0431\u044b\u043c \u0434\u0440\u0443\u0433\u0438\u043c.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/react-native-village.github.io\/docs\/unicorn00\" rel=\"nofollow\">\u044d\u0442\u043e\u0439<\/a> \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/631\/e00\/e86\/631e00e866d9fc3d76c43b97781ae3b4.png\" alt=\"Step02\"><\/p>\n<p>  <\/p>\n<h2 id=\"navigaciya-react-navigation\">\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f react-navigation<\/h2>\n<p>  <\/p>\n<p>\u0421\u0442\u0430\u0432\u0438\u043c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e react-navigation 5, \u0442\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e <a href=\"https:\/\/reactnavigation.org\/docs\/getting-started\/\" rel=\"nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a> (\u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438):<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community\/masked-view @react-navigation\/stack<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0434\u044b \u043f\u043e\u0434 iOS<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd ios &amp;&amp; pod install &amp;&amp; cd ..<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 iOS \u0438 Android, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043d\u0435 \u0438\u0441\u043a\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0430\u0434\u0430\u0435\u0442.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/9eb\/aa1\/4a1\/9ebaa14a1b87631ab663427182eb87cd.png\" alt=\"Step03\"><\/p>\n<p>  <\/p>\n<h2 id=\"react-native-keychain\">react-native-keychain<\/h2>\n<p>  <\/p>\n<p>\u0421\u0442\u0430\u0432\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 react-native-keychain \u2014 \u044d\u0442\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043a\u043b\u044e\u0447\u0435\u0439 react-native-keychain \u0434\u043b\u044f React Native.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">yarn add react-native-keychain<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0434\u044b \u043f\u043e\u0434 iOS<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd ios &amp;&amp; pod install &amp;&amp; cd ..<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442 <a href=\"https:\/\/aws-amplify.github.io\/docs\/js\/authentication#managing-security-tokens\" rel=\"nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>:<\/p>\n<p>  <\/p>\n<blockquote><p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441 AWS Amplify \u0432\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b Amazon Cognito \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0422\u043e\u043a\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438. \u0422\u043e\u043a\u0435\u043d\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a IdToken \u0438\u043b\u0438 AccessToken, \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 localStorage \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u0432 AsyncStorage \u0434\u043b\u044f React Native. \u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u0438 \u0442\u043e\u043a\u0435\u043d\u044b \u0432 \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 Amplify \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432.<\/p><\/blockquote>\n<p>\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 src\/index.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React from 'react' import Amplify from '@aws-amplify\/core' import * as Keychain from 'react-native-keychain' import { ThemeProvider, DarkTheme, LightTheme } from 'react-native-unicorn-uikit' import { useColorScheme } from 'react-native-appearance' import AppNavigator from '.\/AppNavigator' import awsconfig from '..\/aws-exports'  const MEMORY_KEY_PREFIX = '@MyStorage:' let dataMemory = {}  class MyStorage {   static syncPromise = null    static setItem(key, value) {     Keychain.setGenericPassword(MEMORY_KEY_PREFIX + key, value)     dataMemory[key] = value     return dataMemory[key]   }    static getItem(key) {     return Object.prototype.hasOwnProperty.call(dataMemory, key) ? dataMemory[key] : undefined   }    static removeItem(key) {     Keychain.resetGenericPassword()     return delete dataMemory[key]   }    static clear() {     dataMemory = {}     return dataMemory   } }  Amplify.configure({   ...awsconfig,   Analytics: {     disabled: false   },   storage: MyStorage })  const App = () =&gt; {   const scheme = useColorScheme()   return (     &lt;&gt;       &lt;ThemeProvider theme={scheme === 'dark' ? DarkTheme : LightTheme}&gt;         &lt;AppNavigator \/&gt;       &lt;\/ThemeProvider&gt;     &lt;\/&gt;   ) }  export default App<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/af4\/70f\/d98\/af470fd981fa96a00da9992a9a7e6924.png\" alt=\"Step04\"><\/p>\n<p>  <\/p>\n<h2 id=\"konstanty\">\u041a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b<\/h2>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0438\u0442\u044c \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438 \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445 src\/constants.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import { Dimensions } from 'react-native'  export const BG = '#0B0B0B' export const PINK = '#F20AF5' export const PURPLE = '#7A1374' export const BLUE = '#00FFFF' export const GREEN = '#2E7767' export const RED = '#FC2847' export const LABEL_COLOR = BLUE export const INPUT_COLOR = PINK export const ERROR_COLOR = RED export const HELP_COLOR = '#999999' export const BORDER_COLOR = BLUE export const DISABLED_COLOR = '#777777' export const DISABLED_BACKGROUND_COLOR = '#eeeeee'  export const win = Dimensions.get('window') export const W = win.width export const H = win.height  export const Device = {   \/\/ eslint-disable-next-line   select(variants) {     if (W &gt;= 300 &amp;&amp; W &lt;= 314) return variants.mobile300 || {}     if (W &gt;= 315 &amp;&amp; W &lt;= 341) return variants.iphone5 || {}     if (W &gt;= 342 &amp;&amp; W &lt;= 359) return variants.mobile342 || {}     if (W &gt;= 360 &amp;&amp; W &lt;= 374) return variants.mi5 || {}     if (W &gt;= 375 &amp;&amp; W &lt;= 399) return variants.iphone678 || {}     if (W &gt;= 400 &amp;&amp; W &lt;= 409) return variants.mobile400 || {}     if (W &gt;= 410 &amp;&amp; W &lt;= 414) return variants.googlePixel || {}     if (W &gt;= 415 &amp;&amp; W &lt;= 434) return variants.mobile415 || {}     if (W &gt;= 435 &amp;&amp; W &lt;= 480) return variants.redmiNote5 || {}   } }  export const goBack = navigation =&gt; () =&gt; navigation.goBack()  export const onScreen = (screen, navigation, obj) =&gt; () =&gt; {   navigation.navigate(screen, obj) }  export const goHome = navigation =&gt; () =&gt; navigation.popToTop()()<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d23\/840\/9a4\/d238409a47778024c1f12cd93691c3ab.png\" alt=\"Step05\"><\/p>\n<p>  <\/p>\n<h2 id=\"appnavigator\">AppNavigator<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b \u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 src\/AppNavigator.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import * as React from 'react' import { createStackNavigator } from '@react-navigation\/stack' import { Hello } from '.\/screens\/Authenticator'  const Stack = createStackNavigator()  const AppNavigator = () =&gt; {      return (     &lt;Stack.Navigator       screenOptions={{         headerShown: false       }}       initialRouteName=&quot;HELLO&quot;     &gt;       &lt;Stack.Screen name=&quot;HELLO&quot; component={Hello} \/&gt;     &lt;\/Stack.Navigator&gt;   ) }  export default AppNavigator<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/34b\/ec2\/c86\/34bec2c860805fdf4daca2f36ec985fe.png\" alt=\"Step06\"><\/p>\n<p>  <\/p>\n<h2 id=\"hello-screen\">Hello screen<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043d\u0430\u0448\u044b\u0445 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 src\/screens\/Authenticator\/index.js<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/942\/35a\/76b\/94235a76b21bd666faad2a2be9dbace2.png\" alt=\"Hello screen\"><\/p>\n<p>  <\/p>\n<p>\u0413\u0434\u0435 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u044d\u043a\u0440\u0430\u043d \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">export * from '.\/Hello'<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0435\u0433\u043e src\/screens\/Authenticator\/Hello\/index.js<\/p>\n<p>  <\/p>\n<p>\u0412 \u0445\u0443\u043a\u0435 useEffect \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0433\u0434\u0435 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 true \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d User, \u0430 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 false \u043e\u0441\u0442\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u043a\u0440\u0430\u043d\u0435.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React, { useEffect, useState } from 'react' import { Auth } from 'aws-amplify' import * as Keychain from 'react-native-keychain' import { AppContainer, Button, Space, H6 } from 'react-native-unicorn-uikit' import { onScreen } from '..\/..\/..\/constants'  const Hello = ({ navigation }) =&gt; {   const [loading, setLoading] = useState(false)   useEffect(() =&gt; {     setLoading(true)     const key = async () =&gt; {       try {         const credentials = await Keychain.getInternetCredentials('auth')          if (credentials) {           const { username, password } = credentials           const user = await Auth.signIn(username, password)           setLoading(false)           user &amp;&amp; onScreen('USER', navigation)()         } else {           setLoading(false)         }       } catch (err) {         console.log('error', err) \/\/ eslint-disable-line         setLoading(false)       }     }     key()   }, []) \/\/ eslint-disable-line   return (     &lt;AppContainer loading={loading}&gt;       &lt;Space height={200} \/&gt;       &lt;Button title=&quot;Sign In&quot; onPress={onScreen('SIGN_IN', navigation)} \/&gt;       &lt;Space height={10} \/&gt;       &lt;H6 title=&quot;or&quot; textStyle={{ alignSelf: 'center' }} \/&gt;       &lt;Space height={15} \/&gt;       &lt;Button title=&quot;Sign Up&quot; onPress={onScreen('SIGN_UP', navigation)} \/&gt;     &lt;\/AppContainer&gt;   ) }  export { Hello }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u043c \u044d\u043a\u0440\u0430\u043d \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f.<\/p>\n<h2 id=\"signup-screen\">SignUp screen<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0440\u0430\u043d \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 SIGN_UP src\/screens\/Authenticator\/SignUp\/index.js, \u0433\u0434\u0435 \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <a href=\"https:\/\/aws-amplify.github.io\/docs\/js\/authentication#sign-up\" rel=\"nofollow\">Auth.signUp<\/a><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/ae8\/966\/d5e\/ae8966d5e8590e6dbb72da5c187d859d.png\" alt=\"SignUp\"><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React, { useState } from 'react' import { Auth } from 'aws-amplify' import * as Keychain from 'react-native-keychain' import { Formik } from 'formik' import * as Yup from 'yup' import { AppContainer, Space, Button, Input, TextError } from 'react-native-unicorn-uikit' import { onScreen, goBack } from '..\/..\/..\/constants'  const SignUp = ({ navigation }) =&gt; {   const [loading, setLoading] = useState(false)   const [error, setError] = useState('')    const _onPress = async (values) =&gt; {     const { email, password, passwordConfirmation } = values     if (password !== passwordConfirmation) {       setError('Passwords do not match!')     } else {       setLoading(true)       setError('')       try {         const user = await Auth.signUp(email, password)         await Keychain.setInternetCredentials('auth', email, password)         user &amp;&amp; onScreen('CONFIRM_SIGN_UP', navigation, { email, password })()         setLoading(false)       } catch (err) {         setLoading(false)         if (err.code === 'UserNotConfirmedException') {           setError('Account not verified yet')         } else if (err.code === 'PasswordResetRequiredException') {           setError('Existing user found. Please reset your password')         } else if (err.code === 'NotAuthorizedException') {           setError('Forgot Password?')         } else if (err.code === 'UserNotFoundException') {           setError('User does not exist!')         } else {           setError(err.code)         }       }     }   }    return (     &lt;&gt;       &lt;AppContainer onPress={goBack(navigation)} title=&quot;Sign Up&quot; loading={loading}&gt;         &lt;Space height={80} \/&gt;         &lt;Formik           initialValues={{ email: '', password: '', passwordConfirmation: '' }}           onSubmit={(values) =&gt; _onPress(values)}           validationSchema={Yup.object().shape({             email: Yup.string().email().required(),             password: Yup.string().min(6).required(),             passwordConfirmation: Yup.string().min(6).required()           })}         &gt;           {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) =&gt; (             &lt;&gt;               &lt;Input                 name=&quot;email&quot;                 value={values.email}                 onChangeText={handleChange('email')}                 onBlur={() =&gt; setFieldTouched('email')}                 placeholder=&quot;E-mail&quot;                 touched={touched}                 errors={errors}                 autoCapitalize=&quot;none&quot;               \/&gt;               &lt;Input                 name=&quot;password&quot;                 value={values.password}                 onChangeText={handleChange('password')}                 onBlur={() =&gt; setFieldTouched('password')}                 placeholder=&quot;Password&quot;                 touched={touched}                 errors={errors}                 secureTextEntry               \/&gt;               &lt;Input                 name=&quot;passwordConfirmation&quot;                 value={values.passwordConfirmation}                 onChangeText={handleChange('passwordConfirmation')}                 onBlur={() =&gt; setFieldTouched('passwordConfirmation')}                 placeholder=&quot;Password confirm&quot;                 touched={touched}                 errors={errors}                 secureTextEntry               \/&gt;               &lt;Space height={30} \/&gt;               {error !== '' &amp;&amp; &lt;TextError title={error} textStyle={{ alignSelf: 'center' }} \/&gt;}               &lt;Button title=&quot;Sign Up&quot; disabled={!isValid} onPress={handleSubmit} formik \/&gt;             &lt;\/&gt;           )}         &lt;\/Formik&gt;       &lt;\/AppContainer&gt;     &lt;\/&gt;   ) }  export { SignUp }<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/9c9\/355\/eab\/9c9355eabb59b5a4c4f36b4336c5febd.png\" alt=\"Step08\"><\/p>\n<p>  <\/p>\n<h2 id=\"confirmsignup-screen\">ConfirmSignUp screen<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043c\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0438 \u0432\u0432\u043e\u0434\u0430 \u043a\u043e\u0434\u0430, \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0435\u0433\u043e \u043d\u0430\u043c \u043d\u0430 \u043f\u043e\u0447\u0442\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0440\u0430\u043d CONFIRM_SIGN_UP src\/screens\/Authenticator\/ConfirmSignUp\/index.js<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/a51\/873\/7a5\/a518737a5a9f8845da5a9e320f9589c2.png\" alt=\"ConfirmSignUp\"><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React, { useState } from 'react' import { Auth } from 'aws-amplify' import { Formik } from 'formik' import * as Yup from 'yup' import { AppContainer, Button, Space, ButtonLink, TextError, Input } from 'react-native-unicorn-uikit' import { onScreen, goBack } from '..\/..\/..\/constants'  const ConfirmSignUp = ({ route, navigation }) =&gt; {   const [loading, setLoading] = useState(false)   const [error, setError] = useState('')    const _onPress = async (values) =&gt; {     setLoading(true)     setError('')     try {       const { code } = values       const { email, password } = route.params       await Auth.confirmSignUp(email, code, { forceAliasCreation: true })       const user = await Auth.signIn(email, password)       user &amp;&amp; onScreen('USER', navigation)()       setLoading(false)     } catch (err) {       setLoading(false)       setError(err.message)       if (err.code === 'UserNotConfirmedException') {         setError('Account not verified yet')       } else if (err.code === 'PasswordResetRequiredException') {         setError('Existing user found. Please reset your password')       } else if (err.code === 'NotAuthorizedException') {         setError('Forgot Password?')       } else if (err.code === 'UserNotFoundException') {         setError('User does not exist!')       }     }   }    const _onResend = async () =&gt; {     try {       const { email } = route.params       await Auth.resendSignUp(email)     } catch (err) {       setError(err.message)     }   }    return (     &lt;&gt;       &lt;AppContainer title=&quot;Confirmation&quot; onPress={goBack(navigation)} loading={loading}&gt;         &lt;Formik           initialValues={{ code: '' }}           onSubmit={(values) =&gt; _onPress(values)}           validationSchema={Yup.object().shape({             code: Yup.string().min(6).required()           })}         &gt;           {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) =&gt; (             &lt;&gt;               &lt;Space height={180} \/&gt;               &lt;Input                 name=&quot;code&quot;                 value={values.code}                 onChangeText={handleChange('code')}                 onBlur={() =&gt; setFieldTouched('code')}                 placeholder=&quot;Insert code&quot;                 touched={touched}                 errors={errors}               \/&gt;               &lt;ButtonLink title=&quot;Resend code?&quot; onPress={_onResend} textStyle={{ alignSelf: 'center' }} \/&gt;               {error !== 'Forgot Password?' &amp;&amp; &lt;TextError title={error} \/&gt;}               &lt;Button title=&quot;Confirm&quot; disabled={!isValid} onPress={handleSubmit} formik \/&gt;               &lt;Space height={50} \/&gt;             &lt;\/&gt;           )}         &lt;\/Formik&gt;       &lt;\/AppContainer&gt;     &lt;\/&gt;   ) }  export { ConfirmSignUp }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"resendsignup\">ResendSignUp<\/h2>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043e\u0434 \u043d\u0435 \u043f\u0440\u0438\u0448\u0435\u043b, \u0442\u043e \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u0434 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 Resend code? \u043c\u044b \u0432\u0435\u0448\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 Auth.resendSignUp(userInfo.email)<br \/>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">Auth.confirmSignUp(email, code, { forceAliasCreation: true })<\/code><\/pre>\n<p>  <\/p>\n<p>\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">Auth.signIn(email, password)<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/560\/ec1\/171\/560ec1171f5bc79a6dde22f0f344cb58.png\" alt=\"Step09\"><\/p>\n<p>  <\/p>\n<h2 id=\"user-screen\">User screen<\/h2>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d USER, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c c \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043e\u0447\u0438\u0441\u0442\u043a\u043e\u0439 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 src\/screens\/Authenticator\/User\/index.js<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/cd9\/6c3\/76b\/cd96c376bb368293f22d215627c466ac.png\" alt=\"User screen\"><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React, { useState, useEffect } from 'react' import { Auth } from 'aws-amplify' import * as Keychain from 'react-native-keychain' import { AppContainer, Button } from 'react-native-unicorn-uikit' import { goHome } from '..\/..\/..\/constants'  const User = ({ navigation }) =&gt; {   const [loading, setLoading] = useState(false)   const [error, setError] = useState('')    useEffect(() =&gt; {     const checkUser = async () =&gt; {       await Auth.currentAuthenticatedUser()     }     checkUser()   })    const _onPress = async () =&gt; {     setLoading(true)     try {       await Auth.signOut()       await Keychain.resetInternetCredentials('auth')       goHome(navigation)()     } catch (err) {       setError(err.message)     }   }    return (     &lt;AppContainer message={error} loading={loading}&gt;       &lt;Button title=&quot;Sign Out&quot; onPress={_onPress} \/&gt;     &lt;\/AppContainer&gt;   ) }  export { User }<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/df8\/22a\/e04\/df822ae04334378b0b39d6bd70bf2513.png\" alt=\"Step10\"><\/p>\n<p>  <\/p>\n<h2 id=\"signin-screen\">SignIn screen<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044e\u0437\u0435\u0440\u0443 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u043e\u0439\u0442\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0440\u0430\u043d SIGN_IN src\/screens\/Authenticator\/SignIn\/index.js<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/603\/4f5\/702\/6034f57024d57d86448d22469e8ac0be.png\" alt=\"SignIn screen\"><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React, { useState } from 'react' import { Auth } from 'aws-amplify' import * as Keychain from 'react-native-keychain' import { Formik } from 'formik' import * as Yup from 'yup' import { AppContainer, Button, Space, ButtonLink, TextError, Input } from 'react-native-unicorn-uikit' import { onScreen, goBack } from '..\/..\/..\/constants'  const SignIn = ({ navigation }) =&gt; {   const [userInfo, setUserInfo] = useState('')   const [loading, setLoading] = useState(false)   const [error, setError] = useState('')    const _onPress = async (values) =&gt; {     setLoading(true)     setError('')     try {       const { email, password } = values       const user = await Auth.signIn(email, password)       await Keychain.setInternetCredentials('auth', email, password)       user &amp;&amp; onScreen('USER', navigation)()       setLoading(false)     } catch (err) {       setLoading(false)       if (err.code === 'UserNotConfirmedException') {         setError('Account not verified yet')       } else if (err.code === 'PasswordResetRequiredException') {         setError('Existing user found. Please reset your password')       } else if (err.code === 'NotAuthorizedException') {         setError('Forgot Password?')       } else if (err.code === 'UserNotFoundException') {         setError('User does not exist!')       } else {         setError(err.code)       }     }   }    return (     &lt;&gt;       &lt;AppContainer onPress={goBack(navigation)} title=&quot;Sign In&quot; loading={loading}&gt;         &lt;Space height={140} \/&gt;         &lt;Formik           initialValues={{ email: '', password: '' }}           onSubmit={(values) =&gt; _onPress(values) &amp;&amp; setUserInfo(values.email)}           validationSchema={Yup.object().shape({             email: Yup.string().email().required(),             password: Yup.string().min(6).required()           })}         &gt;           {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) =&gt; (             &lt;&gt;               &lt;Input                 name=&quot;email&quot;                 value={values.email}                 onChangeText={handleChange('email')}                 onBlur={() =&gt; setFieldTouched('email')}                 placeholder=&quot;E-mail&quot;                 touched={touched}                 errors={errors}                 autoCapitalize=&quot;none&quot;               \/&gt;               &lt;Input                 name=&quot;password&quot;                 value={values.password}                 onChangeText={handleChange('password')}                 onBlur={() =&gt; setFieldTouched('password')}                 placeholder=&quot;Password&quot;                 touched={touched}                 errors={errors}                 secureTextEntry               \/&gt;               {error !== 'Forgot Password?' &amp;&amp; &lt;TextError title={error} textStyle={{ alignSelf: 'center' }} \/&gt;}               {error === 'Forgot Password?' &amp;&amp; (                 &lt;ButtonLink                   title={error}                   onPress={onScreen('FORGOT', navigation, userInfo)}                   textStyle={{ alignSelf: 'center' }}                 \/&gt;               )}               &lt;Space height={30} \/&gt;               &lt;Button title=&quot;Sign In&quot; disabled={!isValid} onPress={handleSubmit} formik \/&gt;             &lt;\/&gt;           )}         &lt;\/Formik&gt;       &lt;\/AppContainer&gt;     &lt;\/&gt;   ) }  export { SignIn }<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/81f\/03c\/c4c\/81f03cc4cf1c819f35f562367e6975d1.png\" alt=\"Step11\"><\/p>\n<p>  <\/p>\n<h2 id=\"forgot-password-screen\">Forgot password screen<\/h2>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430, \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u044e\u0437\u0435\u0440\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d USER, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0443\u0436\u0435 \u0440\u0430\u043d\u0435\u0435 \u0441\u0434\u0435\u043b\u0430\u043b\u0438, \u0430 \u0435\u0441\u043b\u0438 \u044e\u0437\u0435\u0440 \u0437\u0430\u0431\u044b\u043b \u0438\u043b\u0438 \u043d\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u0432\u0435\u043b \u043f\u0430\u0440\u043e\u043b\u044c, \u0442\u043e \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 Forgot Password? \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/39c\/556\/be6\/39c556be682081bc220a4ae25c147e0a.png\" alt=\"Forgot password\"><\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0440\u0430\u043d FORGOT src\/screens\/Authenticator\/Forgot\/index.js<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/ec3\/e63\/053\/ec3e630535201998be068fad593bb650.png\" alt=\"Forgot password\"><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React, { useState } from 'react' import { Auth } from 'aws-amplify' import { Formik } from 'formik' import * as Yup from 'yup' import { AppContainer, Button, Input } from 'react-native-unicorn-uikit' import { onScreen, goBack } from '..\/..\/..\/constants'  const Forgot = ({ route, navigation }) =&gt; {   const [loading, setLoading] = useState(false)   const [error, setError] = useState('')    const _onPress = async (values) =&gt; {     setLoading(true)     try {       const { email } = values       const user = await Auth.forgotPassword(email)       user &amp;&amp; onScreen('FORGOT_PASSWORD_SUBMIT', navigation, email)()       setLoading(false)     } catch (err) {       setError(error)     }   }    return (     &lt;&gt;       &lt;AppContainer title=&quot;Forgot&quot; onPress={goBack(navigation)} loading={loading}&gt;         &lt;Formik           initialValues={{ email: route.params }}           onSubmit={(values) =&gt; _onPress(values)}           validationSchema={Yup.object().shape({             email: Yup.string().email().required()           })}         &gt;           {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) =&gt; (             &lt;&gt;               &lt;Input                 name=&quot;email&quot;                 value={values.email}                 onChangeText={handleChange('email')}                 onBlur={() =&gt; setFieldTouched('email')}                 placeholder=&quot;E-mail&quot;                 touched={touched}                 errors={errors}                 autoCapitalize=&quot;none&quot;               \/&gt;               &lt;Button title=&quot;Confirm&quot; disabled={!isValid} onPress={handleSubmit} formik \/&gt;             &lt;\/&gt;           )}         &lt;\/Formik&gt;       &lt;\/AppContainer&gt;     &lt;\/&gt;   ) }  export { Forgot }<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/3a2\/be6\/a51\/3a2be6a514a1193ffc38111740b16e3a.png\" alt=\"Step12\"><\/p>\n<p>  <\/p>\n<h2 id=\"forgot-password-submit\">Forgot Password Submit<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f e-mail, \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 Auth.forgotPassword(email) \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u044e\u0437\u0435\u0440 \u0435\u0441\u0442\u044c, \u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d FORGOT_PASSWORD_SUBMIT src\/screens\/Authenticator\/ForgotPassSubmit\/index.js<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/3b3\/32a\/335\/3b332a33583377b95f9454b26f912259.png\" alt=\"ForgotPassSubmit\"><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import React, { useState } from 'react' import { Platform } from 'react-native' import { Auth } from 'aws-amplify' import * as Keychain from 'react-native-keychain' import { Formik } from 'formik' import * as Yup from 'yup' import { AppContainer, Button, Space, Input, TextError } from 'react-native-unicorn-uikit' import { onScreen, goBack } from '..\/..\/..\/constants'  const ForgotPassSubmit = ({ route, navigation }) =&gt; {   const [loading, setLoading] = useState(false)   const [error, setError] = useState('')    const _onPress = async (values) =&gt; {     setLoading(true)     try {       const { email, code, password } = values       await Auth.forgotPasswordSubmit(email, code, password)       await Keychain.setInternetCredentials('auth', email, password)       onScreen('USER', navigation)()       setLoading(false)     } catch (err) {       setLoading(false)       setError(err.message)     }   }    return (     &lt;&gt;       &lt;AppContainer title=&quot;Confirmation&quot; onPress={goBack(navigation)} loading={loading}&gt;         &lt;Space height={Platform.OS === 'ios' ? 20 : 150} \/&gt;         &lt;Formik           initialValues={{ email: route.params, code: '', password: '', passwordConfirmation: '' }}           onSubmit={(values) =&gt; _onPress(values)}           validationSchema={Yup.object().shape({             email: Yup.string().email().required(),             code: Yup.string().min(6).required(),             password: Yup.string().min(6).required(),             passwordConfirmation: Yup.string().min(6).required()           })}         &gt;           {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) =&gt; (             &lt;&gt;               &lt;Input                 name=&quot;email&quot;                 value={values.email}                 onChangeText={handleChange('email')}                 onBlur={() =&gt; setFieldTouched('email')}                 placeholder=&quot;E-mail&quot;                 touched={touched}                 errors={errors}                 autoCapitalize=&quot;none&quot;               \/&gt;               &lt;Input                 name=&quot;code&quot;                 value={values.code}                 onChangeText={handleChange('code')}                 onBlur={() =&gt; setFieldTouched('code')}                 placeholder=&quot;Code&quot;                 touched={touched}                 errors={errors}               \/&gt;               &lt;Input                 name=&quot;password&quot;                 value={values.password}                 onChangeText={handleChange('password')}                 onBlur={() =&gt; setFieldTouched('password')}                 placeholder=&quot;Password&quot;                 touched={touched}                 errors={errors}                 secureTextEntry               \/&gt;               &lt;Input                 name=&quot;passwordConfirmation&quot;                 value={values.passwordConfirmation}                 onChangeText={handleChange('passwordConfirmation')}                 onBlur={() =&gt; setFieldTouched('passwordConfirmation')}                 placeholder=&quot;Password confirm&quot;                 touched={touched}                 errors={errors}                 secureTextEntry               \/&gt;               {error !== '' &amp;&amp; &lt;TextError title={error} textStyle={{ alignSelf: 'center' }} \/&gt;}               &lt;Space height={30} \/&gt;               &lt;Button title=&quot;Confirm&quot; disabled={!isValid} onPress={handleSubmit} formik \/&gt;             &lt;\/&gt;           )}         &lt;\/Formik&gt;       &lt;\/AppContainer&gt;     &lt;\/&gt;   ) }  export { ForgotPassSubmit }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0433\u0434\u0435 \u043f\u043e\u0441\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u043a\u043e\u0434\u0430, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u043f\u043e\u0447\u0442\u0443, \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0430\u0440\u043e\u043b\u044f \u0438 \u0435\u0433\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f, \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0441\u043c\u0435\u043d\u044b \u043f\u0430\u0440\u043e\u043b\u044f<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">Auth.forgotPasswordSubmit(email, code, password)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0443\u0441\u043f\u0435\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u044e\u0437\u0435\u0440\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d USER.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e0a\/e7c\/f83\/e0ae7cf835073155c02c00d537d335fd.png\" alt=\"Step13\"><\/p>\n<p>  <\/p>\n<h2 id=\"svyazyvanie-ekranov\">\u0421\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u043e\u0432<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432 src\/screens\/Authenticator\/index.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">export * from '.\/Hello' export * from '.\/User' export * from '.\/SignIn' export * from '.\/SignUp' export * from '.\/Forgot' export * from '.\/ForgotPassSubmit' export * from '.\/ConfirmSignUp'<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/f21\/101\/ea7\/f21101ea74d3f57f1691aacb625d707a.png\" alt=\"Step14\"><\/p>\n<p>  <\/p>\n<h2 id=\"udpate-appnavigator\">Udpate AppNavigator<\/h2>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">import * as React from 'react' import { createStackNavigator } from '@react-navigation\/stack' import { Hello, SignUp, SignIn, ConfirmSignUp, User, Forgot, ForgotPassSubmit } from '.\/screens\/Authenticator'  const Stack = createStackNavigator()  const AppNavigator = () =&gt; {   return (     &lt;Stack.Navigator       screenOptions={{         headerShown: false       }}       initialRouteName=&quot;HELLO&quot;     &gt;       &lt;Stack.Screen name=&quot;HELLO&quot; component={Hello} \/&gt;       &lt;Stack.Screen name=&quot;SIGN_UP&quot; component={SignUp} \/&gt;       &lt;Stack.Screen name=&quot;SIGN_IN&quot; component={SignIn} \/&gt;       &lt;Stack.Screen name=&quot;FORGOT&quot; component={Forgot} \/&gt;       &lt;Stack.Screen name=&quot;FORGOT_PASSWORD_SUBMIT&quot; component={ForgotPassSubmit} \/&gt;       &lt;Stack.Screen name=&quot;CONFIRM_SIGN_UP&quot; component={ConfirmSignUp} \/&gt;       &lt;Stack.Screen name=&quot;USER&quot; component={User} \/&gt;     &lt;\/Stack.Navigator&gt;   ) }  export default AppNavigator<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e7a\/ab6\/a44\/e7aab6a44c55db24e7571c547fe90434.png\" alt=\"Step15\"><\/p>\n<p>  <\/p>\n<h2 id=\"clean-up\">Clean Up<\/h2>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u0442\u0435\u043c\u0443, \u0442\u043e \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b AmplifyTheme \u0438 Localei18n<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/8f1\/aed\/fbf\/8f1aedfbf2e71d312601354edb707715.png\" alt=\"Step16\"><\/p>\n<p>  <\/p>\n<h2 id=\"debug\">Debug<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \/index.js<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">window.LOG_LEVEL = 'DEBUG'<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.<\/p>\n<p>  <\/p>\n<h2 id=\"done-1\">Done<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043c\u044b \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e <a href=\"https:\/\/habr.com\/ru\/post\/503964\">DataStore \u2014 CRUD (Create Read Update Delete)<\/a><\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/www.patreon.com\/bePatron?u=31769291\" rel=\"nofollow\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/00c\/16d\/925\/00c16d925fd0bca08a5442812fa02fbf.png\" alt=\"Become a Patron!\"><\/a><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/504344\/\"> https:\/\/habr.com\/ru\/post\/504344\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/504344\/\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/406\/65e\/0e9\/40665e0e973bdd2a10416e9113667856.png\" alt=\"cognito\"><\/p>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0442\u0435\u043c, \u0441\u0440\u0435\u0434\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432 \u043c\u043e\u0435\u0433\u043e \u043a\u0430\u043d\u0430\u043b\u0430 <a href=\"https:\/\/www.youtube.com\/channel\/UCOxewePwIQATdHTD3yZ2UZw\" rel=\"nofollow\">\u0414\u0438\u043c\u043a\u0430 \u0420\u0435\u0430\u043a\u0442\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439<\/a> \u2014 \u044d\u0442\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 React Native. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0441\u0432\u0435\u0442\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043b\u043e\u043d\u0433\u0440\u0438\u0434 \u0438 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u043a\u043e\u0434\u0438\u0442\u044c, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\/\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-304447","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/304447","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=304447"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/304447\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=304447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=304447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=304447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}