{"id":465369,"date":"2025-07-01T15:04:46","date_gmt":"2025-07-01T15:04:46","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=465369"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=465369","title":{"rendered":"<span>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f OAuth 2.0 \u0432 PostgreSQL \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 Keycloak<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u041f\u043b\u0430\u043d \u0441\u0442\u0430\u0442\u044c\u0438<\/h2>\n<ul>\n<li>\n<p><a href=\"#%D0%92%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20Keycloak%20%D0%B8%D0%BD%D0%B6%D0%B5%D0%BD%D0%B5%D1%80%D0%BE%D0%BC%20%D0%BF%D0%BE%20%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D0%B8\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20PostgreSQL%20%D0%B0%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%BC%20%D0%B1%D0%B0%D0%B7%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9F%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%20%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/a><\/p>\n<\/li>\n<\/ul>\n<p><a class=\"anchor\" name=\"%D0%92%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5\" id=\"\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435\"><\/a><\/p>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0421\u0423\u0411\u0414 Tantor Postgres 17.5.0. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u043c\u044b\u00a0<a href=\"https:\/\/habr.com\/ru\/companies\/tantor\/articles\/919592\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0438\u0441\u0430\u043b\u0438<\/a>\u00a0\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u0441\u0431\u043e\u0440 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0441\u00a0pg_stat_statements \u043c\u043e\u0436\u0435\u0442 \u0447\u0435\u0440\u0435\u0441\u0447\u0443\u0440 \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438, \u043a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432 \u043a\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 OAuth 2.0.\u00a0\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 OAuth 2.0 Device Authorization Flow \u2014 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 PostgreSQL 18. \u042d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a PostgreSQL \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u00a0\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, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 Keycloak, \u0447\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0440\u0435\u0434 \u0438 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 Tantor Postgres \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0432 \u0438\u044e\u043d\u0435 2025 \u0433. \u0432\u0435\u0440\u0441\u0438\u0438 17.5.0.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u0430\u0440\u043e\u043b\u044e (password, md5, SCRAM), OAuth \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0447\u0435\u0442\u043d\u044b\u043c\u0438 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 \u0438 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430\u043c\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0432 \u0435\u0434\u0438\u043d\u043e\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\u00a0\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c. Device Authorization Flow \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432, \u0433\u0434\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u0438\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b), \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438\u043b\u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 OAuth-\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 PostgreSQL \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Keycloak: \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c Keycloak, \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c PostgreSQL, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 OAuth \u0432 PostgreSQL \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u0443\u044e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 psql \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Device Flow. \u0418\u043d\u0430\u0447\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u043f\u0440\u043e\u0439\u0434\u0451\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043d\u0438\u0436\u0435 \u0441\u0445\u0435\u043c\u0443\u00a0\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 OAuth-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432 PostgreSQL:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d7e\/395\/d73\/d7e395d7344e3a97283000de1068b0cb.png\" width=\"2046\" height=\"1542\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d7e\/395\/d73\/d7e395d7344e3a97283000de1068b0cb.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d7e\/395\/d73\/d7e395d7344e3a97283000de1068b0cb.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a class=\"anchor\" name=\"%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20Keycloak%20%D0%B8%D0%BD%D0%B6%D0%B5%D0%BD%D0%B5%D1%80%D0%BE%D0%BC%20%D0%BF%D0%BE%20%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D0%B8\" id=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438\"><\/a><\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/h2>\n<p>Keycloak \u2014 \u044d\u0442\u043e \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\u00a0\u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c (open source), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \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, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u00a0\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0438 \u0434\u0430\u043d\u043d\u044b\u043c, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044f \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 (SSO).\u00a0Keycloak \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f, \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0438 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438 \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0430\u0440\u043e\u043b\u0435\u0439, \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0432\u0445\u043e\u0434\u0430. \u0421 Keycloak \u044d\u0442\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0449\u0435\u043b\u0447\u043a\u0430\u043c\u0438 \u043c\u044b\u0448\u0438.<\/p>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a Keycloak<\/h3>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c Keycloak \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0431\u0440\u0430\u0437\u0430 Docker. \u0422\u0430\u043a\u0436\u0435 \u043e\u0442\u043a\u0440\u043e\u0435\u043c 8080 \u043f\u043e\u0440\u0442 \u0438\u00a0\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0admin\u00a0\u0441\u00a0\u0438\u043c\u0435\u043d\u0435\u043c\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0admin\u00a0\u0438\u00a0\u043f\u0430\u0440\u043e\u043b\u0435\u043c\u00a0admin. \u041e\u043f\u0446\u0438\u0435\u0439 &#8212;name \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0438\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u043a\u0430\u043a keycloak.<\/p>\n<pre><code class=\"bash\">docker run --name keycloak -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io\/keycloak\/keycloak:26.2.1 start-dev<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u0432\u0435\u0434\u0451\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0430\u0434\u0440\u0435\u0441\u00a0<a href=\"http:\/\/localhost:8080\" rel=\"noopener noreferrer nofollow\">http:\/\/localhost:8080<\/a>, \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0430\u0434\u043c\u0438\u043d \u043f\u0430\u043d\u0435\u043b\u044c Keycloak, \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442 \u043b\u043e\u0433\u0438\u043d-\u043f\u0430\u0440\u043e\u043b\u044c. \u0412\u0432\u0435\u0434\u0451\u043c admin, admin.<\/p>\n<p>\u041f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Realm<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (Users)<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Client scope<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u041a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\u00a0(Clients)<\/p>\n<\/li>\n<\/ol>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u0442\u0430\u043f.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Realm<\/h3>\n<p>Realm \u2014 \u044d\u0442\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0440\u043e\u043b\u0438, \u0433\u0440\u0443\u043f\u043f\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.\u00a0\u0427\u0442\u043e\u0431\u044b \u0435\u0451 \u0441\u043e\u0437\u0434\u0430\u0442\u044c, \u043d\u0443\u0436\u043d\u043e \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u044c Manage realms \u0432 \u043b\u0435\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cf6\/f55\/7fa\/cf6f557faceabea5486a7d4ed64fcb1e.png\" width=\"1039\" height=\"744\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/cf6\/f55\/7fa\/cf6f557faceabea5486a7d4ed64fcb1e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cf6\/f55\/7fa\/cf6f557faceabea5486a7d4ed64fcb1e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 Manage realms:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c61\/012\/c5b\/c61012c5b124d49ec977d67166bb3072.png\" width=\"1449\" height=\"446\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c61\/012\/c5b\/c61012c5b124d49ec977d67166bb3072.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c61\/012\/c5b\/c61012c5b124d49ec977d67166bb3072.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 Create realm, \u0432 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0432 \u043f\u043e\u043b\u0435 Realm name \u0432\u0432\u043e\u0434\u0438\u043c &#171;postgres-realm&#187;.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/736\/d2c\/a58\/736d2ca587f69725d52f0dc0558ef296.png\" width=\"1245\" height=\"874\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/736\/d2c\/a58\/736d2ca587f69725d52f0dc0558ef296.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/736\/d2c\/a58\/736d2ca587f69725d52f0dc0558ef296.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 Create \u043d\u0430\u0448 realm \u0441\u043e\u0437\u0434\u0430\u0441\u0442\u0441\u044f \u0438 \u0441\u0442\u0430\u043d\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u043c.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f7c\/653\/29a\/f7c65329a94526c1ac5704a46a99354d.png\" width=\"1413\" height=\"529\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f7c\/653\/29a\/f7c65329a94526c1ac5704a46a99354d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f7c\/653\/29a\/f7c65329a94526c1ac5704a46a99354d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a class=\"anchor\" name=\"%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9\" id=\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439\"><\/a><\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (Users)<\/h3>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 (Users) \u2013 \u044d\u0442\u043e \u0441\u0443\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. \u041e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0430\u044f \u043f\u043e\u0447\u0442\u0430, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0430\u0434\u0440\u0435\u0441, \u043d\u043e\u043c\u0435\u0440 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0438 \u0434\u0435\u043d\u044c \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f. \u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043e\u043a\u043d\u043e\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 Users \u0432 \u043b\u0435\u0432\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/292\/a67\/e03\/292a67e0356d5a325aefa2ccb2a32ced.png\" width=\"1398\" height=\"784\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/292\/a67\/e03\/292a67e0356d5a325aefa2ccb2a32ced.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/292\/a67\/e03\/292a67e0356d5a325aefa2ccb2a32ced.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Create new user, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.\u00a0\u0412 \u043f\u043e\u043b\u0435 Username \u0432\u0432\u043e\u0434\u0438\u043c \u0438\u043c\u044f &#171;alice&#187;, \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u043b\u044f Email, First name \u0438 Last name.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/29a\/09b\/0c5\/29a09b0c5f60d1290536540a05a76071.png\" width=\"1560\" height=\"991\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/29a\/09b\/0c5\/29a09b0c5f60d1290536540a05a76071.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/29a\/09b\/0c5\/29a09b0c5f60d1290536540a05a76071.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 Create, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. ID \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 \u0411\u0414 \u0434\u043b\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Keycloak \u0438 PostgreSQL \u0432 \u0444\u0430\u0439\u043b\u0435 pg_ident.conf.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/672\/10d\/610\/67210d6108bb463bf1fa25ea33db3991.png\" width=\"1569\" height=\"1175\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/672\/10d\/610\/67210d6108bb463bf1fa25ea33db3991.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/672\/10d\/610\/67210d6108bb463bf1fa25ea33db3991.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Credentials \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 Set password \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0430\u0440\u043e\u043b\u044f:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/db6\/965\/f49\/db6965f49900191a9ec8dd61853dfa3d.png\" width=\"1281\" height=\"624\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/db6\/965\/f49\/db6965f49900191a9ec8dd61853dfa3d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/db6\/965\/f49\/db6965f49900191a9ec8dd61853dfa3d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u043f\u0430\u0440\u043e\u043b\u044c &#171;alice&#187;. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044c\u00a0Temporary (\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c) \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u043b\u043e\u0433\u0438\u043d\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/226\/d03\/794\/226d0379452307f1fb454c1326f4da3e.png\" width=\"836\" height=\"462\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/226\/d03\/794\/226d0379452307f1fb454c1326f4da3e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/226\/d03\/794\/226d0379452307f1fb454c1326f4da3e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Save, \u0437\u0430\u0442\u0435\u043c \u0432 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Save password:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/370\/865\/d2b\/370865d2b7d7a515dec8548b8d191198.png\" width=\"788\" height=\"216\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/370\/865\/d2b\/370865d2b7d7a515dec8548b8d191198.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/370\/865\/d2b\/370865d2b7d7a515dec8548b8d191198.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e2d\/cf1\/db9\/e2dcf1db95ad3cf863c52d2bbfceddb8.png\" width=\"1291\" height=\"345\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e2d\/cf1\/db9\/e2dcf1db95ad3cf863c52d2bbfceddb8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e2d\/cf1\/db9\/e2dcf1db95ad3cf863c52d2bbfceddb8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (Client scopes)<\/h3>\n<p>\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (Client scope) \u2014 \u044d\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u0442\u043e\u043a\u0435\u043d\u0430\u0445.\u00a0\u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u043e\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u044b, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u043c\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u043c\u0438.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Client scopes:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/932\/7af\/38b\/9327af38b8ffdfdef638b328b3c97d44.png\" width=\"1874\" height=\"750\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/932\/7af\/38b\/9327af38b8ffdfdef638b328b3c97d44.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/932\/7af\/38b\/9327af38b8ffdfdef638b328b3c97d44.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 Create client scope, \u043e\u0442\u043a\u0440\u043e\u0435\u043a\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0412\u0432\u043e\u0434\u0438\u043c \u0432 \u043f\u043e\u043b\u0435 Name \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 &#171;postgres&#187;, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u0438\u043f Default, \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c Include in token scope \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c Save.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/54f\/0cc\/729\/54f0cc72904af6bddfba55f70daabda5.png\" width=\"1143\" height=\"1093\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/54f\/0cc\/729\/54f0cc72904af6bddfba55f70daabda5.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/54f\/0cc\/729\/54f0cc72904af6bddfba55f70daabda5.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (Client)<\/h3>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u044b (Clients) \u2013 \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u2013 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c\u00a0\u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Clients \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Create client.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ad3\/e58\/337\/ad3e58337414fc5ffc7ec6526ed96f3f.png\" width=\"1891\" height=\"745\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ad3\/e58\/337\/ad3e58337414fc5ffc7ec6526ed96f3f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ad3\/e58\/337\/ad3e58337414fc5ffc7ec6526ed96f3f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435 General settings \u0432 \u043f\u043e\u043b\u0435 Client ID \u0432\u0432\u043e\u0434\u0438\u043c &#171;postgres-client&#187;. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Next.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/77b\/c65\/0d5\/77bc650d5607691254d499d0383c5886.png\" width=\"1394\" height=\"931\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/77b\/c65\/0d5\/77bc650d5607691254d499d0383c5886.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/77b\/c65\/0d5\/77bc650d5607691254d499d0383c5886.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435 Capability config:<\/p>\n<ol>\n<li>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c Client authentification (\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 On);<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c Standard flow, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b Authorization Code Flow \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c OAuth 2.0 Device Authorization Grant;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Next.<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6bb\/be3\/9ba\/6bbbe39bafe011c6fa7d0a8d68de1fc0.png\" width=\"1341\" height=\"919\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/6bb\/be3\/9ba\/6bbbe39bafe011c6fa7d0a8d68de1fc0.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6bb\/be3\/9ba\/6bbbe39bafe011c6fa7d0a8d68de1fc0.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u043e\u043a\u043d\u0435 Login settings \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0438\u0447\u0435\u0433\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Save.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ead\/4f5\/495\/ead4f5495d663dfa0683073fbf433105.png\" width=\"1405\" height=\"649\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ead\/4f5\/495\/ead4f5495d663dfa0683073fbf433105.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ead\/4f5\/495\/ead4f5495d663dfa0683073fbf433105.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0af\/714\/81a\/0af71481a3d0b30cbf26b5e0e481c161.png\" width=\"1423\" height=\"633\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0af\/714\/81a\/0af71481a3d0b30cbf26b5e0e481c161.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0af\/714\/81a\/0af71481a3d0b30cbf26b5e0e481c161.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Client scopes \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 postgres (\u043d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0438\u0437\u0443) \u0438 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0442\u0438\u043f Default;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043b\u044f basic \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0442\u0438\u043f Default.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 scopes \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0435 \u0432\u0430\u0436\u043d\u044b, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u0430\u043a \u0435\u0441\u0442\u044c.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c4d\/6b5\/4b9\/c4d6b54b9912fa127a8026fcba3f0456.png\" width=\"1698\" height=\"1333\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c4d\/6b5\/4b9\/c4d6b54b9912fa127a8026fcba3f0456.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c4d\/6b5\/4b9\/c4d6b54b9912fa127a8026fcba3f0456.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 Credentials \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f Client Secret, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u043f\u0440\u0438 \u043b\u043e\u0433\u0438\u043d\u0435 \u0432 PostgreSQL (\u0441\u043c. \u0434\u0430\u043b\u0435\u0435 \u0432 \u0441\u0435\u043a\u0446\u0438\u0438\u00a0\u00ab<a href=\"#%D0%90%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20psql\" rel=\"noopener noreferrer nofollow\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 psql<\/a>\u00bb)<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/359\/40c\/ad1\/35940cad1e4686f1bbbc18b9ba3f6851.png\" width=\"1561\" height=\"953\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/359\/40c\/ad1\/35940cad1e4686f1bbbc18b9ba3f6851.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/359\/40c\/ad1\/35940cad1e4686f1bbbc18b9ba3f6851.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a class=\"anchor\" name=\"%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20PostgreSQL%20%D0%B0%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%BC%20%D0%B1%D0%B0%D0%B7%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85\" id=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445\"><\/a><\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b OAuth \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 PostgreSQL:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 PostgreSQL;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u0444\u0430\u0439\u043b\u0435 postgresql.conf;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u0444\u0430\u0439\u043b\u0435\u00a0pg_ident.conf \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL. \u0415\u0441\u043b\u0438 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u00a0\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432\u00a0\u0432 \u0444\u0430\u0439\u043b\u0435 pg_hba.conf.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u043e\u043b\u0435\u0439<\/h3>\n<p>\u0420\u043e\u043b\u044c \u2014 \u044d\u0442\u043e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u043b\u0430\u0434\u0435\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438 \u0438\u043c\u0435\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0430. \u0420\u043e\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f,\u00a0\u0433\u0440\u0443\u043f\u043f\u0443\u00a0\u0438\u043b\u0438 \u0438 \u0442\u043e, \u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0440\u043e\u043b\u044c \u0438 \u0434\u0430\u0434\u0438\u043c \u0435\u0439 \u043f\u0440\u0430\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"bash\">CREATE ROLE alice; ALTER ROLE alice WITH LOGIN;<\/code><\/pre>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0444\u0430\u0439\u043b\u0430\u00a0postgresql.conf<\/h3>\n<p>\u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 oauth_validator_libraries \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0438\u043c\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d (\u0441\u043c. \u0441\u0435\u043a\u0446\u0438\u044e \u00ab<a href=\"#%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c<\/a>\u00bb).<\/p>\n<pre><code class=\"bash\">oauth_validator_libraries = 'oauth_validator'<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u043b\u044e\u0431\u044b\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 OAuth; \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 oauth HBA \u0434\u043e\u043b\u0436\u043d\u044b \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430. \u0415\u0441\u043b\u0438 \u0437\u0430\u0434\u0430\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e), \u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u0445 OAuth \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u043e.<\/p>\n<p><a class=\"anchor\" name=\"%D0%A1%D0%BE%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9%20%D0%BC%D0%B5%D0%B6%D0%B4%D1%83%20Keycloak%20%D0%B8%20PostgreSQL\" id=\"\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL\"><\/a><\/p>\n<h3>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL<\/h3>\n<p>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u0447\u0435\u0440\u0435\u0437 \u0444\u0430\u0439\u043b pg_ident.conf \u2014 \u044d\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445;<\/p>\n<\/li>\n<li>\n<p>\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u2013 \u0432 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0435 \u044d\u0442\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0444\u0430\u0439\u043b\u00a0pg_ident.conf<\/h4>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 id \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 Keycloak \u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code># MAPNAME    SYSTEM-USERNAME                           PG-USERNAME oauthmap    \"0fc72b6f-6221-4ed8-a916-069e7a081d14\"     \"alice\"<\/code><\/pre>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u043c\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u2013 ID \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 Keycloak (\u0441\u043c. \u00ab<a href=\"#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/a>\u00bb), \u0432 \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u2013\u00a0\u0438\u043c\u044f \u0440\u043e\u043b\u0438 \u0432 PostgreSQL.<\/p>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440<\/h4>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0438\u0436\u0435 \u0432 \u0441\u0435\u043a\u0446\u0438\u0438 \u00ab<a href=\"#%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c<\/a>\u00bb.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0444\u0430\u0439\u043b\u0430\u00a0pg_hba.conf<\/h3>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0432\u0445\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code># TYPE  DATABASE        USER            ADDRESS                 METHOD local   all             all             oauth issuer=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" scope=\"openid postgres\" map=\"oauthmap\"<\/code><\/pre>\n<p>\u0412 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u043e\u043c \u043f\u043e\u043b\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u044c oauth \u0438 \u0434\u0430\u043b\u0435\u0435 \u0435\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b. \u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 issuer \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c URL \u0434\u0438\u0441\u043a\u0430\u0432\u0435\u0440\u0438-\u0441\u0435\u0440\u0432\u0438\u0441\u0430 &#171;<a href=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" rel=\"noopener noreferrer nofollow\">http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration<\/a>. \u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 Scope \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0443 Keycloak \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL (\u0441\u043c. \u00ab<a href=\"#%D0%A1%D0%BE%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9%20%D0%BC%D0%B5%D0%B6%D0%B4%D1%83%20Keycloak%20%D0%B8%20PostgreSQL\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL<\/a>\u00bb).<\/p>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437\u00a0pg_ident.conf<\/h4>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 map, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c map id \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 pg_ident.conf, \u0443 \u043d\u0430\u0441 \u044d\u0442\u043e &#171;oauthmap&#187;:<\/p>\n<pre><code># TYPE  DATABASE        USER            ADDRESS                 METHOD local   all             all             oauth issuer=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" scope=\"openid postgres\" map=\"oauthmap\"<\/code><\/pre>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437\u00a0\u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440<\/h4>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043c\u0435\u0441\u0442\u0440\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 map \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0437\u0430\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 delegate_ident_mapping=1.<\/p>\n<pre><code># TYPE  DATABASE        USER            ADDRESS                 METHOD local   all             all             oauth issuer=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" scope=\"openid postgres\" delegate_ident_mapping=1<\/code><\/pre>\n<p>\u0423 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 delegate_ident_mapping \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0432\u044b\u0448\u0435, \u0447\u0435\u043c \u0443 map, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u0441 delegate_ident_mapping=1 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u0443\u043a\u0430\u0437\u0430\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 map, \u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d, \u0438 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440.<\/p>\n<p><a class=\"anchor\" name=\"%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC\" id=\"\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c\"><\/a><\/p>\n<h2>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c<\/h2>\n<p>\u041c\u043e\u0434\u0443\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u0438 OAuth \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0441\u0432\u043e\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044f \u043d\u0430\u0431\u043e\u0440 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432. \u0421\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u043e \u043c\u0435\u0440\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0442\u043e\u043a\u0435\u043d\u0430<\/h3>\n<p>\u041f\u0440\u0438 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 pg_ident.conf \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 get_user. \u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435\u00a0\u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c pg_ident.conf. \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u00a0\u0442\u043e\u043a\u0435\u043d\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 pg_hba.conf \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0435 scope \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0432 \u0442\u043e\u043a\u0435\u043d\u0435, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e\u043c \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0432 \u043f\u043e\u043b\u0435 Scope. \u041f\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \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 \u0438\u0437 \u043f\u043e\u043b\u044f sub \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f res-&gt;authn_id.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 validate_token. \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u044b:<\/p>\n<p>1. \u0420\u0430\u0437\u0431\u043e\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430: \u0438\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0442\u043e\u043a\u0435\u043d\u0430 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e (payload). \u0415\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0438\u043c\u0435\u0435\u0442 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438\u043b\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u043e, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u0443\u0434\u0430\u0447\u0435\u0439.<\/p>\n<p>2. \u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 JWT-\u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u043e\u043b\u0435\u0439 sub \u0438 scope. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043e\u0431\u0430 \u043f\u043e\u043b\u044f:<\/p>\n<ul>\n<li>\n<p>sub (Subject) &#8212; \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<\/p>\n<\/li>\n<li>\n<p>scope \u2013 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 (Scopes), \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u043c, \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u0435\u043b\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u043b\u044e\u0431\u043e\u0435 \u0438\u0437 \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u043e\u0439.<\/p>\n<p>3. \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 sub \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u044e res-&gt;authn_id, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 PostgreSQL \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u043b\u044f \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. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0442\u0435\u043c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 \u0432 pg_ident.conf \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u043e\u043b\u0438 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>4. \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 (scopes). \u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u043c, \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u0442\u0435\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0432 pg_hba.conf (\u0438\u0437 oauth_scope). \u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0432 \u0442\u043e\u043a\u0435\u043d\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439.<\/p>\n<p>5. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u0424\u043b\u0430\u0433 res-&gt;authorized \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 true, \u0435\u0441\u043b\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u0438\u043d\u0430\u0447\u0435 \u2013 false.<\/p>\n<p>6. \u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 sub \u0437\u0430\u0442\u0435\u043c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f (\u0432\u043d\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f) \u0441 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 \u0432 pg_ident.conf \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u043e\u043b\u0438 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e\u00a0 \u043d\u0430\u0448\u0435\u0433\u043e \u0443\u0447\u0435\u0431\u043d\u043e\u0433\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430\u00a0(\u0435\u0433\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u043b\u043e\u0436\u0435\u043d\u044b \u043d\u0430\u00a0<a href=\"https:\/\/github.com\/TantorLabs\/oauth_validator\" rel=\"noopener noreferrer nofollow\">GitHub<\/a>). \u0421\u043f\u0435\u0440\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 oauth_validator, \u0430 \u0432 \u043d\u0435\u0439 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b\u00a0<strong>oauth_validator.c<\/strong><\/p>\n<p><strong>oauth_validator.c<\/strong>  <\/p>\n<pre><code class=\"cpp\">#include &lt;string.h&gt;  #include \"postgres.h\"  #include \"token_utils.h\"  #include \"fmgr.h\" #include \"libpq\/oauth.h\" #include \"miscadmin.h\" #include \"nodes\/pg_list.h\" #include \"utils\/builtins.h\"  PG_MODULE_MAGIC;  \/*  * \u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043c\u043e\u0434\u0443\u043b\u044f.  *\/ static void validator_startup(ValidatorModuleState *state); static void validator_shutdown(ValidatorModuleState *state); static bool validate_token(const ValidatorModuleState *state,                            const char *token,                            const char *role,                            ValidatorModuleResult *result);  \/*  * \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 OAuth.  * PostgreSQL \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u043c\u043e\u0434\u0443\u043b\u044f.  *\/ static const OAuthValidatorCallbacks validator_callbacks = {     PG_OAUTH_VALIDATOR_MAGIC, \/* \u041c\u0430\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0435\u0440\u0441\u0438\u0438 API *\/      .startup_cb = validator_startup,   \/* \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 *\/     .shutdown_cb = validator_shutdown, \/* \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 *\/     .validate_cb = validate_token      \/* \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 *\/ };  \/*  * \u0422\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 OAuth.  * PostgreSQL \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043c\u043e\u0434\u0443\u043b\u044f.  *\/ const OAuthValidatorCallbacks * _PG_oauth_validator_module_init(void) {     return &amp;validator_callbacks; }  \/*  * \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430.  * \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u043e\u0434\u0443\u043b\u044f.  *\/ static void validator_startup(ValidatorModuleState *state) {     \/*      * \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043b\u0438 \u0432\u0435\u0440\u0441\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441 \u0442\u043e\u0439, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u044b\u043b \u0441\u043e\u0431\u0440\u0430\u043d \u043c\u043e\u0434\u0443\u043b\u044c.      *\/     if (state-&gt;sversion != PG_VERSION_NUM)         elog(ERROR, \"oauth_validator: \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430: sversion=%d\", state-&gt;sversion); }  \/*  * \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430.  * \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0435 \u043c\u043e\u0434\u0443\u043b\u044f \u0438\u043b\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430.  *\/ static void validator_shutdown(ValidatorModuleState *state) {     \/* \u041f\u043e\u043a\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c, \u043d\u043e \u0441\u044e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438. *\/ }  \/*  * \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 OAuth.  *  * \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:  * - state: \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 (\u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0442.\u043f.);  * - token: \u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u0442\u043e\u043a\u0435\u043d\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c;  * - role: \u0438\u043c\u044f \u0440\u043e\u043b\u0438 PostgreSQL, \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442;  * - res: \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438.  *  * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true, \u0435\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d, \u0438\u043d\u0430\u0447\u0435 false.  *\/ static bool validate_token(const ValidatorModuleState *state,                const char *token, const char *role,                ValidatorModuleResult *res) {     char *sub = NULL;               \/* \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \"sub\" \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430 (\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) *\/     char *scope = NULL;             \/* \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \"scope\" \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430 (\u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430) *\/     const char *token_payload = NULL; \/* \u041f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 (payload) \u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 JSON *\/     List *granted_scopes = NIL;     \/* \u0421\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430 *\/     List *required_scopes = NIL;    \/* \u0421\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 HBA-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 *\/     bool matched = false;           \/* \u0424\u043b\u0430\u0433 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 *\/      \/* \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 *\/     res-&gt;authn_id = NULL;   \/* \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (sub) *\/     res-&gt;authorized = false; \/* \u0424\u043b\u0430\u0433 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 *\/      \/* \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430 *\/     token_payload = parse_token_payload(token);     if (token_payload == NULL)     {         elog(LOG, \"\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d: \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 payload: %s\", token);         return false;     }      \/* \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u043f\u043e\u043b\u044f 'sub' \u0438 'scope' \u0438\u0437 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 *\/     extract_sub_scope_fields(token_payload, &amp;sub, &amp;scope);     if (!sub || !scope)     {         elog(LOG, \"\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d: \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043f\u043e\u043b\u044f sub \u0438\/\u0438\u043b\u0438 scope: %s\", token);         return false;     }      \/* \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \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 (sub) \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 *\/     res-&gt;authn_id = pstrdup(sub);      \/* \u0420\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b *\/     granted_scopes = split_scopes(scope);      \/* \u0420\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 HBA-\u0444\u0430\u0439\u043b\u0430 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b *\/     required_scopes = split_scopes(MyProcPort-&gt;hba-&gt;oauth_scope);      if (!granted_scopes || !required_scopes)         return false;      \/* \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 \u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 *\/     matched = check_scopes(granted_scopes, required_scopes);      \/* \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 *\/     res-&gt;authorized = matched;      return true; }  <\/code><\/pre>\n<p><strong>token_utils.c\/.h<\/strong>\u00a0\u2013 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u0443\u0442\u0438\u043b\u0438\u0442\u044b<\/p>\n<p><strong>token_utils.h<\/strong>  <\/p>\n<pre><code class=\"cpp\">#ifndef TOKEN_UTILS_H #define TOKEN_UTILS_H  #include &lt;stdbool.h&gt;  #include \"common\/jsonapi.h\" #include \"nodes\/pg_list.h\"  const char* parse_token_payload(const char *token); void extract_sub_scope_fields(const char *json, char **sub_field, char **scope_field); const char *decode_base64(const char *b64); char *base64url_to_base64(const char *b64url); List *split_scopes(const char *raw); bool check_scopes(List *granted, List *required);  #endif<\/code><\/pre>\n<p><strong>token_utils.c<\/strong>  <\/p>\n<pre><code class=\"cpp\">#include \"PostgreSQL.h\"  #include \"token_utils.h\"  #include \"common\/base64.h\" #include \"mb\/pg_wchar.h\"  #define SUB_FIELD   0   \/* \u0418\u043d\u0434\u0435\u043a\u0441 \u0434\u043b\u044f \u043f\u043e\u043b\u044f 'sub' *\/ #define SCOPE_FIELD 1   \/* \u0418\u043d\u0434\u0435\u043a\u0441 \u0434\u043b\u044f \u043f\u043e\u043b\u044f 'scope' *\/  \/*  * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u043b\u044f JSON-\u043e\u0431\u044a\u0435\u043a\u0442\u0430.  * \u041e\u0442\u043c\u0435\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u043f\u043e\u043b\u0435 'sub' \u0438 'scope', \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u044d\u0442\u0430\u043f\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.  *\/ static JsonParseErrorType token_field_start(void *state, char *fname, bool isnull) {     char **fields = (char **) state;      if (strcmp(fname, \"sub\") == 0)         fields[SUB_FIELD] = (char *) 1;  \/* \u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u043f\u043e\u043b\u0435 \u2014 \u044d\u0442\u043e 'sub' *\/     else if (strcmp(fname, \"scope\") == 0)         fields[SCOPE_FIELD] = (char *) 1; \/* \u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u043f\u043e\u043b\u0435 \u2014 \u044d\u0442\u043e 'scope' *\/      return JSON_SUCCESS; }  \/*  * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f JSON.  * \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 'sub' \u0438\u043b\u0438 'scope', \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043e \u0440\u0430\u043d\u0435\u0435.  *\/ static JsonParseErrorType token_scalar(void *state, char *token, JsonTokenType tokentype) {     char **fields = (char **) state;      if (fields[SUB_FIELD] == (char *) 1)         fields[SUB_FIELD] = pstrdup(token);  \/* \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 'sub' *\/     else if (fields[SCOPE_FIELD] == (char *) 1)         fields[SCOPE_FIELD] = pstrdup(token); \/* \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 'scope' *\/      return JSON_SUCCESS; }  \/*  * \u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0439 'sub' \u0438 'scope' \u0438\u0437 JSON \u0441\u0442\u0440\u043e\u043a\u0438.  *  * \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:  *  - json: \u0441\u0442\u0440\u043e\u043a\u0430 JSON  *  - sub_field: \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f 'sub'  *  - scope_field: \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f 'scope'  *\/ void extract_sub_scope_fields(const char *json, char **sub_field, char **scope_field) {     JsonLexContext lex;     JsonSemAction sem;      char **fields = palloc0(sizeof(char *) * 2); \/* \u0412\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c \u0434\u043b\u044f 2 \u0441\u0442\u0440\u043e\u043a ('sub', 'scope') *\/      *sub_field = NULL;     *scope_field = NULL;      \/* \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043e\u0440\u0430 JSON *\/     makeJsonLexContextCstringLen(&amp;lex, json, strlen(json), GetDatabaseEncoding(), true);      \/* \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 JSON-\u043f\u0430\u0440\u0441\u0435\u0440\u0430 *\/     memset(&amp;sem, 0, sizeof(sem));     sem.semstate = (void *) fields;     sem.object_field_start = token_field_start;     sem.scalar = token_scalar;      \/* \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0430\u0440\u0441\u0438\u043d\u0433 JSON *\/     pg_parse_json(&amp;lex, &amp;sem);      \/* \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f *\/     *sub_field = fields[SUB_FIELD];     *scope_field = fields[SCOPE_FIELD]; }  \/*  * \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 payload \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430 JWT.  * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0441\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 payload \u0432 \u0432\u0438\u0434\u0435 JSON.  *\/ const char* parse_token_payload(const char *token) {     char *dot1 = NULL;     char *dot2 = NULL;     int payload_len = 0;     char *payload_b64url = NULL;     char *b64 = NULL;      if(!token)         return NULL;      \/* \u0418\u0449\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u0438 \u0432\u0442\u043e\u0440\u0443\u044e \u0442\u043e\u0447\u043a\u0438 \u0432 JWT (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u0438 header.payload.signature) *\/     dot1 = strchr(token, '.');     dot2 = dot1 ? strchr(dot1 + 1, '.') : NULL;      if (!dot1 || !dot2)     {         elog(LOG, \"\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0442\u043e\u043a\u0435\u043d\u0430, \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0432\u0435 \u0442\u043e\u0447\u043a\u0438: %s\", token);         return NULL;     }      \/* \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 payload \u043c\u0435\u0436\u0434\u0443 \u0442\u043e\u0447\u043a\u0430\u043c\u0438 *\/     payload_len = dot2 - (dot1 + 1);     payload_b64url = pnstrdup(dot1 + 1, payload_len);      \/* \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c base64url \u0432 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 base64 *\/     b64 = base64url_to_base64(payload_b64url);      \/* \u0414\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c base64 \u0432 JSON \u0441\u0442\u0440\u043e\u043a\u0443 *\/     return decode_base64(b64); }  \/*  * \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 base64url \u0432 \u0444\u043e\u0440\u043c\u0430\u0442 base64.  * \u0417\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u0438\u043c\u0432\u043e\u043b\u044b '-' \u043d\u0430 '+', '_' \u043d\u0430 '\/' \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0430\u0434\u0434\u0438\u043d\u0433 '=' \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.  *\/ char * base64url_to_base64(const char *b64url) {     int len = strlen(b64url);     int pad = (4 - (len % 4)) % 4; \/* \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 '=' \u0434\u043b\u044f \u043f\u0430\u0434\u0434\u0438\u043d\u0433\u0430 *\/     char *b64 = palloc(len + pad + 1);      for (int i = 0; i &lt; len; i++)     {         if (b64url[i] == '-')             b64[i] = '+';         else if (b64url[i] == '_')             b64[i] = '\/';         else             b64[i] = b64url[i];     }      \/* \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u0434\u0434\u0438\u043d\u0433 '=' *\/     for (int i = 0; i &lt; pad; i++)         b64[len + i] = '=';      b64[len + pad] = '\\0';     return b64; }  \/*  * \u0414\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 base64 \u0432 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443.  * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0441\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u043b\u0438 NULL \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0448\u0438\u0431\u043a\u0438.  *\/ const char * decode_base64(const char *b64) {     int encoded_len = strlen(b64);     int max_decoded_len = pg_b64_dec_len(encoded_len); \/* \u0412\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0434\u043b\u0438\u043d\u0443 \u0431\u0443\u0444\u0435\u0440\u0430 *\/     char *decoded = palloc(max_decoded_len + 1);     int decoded_len = pg_b64_decode(b64, encoded_len, decoded, max_decoded_len);      if (decoded_len &lt;= 0)     {         elog(LOG, \"\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0442\u043e\u043a\u0435\u043d\u0430: \u043e\u0448\u0438\u0431\u043a\u0430 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f base64\");         return NULL;     }      decoded[decoded_len] = '\\0';     return decoded; }  \/*  * \u0420\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u043f\u0440\u043e\u0431\u0435\u043b\u0430\u043c\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043f\u0438\u0441\u043e\u043a scope \u0438\u0437 \u0442\u043e\u043a\u0435\u043d\u0430) \u043d\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0440\u043e\u043a List.  *\/ List * split_scopes(const char *raw) {     List *result = NIL;     char *str = pstrdup(raw);  \/* \u0414\u0435\u043b\u0430\u0435\u043c \u043a\u043e\u043f\u0438\u044e \u0441\u0442\u0440\u043e\u043a\u0438, \u0442\u0430\u043a \u043a\u0430\u043a strtok \u0435\u0451 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442 *\/     char *tok = strtok(str, \" \");     while (tok)     {         result = lappend(result, pstrdup(tok));         tok = strtok(NULL, \" \");     }     return result; }  \/*  * \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u043a \u0434\u043b\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u043f\u0438\u0441\u043a\u0430.  *\/ static int list_string_cmp(const ListCell *a, const ListCell *b) {     const char *sa = (const char *) lfirst(a);     const char *sb = (const char *) lfirst(b);     return strcmp(sa, sb); }  \/*  * \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u043b\u0438 \u0432\u0441\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 (required) \u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 (granted).  * \u0421\u043f\u0438\u0441\u043a\u0438 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f.  *  * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 required scopes \u043d\u0430\u0439\u0434\u0435\u043d\u044b \u0432 granted scopes.  *\/ bool check_scopes(List *granted, List *required) {     ListCell *gcell;     ListCell *rcell;      \/* \u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f *\/     list_sort(granted, list_string_cmp);     list_sort(required, list_string_cmp);      gcell = list_head(granted);     rcell = list_head(required);      while (rcell != NULL &amp;&amp; gcell != NULL)     {         char *r = (char *) lfirst(rcell);         char *g = (char *) lfirst(gcell);         int cmp = strcmp(r, g);          if (cmp == 0)         {             \/* \u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u2014 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 required *\/             rcell = lnext(required, rcell);             gcell = lnext(granted, gcell);         }         else if (cmp &gt; 0)         {             \/* granted \"\u043e\u0442\u0441\u0442\u0430\u0451\u0442\" \u2014 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 granted *\/             gcell = lnext(granted, gcell);         }         else         {             \/* required \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0432 granted \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c false *\/             return false;         }     }      \/* \u0415\u0441\u043b\u0438 \u043d\u0435 \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b required \u0431\u044b\u043b\u0438 \u043d\u0430\u0439\u0434\u0435\u043d\u044b \u2014 \u043e\u0448\u0438\u0431\u043a\u0430 *\/     if (rcell != NULL)         return false;      return true; }<\/code><\/pre>\n<p><strong>Makefile<\/strong> <\/p>\n<pre><code class=\"bash\"># contrib\/oauth_validator\/Makefile  PGFILEDESC = \"oauth_validator - OAuth validator\" MODULE_big = oauth_validator  OBJS = \\ $(WIN32RES) \\ oauth_validator.o \\ token_utils.o  PG_CPPFLAGS += -I$(top_srcdir)\/src\/common PG_CPPFLAGS += -I$(libpq_srcdir)  PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS)<\/code><\/pre>\n<h3>\u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b<\/h3>\n<h4>\u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 startup_cb<\/h4>\n<p>\u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 startup_cb \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043c\u043e\u0434\u0443\u043b\u044f. \u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. \u0415\u0441\u043b\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0435 state-&gt;private_data \u0434\u043b\u044f \u0435\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"cpp\">typedef\u00a0void\u00a0(*ValidatorStartupCB) (ValidatorModuleState *state);  ValidatorStartupCB startup_cb;<\/code><\/pre>\n<h4>\u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 validate_cb<\/h4>\n<p>\u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 validate_cb \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0439\u0442\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e OAuth. \u041b\u044e\u0431\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0435 \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u0430\u0445, \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0432 state-&gt;private_data.<\/p>\n<pre><code class=\"cpp\">typedef bool (*ValidatorValidateCB) (const ValidatorModuleState *state,                                      const char *token, const char *role,                                      ValidatorModuleResult *result); ValidatorValidateCB validate_cb;<\/code><\/pre>\n<p>\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 token \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d-\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438. PostgreSQL \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u043b\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438 \u0442\u043e\u043a\u0435\u043d \u0431\u044b\u043b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d, \u043d\u043e \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0435 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043b\u043e\u0441\u044c. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 role\u00a0\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u00a0\u0440\u043e\u043b\u044c,\u00a0\u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u043b \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. \u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0434\u0430\u0442\u044c \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">typedef struct ValidatorModuleResult {     bool        authorized;     char       *authn_id; } ValidatorModuleResult;<\/code><\/pre>\n<p>\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442 \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 result-&gt;authorized \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 true. \u0414\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 \u043f\u043e\u0434 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (\u0442.\u0435. \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u043e\u043a\u0435\u043d\u0430) \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0430 \u043f\u0430\u043c\u044f\u0442\u044c (\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 palloc), \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0435\u0433\u0438\u043e\u043d \u043f\u0430\u043c\u044f\u0442\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d \u043f\u043e\u043b\u044e result-&gt;authn_id. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 result-&gt;authn_id \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 NULL, \u0435\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u0435\u043d, \u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u043d\u0438\u043c \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 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d.<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 false \u2013 \u0432\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0442\u043e\u043a\u0435\u043d\u0430, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043f\u0440\u0430\u0432 \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u0438, \u0442\u043e\u0433\u0434\u0430 \u043b\u044e\u0431\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 result \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c true.<\/p>\n<p>\u041f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0438\u0437 validate_cb \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 HBA. \u041e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f result-&gt;authn_id \u0434\u043e\u043b\u0436\u043d\u043e \u0442\u043e\u0447\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0440\u043e\u043b\u0438, \u043f\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 (\u044d\u0442\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f). \u041d\u043e \u043f\u0440\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0443 HBA \u0441 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u043c delegate_ident_mapping PostgreSQL \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f result-&gt;authn_id; \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u044f\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0433 \u0432\u043e\u0439\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043e\u0434 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0440\u043e\u043b\u044c\u044e.<\/p>\n<h4>\u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 shutdown_cb<\/h4>\n<p>\u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 shutdown_cb \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c. \u0415\u0441\u043b\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0438\u043c\u0435\u0435\u0442 \u043a\u0430\u043a\u043e\u0435-\u043b\u0438\u0431\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u044d\u0442\u043e\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u0435\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0443\u0442\u0435\u0447\u043a\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432.<\/p>\n<pre><code class=\"cpp\">typedef void (*ValidatorShutdownCB) (ValidatorModuleState *state); ValidatorShutdownCB shutdown_cb;<\/code><\/pre>\n<p><a class=\"anchor\" name=\"%D0%9F%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%20%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8\" id=\"\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\"><\/a><\/p>\n<h2>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/h2>\n<h4>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 PostgreSQL \u0438 \u043a\u0430\u043a\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442, \u0432 postgresql.conf \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"bash\">log_connections = on<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043b\u043e\u0433\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0434\u0430\u043b\u0435\u0435, \u0432 \u043d\u0438\u0445 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0440\u043e\u043a \u0431\u0443\u0434\u0443\u0442 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u044b, \u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0435\u0444\u0438\u043a\u0441 &#171;&gt;&#187; \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 Keycloak<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0435\u0444\u0438\u043a\u0441 &#171;&lt;&#187; \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 Keycloak<\/p>\n<\/li>\n<\/ul>\n<h4>discovery<\/h4>\n<pre><code class=\"bash\">[libcurl] *   Trying 192.168.0.156:8080... [libcurl] * Connected to 192.168.0.156 (192.168.0.156) port 8080 (#0) [libcurl] &gt; GET \/realms\/postgres-realm\/.well-known\/openid-configuration HTTP\/1.1 [libcurl] &gt; Host: 192.168.0.156:8080 [libcurl] &gt;  [libcurl] &lt; HTTP\/1.1 200 OK [libcurl] &lt; content-length: 6638 [libcurl] &lt; Cache-Control: no-cache, must-revalidate, no-transform, no-store [libcurl] &lt; Content-Type: application\/json;charset=UTF-8 [libcurl] &lt; Referrer-Policy: no-referrer [libcurl] &lt; Strict-Transport-Security: max-age=31536000; includeSubDomains [libcurl] &lt; X-Content-Type-Options: nosniff [libcurl] &lt; X-Frame-Options: SAMEORIGIN [libcurl] &lt;  [libcurl] &lt; {\"issuer\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\",\"authorization_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/auth\",\"token_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/token\",\"introspection_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/token\/introspect\",\"userinfo_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/userinfo\",\"end_session_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/logout\",\"frontchannel_logout_session_supported\":true,\"frontchannel_logout_supported\":true,\"jwks_uri\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/certs\",\"check_session_iframe\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/login-status-iframe.html\",\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"implicit\",\"password\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\",\"urn:ietf:params:oauth:grant-type:uma-ticket\",\"urn:openid:params:grant-type:ciba\"],\"acr_values_supported\":[\"0\",\"1\"],\"response_types_supported\":[\"code\",\"none\",\"id_token\",\"token\",\"id_token token\",\"code id_token\",\"code token\",\"code id_token token\"],\"subject_types_supported\":[\"public\",\"pairwise\"],\"prompt_values_supported\":[\"none\",\"login\",\"consent\"],\"id_token_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"],\"id_token_encryption_alg_values_supported\":[\"ECDH-ES+A256KW\",\"ECDH-ES+A192KW\",\"ECDH-ES+A128KW\",\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\",\"ECDH-ES\"],\"id_token_encryption_enc_values_supported\":[\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\"],\"userinfo_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\",\"none\"],\"userinfo_encryption_alg_values_supported\":[\"ECDH-ES+A256KW\",\"ECDH-ES+A192KW\",\"ECDH-ES+A128KW\",\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\",\"ECDH-ES\"],\"userinfo_encryption_enc_values_supported\":[\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\"],\"request_object_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\",\"none\"],\"request_object_encryption_alg_values_supported\":[\"ECDH-ES+A256KW\",\"ECDH-ES+A192KW\",\"ECDH-ES+A128KW\",\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\",\"ECDH-ES\"],\"request_object_encryption_enc_values_supported\":[\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\"],\"response_modes_supported\":[\"query\",\"fragment\",\"form_post\",\"query.jwt\",\"fragment.jwt\",\"form_post.jwt\",\"jwt\"],\"registration_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/clients-registrations\/openid-connect\",\"token_endpoint_auth_methods_supported\":[\"private_key_jwt\",\"client_secret_basic\",\"client_secret_post\",\"tls_client_auth\",\"client_secret_jwt\"],\"token_endpoint_auth_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"],\"introspection_endpoint_auth_methods_supported\":[\"private_key_jwt\",\"client_secret_basic\",\"client_secret_post\",\"tls_client_auth\",\"client_secret_jwt\"],\"introspection_endpoint_auth_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"],\"authorization_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"],\"authorization_encryption_alg_values_supported\":[\"ECDH-ES+A256KW\",\"ECDH-ES+A192KW\",\"ECDH-ES+A128KW\",\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\",\"ECDH-ES\"],\"authorization_encryption_enc_values_supported\":[\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\"],\"claims_supported\":[\"aud\",\"sub\",\"iss\",\"auth_time\",\"name\",\"given_name\",\"family_name\",\"preferred_username\",\"email\",\"acr\"],\"claim_types_supported\":[\"normal\"],\"claims_parameter_supported\":true,\"scopes_supported\":[\"openid\",\"offline_access\",\"organization\",\"service_account\",\"postgres\",\"address\",\"phone\",\"acr\",\"profile\",\"microprofile-jwt\",\"web-origins\",\"roles\",\"basic\",\"email\"],\"request_parameter_supported\":true,\"request_uri_parameter_supported\":true,\"require_request_uri_registration\":true,\"code_challenge_methods_supported\":[\"plain\",\"S256\"],\"tls_client_certificate_bound_access_tokens\":true,\"revocation_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/revoke\",\"revocation_endpoint_auth_methods_supported\":[\"private_key_jwt\",\"client_secret_basic\",\"client_secret_post\",\"tls_client_auth\",\"client_secret_jwt\"],\"revocation_endpoint_auth_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"],\"backchannel_logout_supported\":true,\"backchannel_logout_session_supported\":true,\"device_authorization_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/auth\/device\",\"backchannel_token_delivery_modes_supported\":[\"poll\",\"ping\"],\"backchannel_authentication_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/ext\/ciba\/auth\",\"backchannel_authentication_request_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"ES256\",\"RS256\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"],\"require_pushed_authorization_requests\":false,\"pushed_authorization_request_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/ext\/par\/request\",\"mtls_endpoint_aliases\":{\"token_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/token\",\"revocation_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/revoke\",\"introspection_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/token\/introspect\",\"device_authorization_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/auth\/device\",\"registration_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/clients-registrations\/openid-connect\",\"userinfo_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/userinfo\",\"pushed_authorization_request_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/ext\/par\/request\",\"backchannel_authentication_endpoint\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/protocol\/openid-connect\/ext\/ciba\/auth\"},\"authorization_response_iss_parameter_supported\":true}  <\/code><\/pre>\n<h4>auth device<\/h4>\n<pre><code class=\"bash\">[libcurl] * Connection #0 to host 192.168.0.156 left intact [libcurl] * Found bundle for host: 0x6124961fd400 [serially] [libcurl] * Can not multiplex, even if we wanted to [libcurl] * Re-using existing connection #0 with host 192.168.0.156 [libcurl] * Server auth using Basic with user 'postgres-client' [libcurl] &gt; POST \/realms\/postgres-realm\/protocol\/openid-connect\/auth\/device HTTP\/1.1 [libcurl] &gt; Host: 192.168.0.156:8080 [libcurl] &gt; Authorization: Basic cG9zdGdyZXMtY2xpZW50OmZTY1hYcDFUcFNQY3BVaEZLcWk0eDk4alZ5NTR1Y1RC [libcurl] &gt; Content-Length: 47 [libcurl] &gt; Content-Type: application\/x-www-form-urlencoded [libcurl] &gt;  [libcurl] &gt; scope=openid+postgres&amp;client_id=postgres-client [libcurl] &lt; HTTP\/1.1 200 OK [libcurl] &lt; Cache-Control: no-store, must-revalidate, max-age=0 [libcurl] &lt; content-length: 296 [libcurl] &lt; Content-Type: application\/json [libcurl] &lt; Referrer-Policy: no-referrer [libcurl] &lt; Strict-Transport-Security: max-age=31536000; includeSubDomains [libcurl] &lt; X-Content-Type-Options: nosniff [libcurl] &lt; X-Frame-Options: SAMEORIGIN [libcurl] &lt;  [libcurl] &lt; {\"device_code\":\"tgElqUogevqjEkZy6-Z1i209pgoKW9_CT0t9wwNjafY\",\"user_code\":\"WXAI-ZNVY\",\"verification_uri\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/device\",\"verification_uri_complete\":\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/device?user_code=WXAI-ZNVY\",\"expires_in\":600,\"interval\":5} <\/code><\/pre>\n<h4>token<\/h4>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<pre><code class=\"bash\">[libcurl] * Connection #0 to host 192.168.0.156 left intact [libcurl] * Found bundle for host: 0x6124961fd400 [serially] [libcurl] * Can not multiplex, even if we wanted to [libcurl] * Re-using existing connection #0 with host 192.168.0.156 [libcurl] * Server auth using Basic with user 'postgres-client' [libcurl] &gt; POST \/realms\/postgres-realm\/protocol\/openid-connect\/token HTTP\/1.1 [libcurl] &gt; Host: 192.168.0.156:8080 [libcurl] &gt; Authorization: Basic cG9zdGdyZXMtY2xpZW50OmZTY1hYcDFUcFNQY3BVaEZLcWk0eDk4alZ5NTR1Y1RC [libcurl] &gt; Content-Length: 147 [libcurl] &gt; Content-Type: application\/x-www-form-urlencoded [libcurl] &gt;  [libcurl] &gt; device_code=tgElqUogevqjEkZy6-Z1i209pgoKW9_CT0t9wwNjafY&amp;grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&amp;client_id=postgres-client [libcurl] &lt; HTTP\/1.1 400 Bad Request [libcurl] &lt; Cache-Control: no-store [libcurl] &lt; Pragma: no-cache [libcurl] &lt; content-length: 98 [libcurl] &lt; Content-Type: application\/json [libcurl] &lt; Referrer-Policy: no-referrer [libcurl] &lt; Strict-Transport-Security: max-age=31536000; includeSubDomains [libcurl] &lt; X-Content-Type-Options: nosniff [libcurl] &lt; X-Frame-Options: SAMEORIGIN [libcurl] &lt;  [libcurl] &lt; {\"error\":\"authorization_pending\",\"error_description\":\"The authorization request is still pending\"}  <\/code><\/pre>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0434\u043e\u0431\u0440\u0435\u043d:<\/p>\n<pre><code class=\"bash\">[libcurl] * Connection #0 to host 192.168.0.156 left intact [libcurl] * Found bundle for host: 0x6124961fd400 [serially] [libcurl] * Can not multiplex, even if we wanted to [libcurl] * Re-using existing connection #0 with host 192.168.0.156 [libcurl] * Server auth using Basic with user 'postgres-client' [libcurl] &gt; POST \/realms\/postgres-realm\/protocol\/openid-connect\/token HTTP\/1.1 [libcurl] &gt; Host: 192.168.0.156:8080 [libcurl] &gt; Authorization: Basic cG9zdGdyZXMtY2xpZW50OmZTY1hYcDFUcFNQY3BVaEZLcWk0eDk4alZ5NTR1Y1RC [libcurl] &gt; Content-Length: 147 [libcurl] &gt; Content-Type: application\/x-www-form-urlencoded [libcurl] &gt;  [libcurl] &gt; device_code=tgElqUogevqjEkZy6-Z1i209pgoKW9_CT0t9wwNjafY&amp;grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&amp;client_id=postgres-client [libcurl] &lt; HTTP\/1.1 200 OK [libcurl] &lt; Cache-Control: no-store [libcurl] &lt; Pragma: no-cache [libcurl] &lt; content-length: 3307 [libcurl] &lt; Content-Type: application\/json [libcurl] &lt; Referrer-Policy: no-referrer [libcurl] &lt; Strict-Transport-Security: max-age=31536000; includeSubDomains [libcurl] &lt; X-Content-Type-Options: nosniff [libcurl] &lt; X-Frame-Options: SAMEORIGIN [libcurl] &lt;  [libcurl] &lt; {\"access_token\":\"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwb1RQSV85LXVIQWJ5Q0t3M2luTm5MTW5hU21hc05nWS1OaDVkTzJ4X0lNIn0.eyJleHAiOjE3NDYwMzEyNTMsImlhdCI6MTc0NjAzMDk1MywiYXV0aF90aW1lIjoxNzQ2MDMwOTUyLCJqdGkiOiJvbnJ0ZGc6MWU3MmRlNGUtNTRhYi00OTZjLWIxYWYtY2FhYmRiYzJlYzExIiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMC4xNTY6ODA4MC9yZWFsbXMvcG9zdGdyZXMtcmVhbG0iLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMGZjNzJiNmYtNjIyMS00ZWQ4LWE5MTYtMDY5ZTdhMDgxZDE0IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicG9zdGdyZXMtY2xpZW50Iiwic2lkIjoiNjRlMDUzMTMtM2UyMi00MmNjLWE0YmItOTAxODU2YTFhYjMzIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsImRlZmF1bHQtcm9sZXMtcG9zdGdyZXMtcmVhbG0iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgcG9zdGdyZXMiLCJuYW1lIjoiYWxpY2UgcG9zdGdyZXMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhbGljZSIsImdpdmVuX25hbWUiOiJhbGljZSIsImZhbWlseV9uYW1lIjoicG9zdGdyZXMifQ.RXMszI-snIdrXyyTw74U8QXQeDG3zpfV4OvxYuJQvsb86eauXkKHAH35GfEm3XvQbtmpdSdfs1S4i11d69dUjpVTgPpzx6G7IXCXj2NTowzZuyuvdnLxPi1aXdxXqOKNSLSj5PXhGIaZhWsn2sR8dAJ0jjWTUO_lh8qJuJYaDcFulWn_flHVGQYzMZ5PTneRadg8h_1dWp4HSr6yC74NmF94dnOBmytivM4a__Wcq6TkZ3KLn_gafqnn72HpWY0WRwyZdQuzc5o8mE3UUAoKukxMnwDG7Yhxif2YFb_a5aCloMbL9aDghbMypahl3MiJHHx3j50FavSRm0FJa3zK9w\",\"expires_in\":300,\"refresh_expires_in\":1800,\"refresh_token\":\"eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjOGNiNjY3Ni00OTAxLTRmNjItOTI0OS1kMzY2MWI5Mjg3OTIifQ.eyJleHAiOjE3NDYwMzI3NTMsImlhdCI6MTc0NjAzMDk1MywianRpIjoiZTJkNzkzODUtNjBhZS00MTIwLWIwODAtNjVmYWU4ZmNhYzIzIiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMC4xNTY6ODA4MC9yZWFsbXMvcG9zdGdyZXMtcmVhbG0iLCJhdWQiOiJodHRwOi8vMTkyLjE2OC4wLjE1Njo4MDgwL3JlYWxtcy9wb3N0Z3Jlcy1yZWFsbSIsInN1YiI6IjBmYzcyYjZmLTYyMjEtNGVkOC1hOTE2LTA2OWU3YTA4MWQxNCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJwb3N0Z3Jlcy1jbGllbnQiLCJzaWQiOiI2NGUwNTMxMy0zZTIyLTQyY2MtYTRiYi05MDE4NTZhMWFiMzMiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIHdlYi1vcmlnaW5zIHBvc3RncmVzIHJvbGVzIGJhc2ljIn0.43pRSq4PBO7ZY86jt8dIL7xZJylntY_CZXllcRfwfh41IRCOft6iqIWdJQp7TJv_JIDI-_-QeOSf1EC_wzABNg\",\"token_type\":\"Bearer\",\"id_token\":\"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwb1RQSV85LXVIQWJ5Q0t3M2luTm5MTW5hU21hc05nWS1OaDVkTzJ4X0lNIn0.eyJleHAiOjE3NDYwMzEyNTMsImlhdCI6MTc0NjAzMDk1MywiYXV0aF90aW1lIjoxNzQ2MDMwOTUyLCJqdGkiOiIzNWM3ZDAyZC05OGFjLTQzMTgtOTg3NC0zYzY0Mjg5NjFhMjgiLCJpc3MiOiJodHRwOi8vMTkyLjE2OC4wLjE1Njo4MDgwL3JlYWxtcy9wb3N0Z3Jlcy1yZWFsbSIsImF1ZCI6InBvc3RncmVzLWNsaWVudCIsInN1YiI6IjBmYzcyYjZmLTYyMjEtNGVkOC1hOTE2LTA2OWU3YTA4MWQxNCIsInR5cCI6IklEIiwiYXpwIjoicG9zdGdyZXMtY2xpZW50Iiwic2lkIjoiNjRlMDUzMTMtM2UyMi00MmNjLWE0YmItOTAxODU2YTFhYjMzIiwiYXRfaGFzaCI6ImphOXRKZ1E0VkVPTTNBZGc0VWJBVGciLCJuYW1lIjoiYWxpY2UgcG9zdGdyZXMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhbGljZSIsImdpdmVuX25hbWUiOiJhbGljZSIsImZhbWlseV9uYW1lIjoicG9zdGdyZXMifQ.dH5hM21-ygBiCXoA9NVOou-L3esUVJUFFUmt_1fU0jc9al4Lk7EUN-cqHicHZPD48HhkIWMJK7WZjxnZLDlkG7ORGdDKPGccMU4-sGsRuVu-GDuNFo_5kHAh_NJZsLBXz9UkpNBkd8ROxK3-fbmyYdwsuwNeg6KNhSOj0FxEnxLc0-HrjEE92P7hzq0PD29oY2jhRKcqpbtknMwxFkkMBi8xPgdpuyTmLtJD3-xxYuwMKP7WUGzwzVAFqfrhFm5O5dJxeld5fTFE4Kyl9fR24JcjtfxBeIHVJqLiQkl9Et_KNGiFoXDG4Xwcc7eIUaBnauhY5_froYvKS8NbQxCOUg\",\"not-before-policy\":0,\"session_state\":\"64e05313-3e22-42cc-a4bb-901856a1ab33\",\"scope\":\"openid profile postgres\"}<\/code><\/pre>\n<p><a class=\"anchor\" name=\"%D0%90%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20psql\" id=\"\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 psql\"><\/a><\/p>\n<h3>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 psql<\/h3>\n<p>\u0414\u043b\u044f \u0446\u0435\u043b\u0435\u0439 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e \u043d\u0435\u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 http (\u043f\u0440\u0438\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 https \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432):<\/p>\n<pre><code class=\"bash\">export PGOAUTHDEBUG=\"UNSAFE\"<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c psql \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0434\u0435\u0442\u0430\u043b\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">psql \"user=alice dbname=postgres oauth_issuer=http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration oauth_client_id=postgres-client oauth_client_secret=YYi8LqfzHRMnqUUlptpWVC2k7eWNrqjX\"<\/code><\/pre>\n<p>\u041c\u044b \u0443\u0432\u0438\u0434\u0438\u043c URL \u0438 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0432\u0435\u0441\u0442\u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u044d\u0442\u043e\u0442 URL:\u00a0<\/p>\n<pre><code><\/code><\/pre>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435\u00a0<a href=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/device\" rel=\"noopener noreferrer nofollow\">http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/device<\/a>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fef\/4b4\/c8b\/fef4b4c8b96e4c6287f14a7d2e5f6f52.png\" width=\"852\" height=\"529\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fef\/4b4\/c8b\/fef4b4c8b96e4c6287f14a7d2e5f6f52.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fef\/4b4\/c8b\/fef4b4c8b96e4c6287f14a7d2e5f6f52.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u043a\u043e\u0434 \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Submit.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/706\/bda\/38f\/706bda38f82a82700aeacdb08c27dbe0.png\" width=\"858\" height=\"528\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/706\/bda\/38f\/706bda38f82a82700aeacdb08c27dbe0.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/706\/bda\/38f\/706bda38f82a82700aeacdb08c27dbe0.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u0438\u0434\u0438\u043c \u043e\u043a\u043d\u043e \u043b\u043e\u0433\u0438\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2e5\/82e\/ec7\/2e582eec72220f252a24953903a14cc0.png\" width=\"889\" height=\"667\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/2e5\/82e\/ec7\/2e582eec72220f252a24953903a14cc0.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2e5\/82e\/ec7\/2e582eec72220f252a24953903a14cc0.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u043b\u043e\u0433\u0438\u043d-\u043f\u0430\u0440\u043e\u043b\u044c (\u0441\u043c. \u00ab<a href=\"#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/a>\u00bb) \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 Sign In.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f6d\/686\/403\/f6d6864036153bfe9ea53991e786c12a.png\" width=\"858\" height=\"686\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f6d\/686\/403\/f6d6864036153bfe9ea53991e786c12a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f6d\/686\/403\/f6d6864036153bfe9ea53991e786c12a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442, \u0433\u043e\u0442\u043e\u0432\u044b \u043b\u0438 \u043c\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c (\u043f\u0440\u0438\u0441\u043b\u0430\u0442\u044c) \u0442\u0430\u043a\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e PostgreSQL. \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Yes.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/de3\/5df\/c66\/de35dfc666f9e3ab1513e47ed040755b.png\" width=\"855\" height=\"652\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/de3\/5df\/c66\/de35dfc666f9e3ab1513e47ed040755b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/de3\/5df\/c66\/de35dfc666f9e3ab1513e47ed040755b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u043b\u043e\u0433\u0438\u043d\u0438\u043b\u0438\u0441\u044c&#8230;<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/94a\/d28\/97b\/94ad2897bf6714312cf427b09cab3e6d.png\" width=\"855\" height=\"402\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/94a\/d28\/97b\/94ad2897bf6714312cf427b09cab3e6d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/94a\/d28\/97b\/94ad2897bf6714312cf427b09cab3e6d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>&#8230; \u0438 \u043c\u043e\u0436\u0435\u043c \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435:<\/p>\n<pre><code class=\"bash\">psql (18devel) Type \"help\" for help.  postgres=&gt; <\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0432 PostgreSQL.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f OAuth 2.0 Device Authorization Flow, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0432 \u0421\u0423\u0411\u0414 PostgreSQL 18 \u0438 Tantor Postgres 17.5.0, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c SSO (single sign-on). \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u0440\u043e\u0434\u0435 Keycloak\u00a0\u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0437\u0430\u0449\u0438\u0442\u044b, \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044f \u0440\u0438\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 \u043f\u0430\u0440\u043e\u043b\u0435\u0439, \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0430\u0445. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Keycloak \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 PostgreSQL \u0434\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 psql.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \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\/articles\/923582\/\"> https:\/\/habr.com\/ru\/articles\/923582\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u041f\u043b\u0430\u043d \u0441\u0442\u0430\u0442\u044c\u0438<\/h2>\n<ul>\n<li>\n<p><a href=\"#%D0%92%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20Keycloak%20%D0%B8%D0%BD%D0%B6%D0%B5%D0%BD%D0%B5%D1%80%D0%BE%D0%BC%20%D0%BF%D0%BE%20%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D0%B8\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20PostgreSQL%20%D0%B0%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%BC%20%D0%B1%D0%B0%D0%B7%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%9F%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%20%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/a><\/p>\n<\/li>\n<\/ul>\n<p><a class=\"anchor\" name=\"%D0%92%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5\" id=\"\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435\">\u043d\u0438\u0435&#187;><\/a><\/p>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0421\u0423\u0411\u0414 Tantor Postgres 17.5.0. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u043c\u044b\u00a0<a href=\"https:\/\/habr.com\/ru\/companies\/tantor\/articles\/919592\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0438\u0441\u0430\u043b\u0438<\/a>\u00a0\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u0441\u0431\u043e\u0440 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0441\u00a0pg_stat_statements \u043c\u043e\u0436\u0435\u0442 \u0447\u0435\u0440\u0435\u0441\u0447\u0443\u0440 \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438, \u043a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432 \u043a\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 OAuth 2.0.\u00a0\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 OAuth 2.0 Device Authorization Flow \u2014 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 PostgreSQL 18. \u042d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a PostgreSQL \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u00a0\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, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 Keycloak, \u0447\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0440\u0435\u0434 \u0438 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 Tantor Postgres \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0432 \u0438\u044e\u043d\u0435 2025 \u0433. \u0432\u0435\u0440\u0441\u0438\u0438 17.5.0.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u0430\u0440\u043e\u043b\u044e (password, md5, SCRAM), OAuth \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0447\u0435\u0442\u043d\u044b\u043c\u0438 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 \u0438 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430\u043c\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0432 \u0435\u0434\u0438\u043d\u043e\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\u00a0\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c. Device Authorization Flow \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432, \u0433\u0434\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u0438\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b), \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438\u043b\u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 OAuth-\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 PostgreSQL \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Keycloak: \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c Keycloak, \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c PostgreSQL, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 OAuth \u0432 PostgreSQL \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u0443\u044e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 psql \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Device Flow. \u0418\u043d\u0430\u0447\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u043f\u0440\u043e\u0439\u0434\u0451\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043d\u0438\u0436\u0435 \u0441\u0445\u0435\u043c\u0443\u00a0\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 OAuth-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432 PostgreSQL:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p><a class=\"anchor\" name=\"%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20Keycloak%20%D0%B8%D0%BD%D0%B6%D0%B5%D0%BD%D0%B5%D1%80%D0%BE%D0%BC%20%D0%BF%D0%BE%20%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D0%B8\" id=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438\"> \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438&#187;><\/a><\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/h2>\n<p>Keycloak \u2014 \u044d\u0442\u043e \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\u00a0\u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c (open source), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \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, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u00a0\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0438 \u0434\u0430\u043d\u043d\u044b\u043c, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044f \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 (SSO).\u00a0Keycloak \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f, \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0438 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438 \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0430\u0440\u043e\u043b\u0435\u0439, \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0432\u0445\u043e\u0434\u0430. \u0421 Keycloak \u044d\u0442\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0449\u0435\u043b\u0447\u043a\u0430\u043c\u0438 \u043c\u044b\u0448\u0438.<\/p>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a Keycloak<\/h3>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c Keycloak \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0431\u0440\u0430\u0437\u0430 Docker. \u0422\u0430\u043a\u0436\u0435 \u043e\u0442\u043a\u0440\u043e\u0435\u043c 8080 \u043f\u043e\u0440\u0442 \u0438\u00a0\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0admin\u00a0\u0441\u00a0\u0438\u043c\u0435\u043d\u0435\u043c\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0admin\u00a0\u0438\u00a0\u043f\u0430\u0440\u043e\u043b\u0435\u043c\u00a0admin. \u041e\u043f\u0446\u0438\u0435\u0439 &#8212;name \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0438\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u043a\u0430\u043a keycloak.<\/p>\n<pre><code class=\"bash\">docker run --name keycloak -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io\/keycloak\/keycloak:26.2.1 start-dev<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u0432\u0435\u0434\u0451\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0430\u0434\u0440\u0435\u0441\u00a0<a href=\"http:\/\/localhost:8080\" rel=\"noopener noreferrer nofollow\">http:\/\/localhost:8080<\/a>, \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0430\u0434\u043c\u0438\u043d \u043f\u0430\u043d\u0435\u043b\u044c Keycloak, \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442 \u043b\u043e\u0433\u0438\u043d-\u043f\u0430\u0440\u043e\u043b\u044c. \u0412\u0432\u0435\u0434\u0451\u043c admin, admin.<\/p>\n<p>\u041f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 Keycloak \u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Realm<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (Users)<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Client scope<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u041a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\u00a0(Clients)<\/p>\n<\/li>\n<\/ol>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u0442\u0430\u043f.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Realm<\/h3>\n<p>Realm \u2014 \u044d\u0442\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0440\u043e\u043b\u0438, \u0433\u0440\u0443\u043f\u043f\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.\u00a0\u0427\u0442\u043e\u0431\u044b \u0435\u0451 \u0441\u043e\u0437\u0434\u0430\u0442\u044c, \u043d\u0443\u0436\u043d\u043e \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u044c Manage realms \u0432 \u043b\u0435\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 Manage realms:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 Create realm, \u0432 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0432 \u043f\u043e\u043b\u0435 Realm name \u0432\u0432\u043e\u0434\u0438\u043c &#171;postgres-realm&#187;.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 Create \u043d\u0430\u0448 realm \u0441\u043e\u0437\u0434\u0430\u0441\u0442\u0441\u044f \u0438 \u0441\u0442\u0430\u043d\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u043c.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p><a class=\"anchor\" name=\"%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9\" id=\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439\">\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439&#187;<\/a><\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (Users)<\/h3>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 (Users) \u2013 \u044d\u0442\u043e \u0441\u0443\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. \u041e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0430\u044f \u043f\u043e\u0447\u0442\u0430, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0430\u0434\u0440\u0435\u0441, \u043d\u043e\u043c\u0435\u0440 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0438 \u0434\u0435\u043d\u044c \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f. \u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043e\u043a\u043d\u043e\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 Users \u0432 \u043b\u0435\u0432\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Create new user, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.\u00a0\u0412 \u043f\u043e\u043b\u0435 Username \u0432\u0432\u043e\u0434\u0438\u043c \u0438\u043c\u044f &#171;alice&#187;, \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u043b\u044f Email, First name \u0438 Last name.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 Create, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. ID \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 \u0411\u0414 \u0434\u043b\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Keycloak \u0438 PostgreSQL \u0432 \u0444\u0430\u0439\u043b\u0435 pg_ident.conf.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Credentials \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 Set password \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0430\u0440\u043e\u043b\u044f:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u043f\u0430\u0440\u043e\u043b\u044c &#171;alice&#187;. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044c\u00a0Temporary (\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c) \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u043b\u043e\u0433\u0438\u043d\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Save, \u0437\u0430\u0442\u0435\u043c \u0432 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Save password:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d:<\/p>\n<figure class=\"full-width\"><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (Client scopes)<\/h3>\n<p>\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (Client scope) \u2014 \u044d\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u0442\u043e\u043a\u0435\u043d\u0430\u0445.\u00a0\u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u043e\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u044b, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u043c\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u043c\u0438.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Client scopes:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 Create client scope, \u043e\u0442\u043a\u0440\u043e\u0435\u043a\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0412\u0432\u043e\u0434\u0438\u043c \u0432 \u043f\u043e\u043b\u0435 Name \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 &#171;postgres&#187;, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u0438\u043f Default, \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c Include in token scope \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c Save.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (Client)<\/h3>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u044b (Clients) \u2013 \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u2013 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c\u00a0\u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Clients \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Create client.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435 General settings \u0432 \u043f\u043e\u043b\u0435 Client ID \u0432\u0432\u043e\u0434\u0438\u043c &#171;postgres-client&#187;. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Next.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435 Capability config:<\/p>\n<ol>\n<li>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c Client authentification (\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 On);<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c Standard flow, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b Authorization Code Flow \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c OAuth 2.0 Device Authorization Grant;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Next.<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u043e\u043a\u043d\u0435 Login settings \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0438\u0447\u0435\u0433\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Save.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 Client scopes \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 postgres (\u043d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0438\u0437\u0443) \u0438 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0442\u0438\u043f Default;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043b\u044f basic \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0442\u0438\u043f Default.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 scopes \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0435 \u0432\u0430\u0436\u043d\u044b, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u0430\u043a \u0435\u0441\u0442\u044c.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 Credentials \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f Client Secret, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u043f\u0440\u0438 \u043b\u043e\u0433\u0438\u043d\u0435 \u0432 PostgreSQL (\u0441\u043c. \u0434\u0430\u043b\u0435\u0435 \u0432 \u0441\u0435\u043a\u0446\u0438\u0438\u00a0\u00ab<a href=\"#%D0%90%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20psql\" rel=\"noopener noreferrer nofollow\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 psql<\/a>\u00bb)<\/p>\n<figure class=\"full-width\"><\/figure>\n<p><a class=\"anchor\" name=\"%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20PostgreSQL%20%D0%B0%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%BC%20%D0%B1%D0%B0%D0%B7%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85\" id=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445\">\u0430\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445&#187;<\/a><\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b OAuth \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 PostgreSQL:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 PostgreSQL;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u0444\u0430\u0439\u043b\u0435 postgresql.conf;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u0444\u0430\u0439\u043b\u0435\u00a0pg_ident.conf \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL. \u0415\u0441\u043b\u0438 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u00a0\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432\u00a0\u0432 \u0444\u0430\u0439\u043b\u0435 pg_hba.conf.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u043e\u043b\u0435\u0439<\/h3>\n<p>\u0420\u043e\u043b\u044c \u2014 \u044d\u0442\u043e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u043b\u0430\u0434\u0435\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438 \u0438\u043c\u0435\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0430. \u0420\u043e\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f,\u00a0\u0433\u0440\u0443\u043f\u043f\u0443\u00a0\u0438\u043b\u0438 \u0438 \u0442\u043e, \u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0440\u043e\u043b\u044c \u0438 \u0434\u0430\u0434\u0438\u043c \u0435\u0439 \u043f\u0440\u0430\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"bash\">CREATE ROLE alice; ALTER ROLE alice WITH LOGIN;<\/code><\/pre>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0444\u0430\u0439\u043b\u0430\u00a0postgresql.conf<\/h3>\n<p>\u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 oauth_validator_libraries \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0438\u043c\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d (\u0441\u043c. \u0441\u0435\u043a\u0446\u0438\u044e \u00ab<a href=\"#%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c<\/a>\u00bb).<\/p>\n<pre><code class=\"bash\">oauth_validator_libraries = 'oauth_validator'<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u043b\u044e\u0431\u044b\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 OAuth; \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 oauth HBA \u0434\u043e\u043b\u0436\u043d\u044b \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430. \u0415\u0441\u043b\u0438 \u0437\u0430\u0434\u0430\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e), \u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u0445 OAuth \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u043e.<\/p>\n<p><a class=\"anchor\" name=\"%D0%A1%D0%BE%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9%20%D0%BC%D0%B5%D0%B6%D0%B4%D1%83%20Keycloak%20%D0%B8%20PostgreSQL\" id=\"\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL\">\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL&#187;<\/a><\/p>\n<h3>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL<\/h3>\n<p>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u0447\u0435\u0440\u0435\u0437 \u0444\u0430\u0439\u043b pg_ident.conf \u2014 \u044d\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445;<\/p>\n<\/li>\n<li>\n<p>\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u2013 \u0432 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0435 \u044d\u0442\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0444\u0430\u0439\u043b\u00a0pg_ident.conf<\/h4>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 id \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 Keycloak \u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code># MAPNAME    SYSTEM-USERNAME                           PG-USERNAME oauthmap    \"0fc72b6f-6221-4ed8-a916-069e7a081d14\"     \"alice\"<\/code><\/pre>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u043c\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u2013 ID \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 Keycloak (\u0441\u043c. \u00ab<a href=\"#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/a>\u00bb), \u0432 \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u2013\u00a0\u0438\u043c\u044f \u0440\u043e\u043b\u0438 \u0432 PostgreSQL.<\/p>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440<\/h4>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0438\u0436\u0435 \u0432 \u0441\u0435\u043a\u0446\u0438\u0438 \u00ab<a href=\"#%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c<\/a>\u00bb.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0444\u0430\u0439\u043b\u0430\u00a0pg_hba.conf<\/h3>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0432\u0445\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code># TYPE  DATABASE        USER            ADDRESS                 METHOD local   all             all             oauth issuer=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" scope=\"openid postgres\" map=\"oauthmap\"<\/code><\/pre>\n<p>\u0412 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u043e\u043c \u043f\u043e\u043b\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u044c oauth \u0438 \u0434\u0430\u043b\u0435\u0435 \u0435\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b. \u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 issuer \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c URL \u0434\u0438\u0441\u043a\u0430\u0432\u0435\u0440\u0438-\u0441\u0435\u0440\u0432\u0438\u0441\u0430 &#171;<a href=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" rel=\"noopener noreferrer nofollow\">http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration<\/a>. \u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 Scope \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0443 Keycloak \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL (\u0441\u043c. \u00ab<a href=\"#%D0%A1%D0%BE%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9%20%D0%BC%D0%B5%D0%B6%D0%B4%D1%83%20Keycloak%20%D0%B8%20PostgreSQL\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 Keycloak \u0438 PostgreSQL<\/a>\u00bb).<\/p>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437\u00a0pg_ident.conf<\/h4>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 map, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c map id \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 pg_ident.conf, \u0443 \u043d\u0430\u0441 \u044d\u0442\u043e &#171;oauthmap&#187;:<\/p>\n<pre><code># TYPE  DATABASE        USER            ADDRESS                 METHOD local   all             all             oauth issuer=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" scope=\"openid postgres\" map=\"oauthmap\"<\/code><\/pre>\n<h4>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437\u00a0\u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440<\/h4>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043c\u0435\u0441\u0442\u0440\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 map \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0437\u0430\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 delegate_ident_mapping=1.<\/p>\n<pre><code># TYPE  DATABASE        USER            ADDRESS                 METHOD local   all             all             oauth issuer=\"http:\/\/192.168.0.156:8080\/realms\/postgres-realm\/.well-known\/openid-configuration\" scope=\"openid postgres\" delegate_ident_mapping=1<\/code><\/pre>\n<p>\u0423 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 delegate_ident_mapping \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0432\u044b\u0448\u0435, \u0447\u0435\u043c \u0443<\/p>\n<\/div>\n<\/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-465369","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/465369","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=465369"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/465369\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=465369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=465369"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=465369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}