{"id":298689,"date":"2020-02-14T15:00:08","date_gmt":"2020-02-14T15:00:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=298689"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2020-02-14T15:00:08","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=298689","title":{"rendered":"\u041a\u0430\u043a \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c Telegram-\u0431\u043e\u0442 \u0441 OpenId Connect"},"content":{"rendered":"\n<div class=\"post__text post__text-html\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/488390\/\">\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0441\u0435\u0431\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e: \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Foobar Inc. \u043f\u0440\u043e\u0432\u0435\u043b\u0438 \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u044a\u044e\u043d\u043a\u0442\u0443\u0440\u044b \u0440\u044b\u043d\u043a\u0430 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0437\u0434\u0435\u0440\u0436\u0435\u043a \u0438 \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0431\u044b\u043b\u0438 Foobar \u043a\u0440\u043e\u0432\u044c \u0438\u0437 \u043d\u043e\u0441\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f Telegram-\u0431\u043e\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u044c\u043e\u043d, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0431\u043e\u0434\u0440\u0438\u0442\u044c \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u0432 \u0442\u0440\u0443\u0434\u043d\u0443\u044e \u043c\u0438\u043d\u0443\u0442\u0443.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, Foobar \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043a\u043e\u0432\u0430\u0440\u043d\u044b\u0435 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u0445 \u043d\u043e\u0443-\u0445\u0430\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0438\u0445 \u0431\u043e\u0442\u0430 \u0441\u0435\u0431\u0435 \u0432 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u044b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0431\u043e\u0442 \u0440\u0430\u0437\u0433\u043e\u0432\u0430\u0440\u0438\u0432\u0430\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430\u043c\u0438 Foobar, \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u043c\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0432\u0445\u043e\u0434\u0430 (SSO) \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 OpenId Connect.<\/p>\n<p>  <\/p>\n<div class=\"oembed\">\n<div>\n<div style=\"left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;\"><iframe src=\"https:\/\/www.youtube.com\/embed\/kJ65rKtOrTw?rel=0&amp;showinfo=1&amp;hl=en-US\" style=\"border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;\" allowfullscreen scrolling=\"no\" allow=\"encrypted-media; accelerometer; gyroscope; picture-in-picture\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"v-teorii\">\u0412 \u0442\u0435\u043e\u0440\u0438\u0438<\/h2>\n<p>  <\/p>\n<p>OpenId Connect (OIDC) \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0441\u0435\u043c\u0435\u0439\u0441\u0442\u0432\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 OAuth 2.0. \u0412 \u043d\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u043c \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 (flow), \u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0442\u0440\u0438 \u0441\u0442\u043e\u0440\u043e\u043d\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0432\u043b\u0430\u0434\u0435\u043b\u0435\u0446 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 (resource owner) \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c;<\/li>\n<li>\u043a\u043b\u0438\u0435\u043d\u0442 (client) \u2014 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0449\u0435\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e;<\/li>\n<li>\u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 (authorization server) \u2014 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0435 \u0435\u0433\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u0430\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/JSON_Web_Token\" rel=\"nofollow\">JWT<\/a>-\u0442\u043e\u043a\u0435\u043d\u043e\u0432 (JSON Web Token). \u041d\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u0443\u0433\u043b\u0443\u0431\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u044e \u0438 \u0434\u0435\u0442\u0430\u043b\u0438 <a href=\"https:\/\/openid.net\/specs\/openid-connect-core-1_0.html\" rel=\"nofollow\">\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OIDC<\/a>, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0438 \u0431\u0435\u0437 \u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u043c\u0430\u043b\u043e \u0441\u0442\u0430\u0442\u0435\u0439, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u043d\u0430 <a href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/475942\/\">\u0425\u0430\u0431\u0440\u0435<\/a>, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0445 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u0445 \u0440\u0430\u0431\u043e\u0442\u044b OIDC.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438, \u043f\u043e\u043c\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0431\u043e\u0442\u0430, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438: \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0432\u044f\u0437\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u0434\u0430\u043d\u043d\u044b\u043c Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0438 \u0443\u0447\u0435\u0442\u043a\u043e\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 SSO. \u041d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u043c, \u043a\u0430\u043a\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u0412 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OIDC \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \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<ul>\n<li>\u043f\u043e\u0442\u043e\u043a \u0441 \u043a\u043e\u0434\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 (authorization code flow),<\/li>\n<li>\u043d\u0435\u044f\u0432\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a (implicit flow),<\/li>\n<li>\u0433\u0438\u0431\u0440\u0438\u0434\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a (hybrid flow),<\/li>\n<li>\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u0438, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0432 OAuth 2.0.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u0448 \u0431\u043e\u0442 \u2014 \u044d\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e HTTP, \u043d\u0430\u043c \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442 \u043f\u043e\u0442\u043e\u043a \u0441 \u043a\u043e\u0434\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0421\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/6z\/cu\/tx\/6zcutxveqfiyt3h5kwjcluhwyec.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u043f\u043e\u0442\u043e\u043a\u0430 \u0441 \u043a\u043e\u0434\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\"><\/div>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0435\u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0438\u0448\u0435\u0442 \u0431\u043e\u0442\u0443.<\/li>\n<li>\u0411\u043e\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/li>\n<li>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.<\/li>\n<li>\u0421\u0435\u0440\u0432\u0435\u0440 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u043e\u0440\u043c\u044b \u043b\u043e\u0433\u0438\u043d\u0430).<\/li>\n<li>\u041f\u043e\u0441\u043b\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 callback URL \u0431\u043e\u0442\u0430 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/li>\n<li>\u0411\u043e\u0442 \u043f\u0440\u043e\u0441\u0438\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0431\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438 ID \u0442\u043e\u043a\u0435\u043d.<\/li>\n<li>\u0421\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u0442\u0443 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0412 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0432\u0441\u0435 \u0445\u043e\u0440\u043e\u0448\u043e, \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u0448\u0430\u0433\u0435, \u043a\u043e\u0433\u0434\u0430 \u0431\u043e\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438 ID \u0442\u043e\u043a\u0435\u043d, \u0443 \u043d\u0435\u0433\u043e \u0443\u0436\u0435 \u043d\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u0441\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439.<\/p>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0440\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <a href=\"https:\/\/openid.net\/specs\/openid-connect-core-1_0.html#AuthRequest\" rel=\"nofollow\">state<\/a> \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0430\u0442\u0430\u043a \u043c\u0435\u0436\u0441\u0430\u0439\u0442\u043e\u0432\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u043b\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (XSRF). \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 state \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0431\u043e\u0442\u0430 \u043d\u0430 \u0448\u0430\u0433\u0435 2 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 URL \u0432 \u0432\u0438\u0434\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0437\u0430\u0442\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0448\u0430\u0433\u0435 5 \u0432 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 callback URL \u0431\u043e\u0442\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0435\u0441\u043b\u0438 \u043c\u044b \u043d\u0430 \u0448\u0430\u0433\u0435 2 \u0441\u0432\u044f\u0436\u0435\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 state \u0441 id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0442\u043e \u043d\u0430 \u0448\u0430\u0433\u0435 7 \u043f\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e state \u0441\u043c\u043e\u0436\u0435\u043c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438. \u0411\u0438\u043d\u0433\u043e!<\/p>\n<p>  <\/p>\n<h2 id=\"na-praktike\">\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435<\/h2>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u043e\u043e\u0440\u0443\u0436\u0438\u0432\u0448\u0438\u0441\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/www.keycloak.org\" rel=\"nofollow\">Keycloak<\/a> \u2014 open source \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c (Identity and Access Management), \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u044b OAuth 2.0, Open ID Connect \u0438 SAML.<\/li>\n<li><a href=\"https:\/\/spring.io\/projects\/spring-boot\" rel=\"nofollow\">Spring Boot<\/a> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u0430\u0440\u043a\u0430\u0441\u0430 \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/li>\n<li><a href=\"https:\/\/github.com\/rubenlagus\/TelegramBots\" rel=\"nofollow\">TelegramBots<\/a> \u2014 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430\u044f Java \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Telegram-\u0431\u043e\u0442\u043e\u0432. \u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u043e\u043d\u0443\u0441 \u2014 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441\u043e Spring Boot.<\/li>\n<li><a href=\"https:\/\/github.com\/scribejava\/scribejava\" rel=\"nofollow\">ScribeJava<\/a> \u2014 \u043f\u043e\u043b\u043d\u043e\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 OAuth \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f Java. \u0425\u043e\u0440\u043e\u0448 \u0441\u0432\u043e\u0435\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0435\u043c \u043f\u0440\u0435\u0441\u0435\u0442\u043e\u0432 \u0434\u043b\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 OAuth \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0434\u043b\u044f Keycloak. \u0417\u0434\u0435\u0441\u044c \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e Keycloak \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u044b \u0434\u043b\u044f \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043f\u043e\u0434 \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b, \u0438 Spring Boot \u2014 \u043d\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. \u042d\u0442\u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 Keycloak \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0441\u0442\u0440\u043e\u0447\u043a\u0430\u043c\u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435, \u043d\u043e \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 \u2014 Telegram-\u0431\u043e\u0442, \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u0441\u0432\u044f\u0437\u043a\u0438 state \u0441 id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0430\u043c \u0442\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442.<\/li>\n<li><a href=\"https:\/\/github.com\/auth0\/java-jwt\" rel=\"nofollow\">Java JWT \u043e\u0442 Auth0<\/a> \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f JWT \u0434\u043b\u044f Java, \u043e\u043d\u0430 \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 ID \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0431\u043e\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">@Component public class Bot extends TelegramLongPollingBot {     private final OidcService oidcService;     \/\/ ...      \/\/ \u041c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0431\u043e\u0442\u043e\u043c \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439,     \/\/ inline-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439.     @Override     public void onUpdateReceived(Update update) {         if (!update.hasMessage()) {             log.debug(&quot;Update has no message. Skip processing.&quot;);             return;         }          \/\/ Id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.         var userId = update.getMessage().getFrom().getId();         var chatId = update.getMessage().getChatId();         \/\/ \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c UserInfo (\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435,         \/\/ \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438) \u043f\u043e id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.         oidcService.findUserInfo(userId).ifPresentOrElse(                 userInfo -&gt; greet(userInfo, chatId),                 () -&gt; askForLogin(userId, chatId));     }      private void greet(UserInfo userInfo, Long chatId) {         \/\/ \u0417\u0434\u0435\u0441\u044c \u043c\u043e\u0433\u043b\u043e \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u0441\u043c\u0435\u0436\u043d\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c         \/\/ \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0441\u043c\u0435\u0436\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435         \/\/ \u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u043e\u0441\u044c \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043f\u0440\u0438\u0441\u043b\u0430\u0432\u0448\u0435\u0433\u043e \u0431\u043e\u0442\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.         var username = userInfo.getPreferredUsername();         var message = String.format(                 &quot;Hello, &lt;b&gt;%s&lt;\/b&gt;!\\nYou are the best! Have a nice day!&quot;,                 username);         sendHtmlMessage(message, chatId);     }      private void askForLogin(Integer userId, Long chatId) {         \/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c URL \u0434\u043b\u044f \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\u044f         \/\/ (\u0441\u043c. \u0448\u0430\u0433 2 \u043d\u0430 \u0441\u0445\u0435\u043c\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f).         var url = oidcService.getAuthUrl(userId);         var message = String.format(&quot;Please, &lt;a href=\\&quot;%s\\&quot;&gt;log in&lt;\/a&gt;.&quot;, url);         sendHtmlMessage(message, chatId);     }     \/\/ ... }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u2014 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u043e\u0438\u0441\u043a\u0430 UserInfo \u043f\u043e id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f URL \u0434\u043b\u044f \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\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">@Service public class OidcService {     \/\/ OAuth20Service \u2014 \u043a\u043b\u0430\u0441\u0441 \u0438\u0437 ScribeJava.     \/\/ \u0427\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0435 \u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.     private final OAuth20Service oAuthService;     \/\/ UserTrackerStorage \u2014 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439     \/\/ (\u0441\u0432\u044f\u0437\u043e\u043a state -&gt; id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).     private final UserTrackerStorage userTrackers;     \/\/ TokenStorage \u2014 &quot;\u0443\u043c\u043d\u043e\u0435&quot; \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 (\u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, ID \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438     \/\/ \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f (refresh token)) \u0432 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0435 \u043a id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.     \/\/ \u0415\u0441\u043b\u0438 \u0441\u0440\u043e\u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0441\u0442\u0435\u043a, \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0441\u0430\u043c\u043e     \/\/ \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430 \u0441\u0432\u0435\u0436\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043f\u0440\u0435\u0434\u044a\u044f\u0432\u043b\u044f\u044f     \/\/ \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f.     \/\/ \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0437\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0431\u043e\u0442 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u043c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c,     \/\/ \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440, \u043d\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043e\u0441\u043e\u0431\u044b\u0435     \/\/ \u0442\u043e\u043a\u0435\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0438 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430,     \/\/ \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0437\u0430\u043b\u043e\u0433\u0438\u043d\u0435\u043d \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.     \/\/ \u042d\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f offline_access. \u041d\u0438\u0436\u0435 \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f.     \/\/ \u0414\u043b\u044f \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0442\u0438, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e TokenStorage \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c.     private final TokenStorage accessTokens;      public Optional&lt;UserInfo&gt; findUserInfo(Integer userId) {         return accessTokens.find(userId)                 .map(UserInfo::of);     }      public String getAuthUrl(Integer userId) {         var state = UUID.randomUUID().toString();         userTrackers.put(state, userId);         return oAuthService.getAuthorizationUrl(state);     }     \/\/ ... }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043b\u0430\u0441\u0441, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u0443\u044e \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">public class UserInfo {     private final String subject;     private final String preferredUsername;      static UserInfo of(OpenIdOAuth2AccessToken token) {         \/\/ \u0414\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c ID \u0442\u043e\u043a\u0435\u043d \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 UserInfo.         var jwt = JWT.decode(token.getOpenIdToken());         var subject = jwt.getSubject();         var preferredUsername = jwt.getClaim(&quot;preferred_username&quot;).asString();          return new UserInfo(subject, preferredUsername);     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 OAuth20Service:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">@Configuration @EnableConfigurationProperties(OidcProperties.class) class OidcAutoConfiguration {     @Bean     OAuth20Service oAuthService(OidcProperties properties) {         \/\/ \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f OAuth20Service \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c id \u043a\u043b\u0438\u0435\u043d\u0442\u0430,         \/\/ \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043e\u043d \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, ...         return new ServiceBuilder(properties.getClientId())                 \/\/ \u0441\u0435\u043a\u0440\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, ...                 .apiSecret(properties.getClientSecret())                 \/\/ \u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f (scopes):                 \/\/ openid \u2014 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f OpenId Connect,                 \/\/ offline_access \u2014 \u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u0444\u043b\u0430\u0439\u043d-\u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a                 \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044e \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u0440\u0430\u043d\u0435\u0435.                 .defaultScope(&quot;openid offline_access&quot;)                 \/\/ \u0417\u0430\u0434\u0430\u0435\u043c callback, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0435\u0442                 \/\/ \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u0448\u0430\u0433\u0435 5.                 .callback(properties.getCallback())                 .build(KeycloakApi.instance(properties.getBaseUrl(), properties.getRealm()));     } }<\/code><\/pre>\n<p>  <\/p>\n<p>Callback endpoint \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">@Component @Path(&quot;\/auth&quot;) public class AuthEndpoint {     private final URI botUri;     private final OidcService oidcService;      \/\/ ...      @GET     @Produces(&quot;text\/plain; charset=UTF-8&quot;)     public Response auth(             @QueryParam(&quot;state&quot;) String state,             @QueryParam(&quot;code&quot;) String code) {         \/\/ \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0442\u043e\u043a\u0435\u043d\u044b \u0432 \u043e\u0431\u043c\u0435\u043d \u043d\u0430 \u043a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438         \/\/ (\u0441\u043c. \u0448\u0430\u0433 6 \u043d\u0430 \u0441\u0445\u0435\u043c\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f).         return oidcService.completeAuth(state, code)                 \/\/ \u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043a, \u0442\u043e \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u043c \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u0447\u0430\u0442 \u0441 \u0431\u043e\u0442\u043e\u043c.                 .map(userInfo -&gt; Response.temporaryRedirect(botUri).build())                 \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443 state \u043d\u0435 \u043d\u0430\u0448\u0435\u043b\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u043b\u0438\u0431\u043e \u0435\u0441\u043b\u0438                 \/\/ \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0445\u043e\u0434\u0435 \u043e\u0431\u043c\u0435\u043d\u0430 \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0442\u043e\u043a\u0435\u043d\u044b,                 \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c HTTP-\u0441\u0442\u0430\u0442\u0443\u0441 500.                 .orElseGet(() -&gt; Response.serverError().entity(&quot;Cannot complete authentication&quot;).build());     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a OidcService, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 completeAuth:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">@Service public class OidcService {     private final OAuth20Service oAuthService;     private final UserTrackerStorage userTrackers;     private final TokenStorage accessTokens;      \/\/ ...      public Optional&lt;UserInfo&gt; completeAuth(String state, String code) {         \/\/ \u0418\u0449\u0435\u043c id Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c\u0443 state.         return userTrackers.find(state)                 \/\/ \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0445 \u0432 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0435 \u043a id                 \/\/ Telegram-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.                 .map(userId -&gt; requestAndStoreToken(code, userId))                 .map(UserInfo::of);     }      private OpenIdOAuth2AccessToken requestAndStoreToken(             String code,             Integer userId) {         var token = requestToken(code);         accessTokens.put(userId, token);         return token;     }      private OpenIdOAuth2AccessToken requestToken(String code) {         try {             return (OpenIdOAuth2AccessToken) oAuthService.getAccessToken(code);         } catch (IOException | InterruptedException | ExecutionException e) {             throw new RuntimeException(&quot;Cannot get access token&quot;, e);         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e!<\/p>\n<p>  <\/p>\n<h2 id=\"v-zaklyuchenie\">\u0412 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0440\u0435\u0448\u0435\u043d\u0430, \u043d\u043e \u0437\u0430 \u043a\u0430\u0434\u0440\u043e\u043c \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0435\u0449\u0435 \u0440\u044f\u0434 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0448\u0438\u0442\u044c, \u043f\u0440\u0435\u0436\u0434\u0435, \u0447\u0435\u043c \u043a\u0430\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0432 \u043f\u0440\u043e\u0434. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0444\u043b\u0430\u0439\u043d-\u0442\u043e\u043a\u0435\u043d\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\/\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u043e\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0443\u0436\u0435 \u0440\u0435\u0448\u0435\u043d\u044b \u0437\u0430 \u043d\u0430\u0441 \u0432 \u0431\u043e\u043b\u0435\u0435 \u0440\u0430\u0437\u0432\u0435\u0441\u0438\u0441\u0442\u044b\u0445 OAuth-\u043a\u043b\u0438\u0435\u043d\u0442\u0430\u0445 \u0432\u0440\u043e\u0434\u0435 <a href=\"https:\/\/spring.io\/projects\/spring-security\" rel=\"nofollow\">Spring Security<\/a> \u0438 <a href=\"https:\/\/github.com\/googleapis\/google-oauth-java-client\" rel=\"nofollow\">Google OAuth Client<\/a>. \u041d\u043e \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439 \u043d\u0430\u043c \u0438 \u0442\u0430\u043a \u043e\u043a \ud83d\ude42<\/p>\n<p>  <\/p>\n<p>\u0412\u0441\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 <a href=\"https:\/\/github.com\/flipp5b\/telegram-bot-oidc\" rel=\"nofollow\">GitHub<\/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\/488390\/\"> https:\/\/habr.com\/ru\/post\/488390\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/488390\/\">\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0441\u0435\u0431\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e: \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Foobar Inc. \u043f\u0440\u043e\u0432\u0435\u043b\u0438 \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u044a\u044e\u043d\u043a\u0442\u0443\u0440\u044b \u0440\u044b\u043d\u043a\u0430 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0437\u0434\u0435\u0440\u0436\u0435\u043a \u0438 \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0431\u044b\u043b\u0438 Foobar \u043a\u0440\u043e\u0432\u044c \u0438\u0437 \u043d\u043e\u0441\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f Telegram-\u0431\u043e\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u044c\u043e\u043d, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0431\u043e\u0434\u0440\u0438\u0442\u044c \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u0432 \u0442\u0440\u0443\u0434\u043d\u0443\u044e \u043c\u0438\u043d\u0443\u0442\u0443.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, Foobar \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043a\u043e\u0432\u0430\u0440\u043d\u044b\u0435 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u0445 \u043d\u043e\u0443-\u0445\u0430\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0438\u0445 \u0431\u043e\u0442\u0430 \u0441\u0435\u0431\u0435 \u0432 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u044b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0431\u043e\u0442 \u0440\u0430\u0437\u0433\u043e\u0432\u0430\u0440\u0438\u0432\u0430\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430\u043c\u0438 Foobar, \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u043c\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0432\u0445\u043e\u0434\u0430 (SSO) \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 OpenId Connect.<\/p>\n<p>  <\/p>\n<div class=\"oembed\">\n<div>\n<div style=\"left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;\"><iframe src=\"https:\/\/www.youtube.com\/embed\/kJ65rKtOrTw?rel=0&amp;showinfo=1&amp;hl=en-US\" style=\"border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;\" allowfullscreen scrolling=\"no\" allow=\"encrypted-media; accelerometer; gyroscope; picture-in-picture\"><\/iframe><\/div>\n<\/div>\n<\/div>\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-298689","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/298689","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=298689"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/298689\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=298689"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=298689"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=298689"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}