{"id":8921,"date":"2020-02-25T16:48:49","date_gmt":"2020-02-25T15:48:49","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=8921"},"modified":"2023-08-10T15:12:49","modified_gmt":"2023-08-10T13:12:49","slug":"uwierzytelnianie-za-pomoca-jwt-w-asp-net-core-2-2","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/uwierzytelnianie-za-pomoca-jwt-w-asp-net-core-2-2\/","title":{"rendered":"Uwierzytelnianie za pomoc\u0105 JWT w ASP .NET Core 2.2"},"content":{"rendered":"\n<p>JWT jest to standard uwierzytelniania oparty o tokeny (RFC 7519) <a aria-label=\" (opens in a new tab)\" href=\"#_ftn1\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >[1]<\/a>. Zak\u0142ada on stworzenie specjalnego obiektu, kt\u00f3ry jest przesy\u0142any do i z serwera. Protok\u00f3\u0142 HTTPS jest bezstanowy, nie wymaga przechowywania informacji o u\u017cytkownikach na serwerze przez czas trwania \u017c\u0105da\u0144. Token JWT jest dodawany do danych w zapytaniach, maj\u0105c na celu autoryzacje lub uwierzytelnienie na serwerze. Po stronie klienta s\u0105 zapisywane w np. pami\u0119ci (w przypadku przegl\u0105darki) localStorage.<\/p>\n\n\n\n<p>Azure Active Directory jest to us\u0142uga umo\u017cliwiaj\u0105ca zarz\u0105dzanie to\u017csamo\u015bciami dla aplikacji internetowych i nie tylko. Korzysta ona z protoko\u0142u uwierzytelnienia OAuth 2.0. Mo\u017cna j\u0105 wykorzysta\u0107 do uwierzytelnienia u\u017cytkownik\u00f3w na r\u00f3\u017cnych platformach, np. w aplikacjach mobilnych lub internetowych. Po zalogowaniu u\u017cytkownika mo\u017ce zwr\u00f3ci\u0107 token JWT. Umo\u017cliwia aplikacji uwierzytelnienie u\u017cytkownika i dost\u0119p do danych znajduj\u0105cych si\u0119 w aplikacji. <a href=\"#_ftn2\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >[2]<\/a> Jest to przyk\u0142ad u\u017cycia istniej\u0105cego dostawcy w celu zdobycia tokenu JWT. Jest to przydatne w przypadku pracy w aplikacjach dla firm korzystaj\u0105cych z tego rozwi\u0105zania lub innych dostawc\u00f3w jak np. Google, Facebook.<\/p>\n\n\n\n<p>Na rys. 1 przedstawiony jest diagram sekwencyjny, pokazuj\u0105cy tworzenie i u\u017cycie tokenu JWT. U\u017cytkownik wype\u0142nia formularz logowania w aplikacji, nast\u0119pnie s\u0105 wysy\u0142ane dane do serwera. Serwer sprawdza, czy s\u0105 podane prawid\u0142owe dane do autentykacji, tworzy token, kt\u00f3ry jest wysy\u0142any w odpowiedzi do u\u017cytkownika. Aplikacja klienta przechwytuje token, zapisuje w pami\u0119ci (np. Cookies lub LocalStorage). Przy kolejnych akcjach u\u017cytkownika token jest do\u0142\u0105czany, aby uwierzytelni\u0107 operacje.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"#_ftnref1\" rel=\"nofollow\" ><img decoding=\"async\" width=\"886\" height=\"707\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz1-1.png\" alt=\"Diagram sekwencyjny, u\u017cycie tokenu JWT\" class=\"wp-image-8922\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz1-1.png 886w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz1-1-300x239.png 300w\" sizes=\"(max-width: 886px) 100vw, 886px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Rys. 1 Diagram sekwencyjny, u\u017cycie tokenu JWT \u0179r\u00f3d\u0142o: Opracowanie w\u0142asne<\/em><\/figcaption><\/figure>\n\n\n\n<p>Token jest to obiekt, kt\u00f3ry zosta\u0142 podzielony na trzy cz\u0119\u015bci:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>nag\u0142\u00f3wek (Header) \u2013 obiekt JSON, zakodowany formatem base64; zawiera informacje takie jak typ tokenu oraz nazwa algorytmu,<\/li>\n\n\n\n<li>zawarto\u015b\u0107 (Payload) \u2013 obiekt JSON, r\u00f3wnie\u017c zakodowany formatem base64; zawarte s\u0105 tutaj atrybuty u\u017cytkownika, np. identyfikator u\u017cytkownika, adres email, rola; zawarto\u015b\u0107 ta nie powinna zawiera\u0107 informacji poufnych, gdy\u017c nie s\u0105 one szyfrowane,<\/li>\n\n\n\n<li>podpis (Signature) \u2013 s\u0142u\u017cy do weryfikacji po stronie serwera czy token zawiera poprawne informacje; jest to cyfrowa sygnatura generowana przez po\u0142\u0105czenie nag\u0142\u00f3wka i zawarto\u015bci i zakodowana przez klucz prywatny znany tylko przez serwer.<\/li>\n<\/ul>\n\n\n\n<p>Gdyby u\u017cytkownik atakuj\u0105cy system chcia\u0142 zmieni\u0107 zawarto\u015b\u0107 tokenu, musia\u0142by tak\u017ce wygenerowa\u0107 podpis ponownie \u2013 w tym momencie jest to ju\u017c nie mo\u017cliwe, gdy\u017c klucz jest dost\u0119pny tylko na serwerze, niedost\u0119pny po stronie klienta.<\/p>\n\n\n\n<p>Wa\u017cniejsze atrybuty, kt\u00f3re warto zna\u0107 i powinny by\u0107 do\u0142\u0105czona do zawarto\u015bci:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>jti \u2013 unikalny identyfikator JWT,<\/li>\n\n\n\n<li>iss \u2013 zleceniodawca, kt\u00f3ry wydaje token,<\/li>\n\n\n\n<li>sub \u2013 identyfikuje podmiot, musi by\u0107 unikalny,<\/li>\n\n\n\n<li>aud \u2013 identyfikuje odbiorc\u00f3w, dla kt\u00f3rych jest przeznaczony,<\/li>\n\n\n\n<li>exp \u2013 okre\u015bla czas wyga\u015bni\u0119cia tokenu.<\/li>\n<\/ul>\n\n\n\n<p>Stworzona zosta\u0142a klasa AccountsService, kt\u00f3ra zawiera w sobie metody pozwalaj\u0105ce na rejestracj\u0119, logowanie i od\u015bwie\u017cenie tokenu u\u017cytkownika. Na rys. 2 pokazano metod\u0119, kt\u00f3ra ilustruje, w jaki spos\u00f3b u\u017cytkownik mo\u017ce by\u0107 uwierzytelniany oraz jak tworzy si\u0119 token JWT.<\/p>\n\n\n\n<p><a href=\"#_ftnref1\" name=\"_ftn1\" rel=\"nofollow\" ><\/a><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-8923\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz2-1.png\"><img decoding=\"async\" width=\"915\" height=\"1130\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz2-1.png\" alt=\"Kod opisuj\u0105cy metody klasy AccountsService\" class=\"wp-image-8923\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz2-1.png 915w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz2-1-243x300.png 243w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz2-1-829x1024.png 829w\" sizes=\"(max-width: 915px) 100vw, 915px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Rys. 2 Metody klasy AccountsService<\/em><br><em>\u0179r\u00f3d\u0142o: opracowanie w\u0142asne<\/em><\/figcaption><\/figure>\n\n\n\n<p>Dodanie konfiguracji JWT do projektu:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>modyfikacja klasy Startup \u2013 na rys. 3 jest kod, kt\u00f3ry zostaje dodany w celu konfiguracji autentykacji przez JWT dopisany do metody ConfigureServices; zostaje do\u0142\u0105czona klasa reprezentuj\u0105ca u\u017cytkownika, schemat tokenu JWT oraz walidacja jego parametr\u00f3w; wymagane jest tak\u017ce w\u0142\u0105czenie autentykacji w metodzie Configure pokazane na rys. 4,<\/li>\n\n\n\n<li>dodanie dodatkowych informacji do tworzenia tokenu JWT \u2013 na rys. 5 jest przyk\u0142adowa konfiguracja pliku JSON projektu.<\/li>\n<\/ul>\n\n\n\n<p><a href=\"#_ftnref1\" name=\"_ftn1\" rel=\"nofollow\" ><\/a><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-8924\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz3-1.png\"><img decoding=\"async\" width=\"879\" height=\"714\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz3-1.png\" alt=\"Kod dopisany do klasy Startup w celu konfiguracji JWT\" class=\"wp-image-8924\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz3-1.png 879w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz3-1-300x244.png 300w\" sizes=\"(max-width: 879px) 100vw, 879px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Rys. 3 Kod dopisany do klasy Startup w celu konfiguracji JWT<\/em><br><em>\u0179r\u00f3d\u0142o: opracowanie w\u0142asne<\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full wp-image-8925\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz4-1.png\"><img decoding=\"async\" width=\"277\" height=\"43\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz4-1.png\" alt=\"Kod dopisany do klasy Startup w celu w\u0142\u0105czenia autentykacji\" class=\"wp-image-8925\"\/><\/a><figcaption class=\"wp-element-caption\"><em>Rys. 4 Kod dopisany do klasy Startup w celu w\u0142\u0105czenia autentykacji<\/em><br><em>\u0179r\u00f3d\u0142o: opracowanie w\u0142asne<\/em><\/figcaption><\/figure>\n\n\n\n<p>Klasa u\u017cytkownika dziedziczy po IdentityUser. Jest to implementacja paczki ASP .NET Core Identity. Zawiera podstawowe w\u0142a\u015bciwo\u015bci, takie jak identyfikator u\u017cytkownika, adres email oraz has\u0142o. W przypadku korzystania Entity Framework Core nale\u017cy doda\u0107 paczk\u0119 nuget Microsoft.AspNetCore.Identity.EntityFrameworkCore.<\/p>\n\n\n\n<p>Dla uproszczenia przyk\u0142adu ustawienia zosta\u0142y zapisane w pliku appsettings.json. Docelowo nale\u017cy jednak skorzysta\u0107 z bardziej bezpiecznych rozwi\u0105za\u0144. Mo\u017cna wykorzysta\u0107 Azure Key Vault <a href=\"#_ftn1\" name=\"_ftnref1\" rel=\"nofollow\" >[3]<\/a>dla przypadku wspomnianego na pocz\u0105tku artyku\u0142u lub w usersecrets.json<a href=\"#_ftn2\" name=\"_ftnref2\" rel=\"nofollow\" >[4]<\/a>.<\/p>\n\n\n\n<p><a href=\"#_ftnref1\" name=\"_ftn1\" rel=\"nofollow\" ><\/a><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-8926\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz5-1.png\"><img decoding=\"async\" width=\"925\" height=\"254\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz5-1.png\" alt=\"Kod opisuj\u0105cy konfiguracj\u0119 pliku appsettings.json\" class=\"wp-image-8926\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz5-1.png 925w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz5-1-300x82.png 300w\" sizes=\"(max-width: 925px) 100vw, 925px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Rys. 5 Konfiguracja pliku appsettings.json<\/em><br><em>\u0179r\u00f3d\u0142o: opracowanie w\u0142asne<\/em><\/figcaption><\/figure>\n\n\n\n<p>Metody w kontrolerach wymagaj\u0105ce uwierzytelnienia musz\u0105 zosta\u0107 opatrzone atrybutem Authorize. W przypadku tokenu JWT trzeba doda\u0107 jeszcze konfiguracj\u0119 schematu w atrybucie. Przyk\u0142ad takiego u\u017cycia atrybutu na ca\u0142ym kontrolerze jest pokazany na rys. 6.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-8927\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz6-1.png\"><img decoding=\"async\" width=\"789\" height=\"96\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz6-1.png\" alt=\"Kod z atrybutami dla klasy, autoryzacja ca\u0142ego kontrolera\" class=\"wp-image-8927\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz6-1.png 789w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/Obraz6-1-300x37.png 300w\" sizes=\"(max-width: 789px) 100vw, 789px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Rys. 6 Kod z atrybutami dla klasy, autoryzacja ca\u0142ego kontrolera<\/em><br><em>\u0179r\u00f3d\u0142o: opracowanie w\u0142asne<\/em><\/figcaption><\/figure>\n\n\n\n<p>Uwierzytelnianie za pomoc\u0105 token\u00f3w JWT zosta\u0142o stworzone z my\u015bl\u0105 o aplikacjach mobilnych i SPA. Jest to proste w obs\u0142udze rozwi\u0105zanie, wymagaj\u0105ce jednak sporej konfiguracji. Elastyczno\u015b\u0107 polityki autoryzacji w ASP .NET Core pozwala na integracj\u0119 dodatkowych, zewn\u0119trznych dostawc\u00f3w.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><a name=\"_ftn1\" href=\"#_ftnref1\" rel=\"nofollow\" >[1]<\/a> <a href=\"https:\/\/tools.ietf.org\/html\/rfc7519\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/tools.ietf.org\/html\/rfc7519<\/a><\/p>\n\n\n\n<p><a name=\"_ftn2\" href=\"#_ftnref2\" rel=\"nofollow\" >[2]<\/a> <a href=\"https:\/\/docs.microsoft.com\/pl-pl\/azure\/active-directory\/develop\/v1-protocols-oauth-code\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/docs.microsoft.com\/pl-pl\/azure\/active-directory\/develop\/v1-protocols-oauth-code<\/a><\/p>\n\n\n\n<p><a name=\"_ftn1\" href=\"#_ftnref1\" rel=\"nofollow\" >[3]<\/a> <a href=\"https:\/\/docs.microsoft.com\/pl-pl\/azure\/key-vault\/basic-concepts\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/docs.microsoft.com\/pl-pl\/azure\/key-vault\/basic-concepts<\/a><\/p>\n\n\n\n<p><a name=\"_ftn2\" href=\"#_ftnref2\" rel=\"nofollow\" >[4]<\/a> <a href=\"https:\/\/docs.microsoft.com\/pl-pl\/aspnet\/core\/security\/app-secrets?view=aspnetcore-2.2&amp;tabs=windows\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/docs.microsoft.com\/pl-pl\/aspnet\/core\/security\/app-secrets?view=aspnetcore-2.2&amp;tabs=windows<\/a><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;8921&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;2&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 2)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Uwierzytelnianie za pomoc\u0105 JWT w ASP .NET Core 2.2&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 2)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>JWT jest to standard uwierzytelniania oparty o tokeny (RFC 7519) [1]. Zak\u0142ada on stworzenie specjalnego obiektu, kt\u00f3ry jest przesy\u0142any do &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/uwierzytelnianie-za-pomoca-jwt-w-asp-net-core-2-2\/\">Continued<\/a><\/p>\n","protected":false},"author":241,"featured_media":8941,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[272,800,886,885],"class_list":["post-8921","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-net","tag-asp","tag-core-2-2","tag-jwt"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2020\/02\/o365-JWT-w-ASP-.NET-Core-2.2.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/8921"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/241"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=8921"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/8921\/revisions"}],"predecessor-version":[{"id":23407,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/8921\/revisions\/23407"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/8941"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=8921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=8921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=8921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}