﻿
{"id":18073,"date":"2020-10-05T22:07:38","date_gmt":"2020-10-05T22:07:38","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=18073"},"modified":"2020-10-05T22:07:38","modified_gmt":"2020-10-05T22:07:38","slug":"net-core-microservices-ocelot-ile-authentication-islemleri","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/net-core-microservices-ocelot-ile-authentication-islemleri\/","title":{"rendered":".NET Core Microservices &#8211; Ocelot \u0130le Authentication \u0130\u015flemleri"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>\u00d6nceki <a href=\"https:\/\/www.gencayyildiz.com\/blog\/net-core-microservices-ocelot-api-gateway\/\" rel=\"noopener noreferrer\" target=\"_blank\">.NET Core Microservices \u2013 Ocelot API Gateway<\/a> ba\u015fl\u0131kl\u0131 makalemizde bir Gateway k\u00fct\u00fcphanesi olan Ocelot&#8217;un; microservice&#8217;ler aras\u0131 ge\u00e7i\u015f g\u00f6revi g\u00f6ren sorumlulu\u011fundan, deploy tasar\u0131mlar\u0131ndan, pratik olarak nas\u0131l kullan\u0131ld\u0131\u011f\u0131ndan ve daha bir\u00e7ok \u00f6zelli\u011finden detayl\u0131ca bahsetmi\u015f bulunmaktay\u0131z. Bu i\u00e7eri\u011fimizde ise Ocelot \u00fczerinden mikro servislerimize eri\u015fim sa\u011flarken kimlik do\u011frulaman\u0131n(authentication) nas\u0131l ger\u00e7ekle\u015ftirildi\u011fini ele alacak ve pratikte uygulayaca\u011f\u0131z. Haydi ba\u015flayal\u0131m&#8230;<\/p>\n<h3 style=\"color:#e83e8c;\">Ocelot \u0130le Authentication Tasar\u0131m\u0131<\/h3>\n<p>Ocelot API Gateway k\u00fct\u00fcphanesinde authentication kullanabilmek i\u00e7in token yap\u0131lanmas\u0131ndan faydalanaca\u011f\u0131z. Yap\u0131sal olarak, client&#8217;\u0131n yapaca\u011f\u0131 giri\u015f talebi neticesinde token&#8217;\u0131 \u00fcretebilmek i\u00e7in yine Ocelot taraf\u0131ndan eri\u015fim sa\u011flanan bir servis bu i\u015fi \u00fcstlenecek ve \u00fcretilen token&#8217;\u0131 client&#8217;a g\u00f6nderecektir. Ard\u0131ndan client, bu token&#8217;\u0131 kullanarak di\u011fer mikro servislere Ocelot \u00fczerinden talepte bulunacak ve her bir servis token&#8217;\u0131 do\u011frulayacakt\u0131r.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri-300x184.png\" alt=\".NET Core Microservices - Ocelot \u0130le Authentication \u0130\u015flemleri\" width=\"300\" height=\"184\" class=\"alignleft size-medium wp-image-18075\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri-300x184.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri.png 567w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>Yandaki g\u00f6rsel anlat\u0131lmak istenileni tam olarak \u00f6zetleyecek mahiyettedir. \u0130ncelendi\u011finde g\u00f6r\u00fclece\u011fi \u00fczere servislerden sadece token \u00fcretiminden sorumlu bir &#8216;Auth Service&#8217; mevcuttur<span style=\"font-size:10px;\">(Bu servis IdentityServer4 serviside olabilir)<\/span> Client sistemi kullanabilmek amac\u0131yla kimli\u011fini do\u011frulayabilmek i\u00e7in bu servisten bir token talebinde bulunmakta ve elde edilen bu token de\u011feri ile di\u011fer servislere(A Service, B Service&#8230;) request atmaktad\u0131r. B\u00f6ylece authentication sa\u011flanm\u0131\u015f olunmaktad\u0131r. Tabi ki t\u00fcm bu s\u00fcre\u00e7 Ocelot arac\u0131l\u0131\u011f\u0131yle tek elden ger\u00e7ekle\u015ftirilmektedir \ud83d\ude42<\/p>\n<h3 style=\"color:#e83e8c;\">Ocelot \u0130le Authentication Uygulamas\u0131<\/h3>\n<p>Bir tasar\u0131m\u0131 anlaman\u0131n en iyi yolu onu uygulamakt\u0131r. Dolay\u0131s\u0131yla bu i\u00e7eri\u011fimizde Ocelot ile authentication i\u015flemlerinin nas\u0131l uyguland\u0131\u011f\u0131n\u0131 anlayabilmek i\u00e7in pratik olarak tam teferruat\u0131yla ele alacak ve \u00f6rnek bir \u00e7al\u0131\u015fma ger\u00e7ekle\u015ftirece\u011fiz.<\/p>\n<p>Her\u015feyden \u00f6nce &#8216;ProductAPI&#8217;, &#8216;CustomerAPI&#8217;, &#8216;AuthAPI&#8217; ve &#8216;APIGateway&#8217; isimlerinde d\u00f6rt adet proje olu\u015ftural\u0131m. <\/p>\n<p><strong style=\"color:red;font-size:25px;\"><code>dotnet new webapi --name ProductAPI<\/code><\/strong><br \/>\n<strong style=\"color:red;font-size:25px;\"><code>dotnet new webapi --name CustomerAPI<\/code><\/strong><br \/>\n<strong style=\"color:red;font-size:25px;\"><code>dotnet new webapi --name AuthAPI<\/code><span style=\"color:blue;font-size:15px;\">(JWT)<\/span><\/strong><br \/>\n<strong style=\"color:red;font-size:25px;\"><code>dotnet new webapi --name APIGateway<\/code><span style=\"color:blue;font-size:15px;\">(Ocelot)<\/span><\/strong><\/p>\n<p>Bu projelerden &#8216;APIGateway&#8217;de Ocelot ile microservice&#8217;lere ge\u00e7i\u015f i\u015flemleri ger\u00e7ekle\u015ftirecek, &#8216;AuthAPI&#8217; ile kullan\u0131c\u0131 do\u011frulama i\u00e7in token olu\u015fturacak ve &#8216;ProductAPI&#8217; ve &#8216;CustomerAPI&#8217; ile de \u00f6rnek i\u015flevsel microservice \u00e7al\u0131\u015fmas\u0131 ger\u00e7ekle\u015ftirece\u011fiz.<\/p>\n<p>\u0130lk olarak local&#8217;de \u00e7al\u0131\u015faca\u011f\u0131m\u0131zdan dolay\u0131 t\u00fcm projelerin portlar\u0131n\u0131 \u00e7ak\u0131\u015fmamas\u0131 i\u00e7in farkl\u0131 olacak \u015fekilde ayarlayarak ba\u015flayal\u0131m;<\/p>\n<ul>\n<li>\n<u>ProductAPI<\/u><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &quot;ProductAPI&quot;: {\r\n      &quot;commandName&quot;: &quot;Project&quot;,\r\n      &quot;launchBrowser&quot;: false,\r\n      &quot;applicationUrl&quot;: &quot;https:\/\/localhost:1000;http:\/\/localhost:1001&quot;,\r\n      &quot;environmentVariables&quot;: {\r\n        &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot;\r\n      }\r\n    }\r\n<\/pre>\n<\/li>\n<li>\n<u>CustomerAPI<\/u><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &quot;CustomerAPI&quot;: {\r\n      &quot;commandName&quot;: &quot;Project&quot;,\r\n      &quot;launchBrowser&quot;: false,\r\n      &quot;applicationUrl&quot;: &quot;https:\/\/localhost:2000;http:\/\/localhost:2001&quot;,\r\n      &quot;environmentVariables&quot;: {\r\n        &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot;\r\n      }\r\n    }\r\n<\/pre>\n<\/li>\n<li>\n<u>AuthAPI<\/u><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &quot;AuthAPI&quot;: {\r\n      &quot;commandName&quot;: &quot;Project&quot;,\r\n      &quot;launchBrowser&quot;: false,\r\n      &quot;applicationUrl&quot;: &quot;https:\/\/localhost:3000;http:\/\/localhost:3001&quot;,\r\n      &quot;environmentVariables&quot;: {\r\n        &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot;\r\n      }\r\n    }\r\n<\/pre>\n<\/li>\n<li>\n<u>APIGateway<\/u><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &quot;APIGateway&quot;: {\r\n      &quot;commandName&quot;: &quot;Project&quot;,\r\n      &quot;launchBrowser&quot;: false,\r\n      &quot;applicationUrl&quot;: &quot;https:\/\/localhost:4000;http:\/\/localhost:4001&quot;,\r\n      &quot;environmentVariables&quot;: {\r\n        &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot;\r\n      }\r\n    }\r\n<\/pre>\n<\/li>\n<\/ul>\n<p>Ard\u0131ndan her bir servisi tek tek ele alarak kodlamaya ba\u015flayal\u0131m.<\/p>\n<p>\u00d6ncelikle &#8216;APIGateway&#8217; projesinden ba\u015flayal\u0131m. \u0130lgili projede Ocelot&#8217;\u0131n kurulumunu ve microservice&#8217;lere eri\u015fim i\u00e7in temel konfig\u00fcrasyonu ger\u00e7ekle\u015ftirelim. Bunun nas\u0131l yap\u0131ld\u0131\u011f\u0131n\u0131 bilmiyorsan\u0131z e\u011fer yukar\u0131larda referans edilmi\u015f <a href=\"https:\/\/www.gencayyildiz.com\/blog\/net-core-microservices-ocelot-api-gateway\/\" rel=\"noopener noreferrer\" target=\"_blank\">.NET Core Microservices \u2013 Ocelot API Gateway<\/a> ba\u015fl\u0131kl\u0131 makaleye g\u00f6z atman\u0131z yeterli olacakt\u0131r.<\/p>\n<p>Temel konfig\u00fcrasyon(ocelot.json) dosyas\u0131 a\u015fa\u011f\u0131daki gibi olacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n   &quot;Routes&quot;: &#x5B;\r\n      {\r\n         &quot;DownstreamPathTemplate&quot;: &quot;\/api\/products&quot;,\r\n         &quot;DownstreamScheme&quot;: &quot;https&quot;,\r\n         &quot;DownstreamHostAndPorts&quot;: &#x5B;\r\n             {\r\n                 &quot;Host&quot;: &quot;localhost&quot;,\r\n                 &quot;Port&quot;: 1000\r\n             }\r\n         ],\r\n         &quot;UpstreamPathTemplate&quot;: &quot;\/api\/products&quot;,\r\n         &quot;UpstreamHttpMethod&quot;: &#x5B; &quot;Get&quot; ]\r\n      },\r\n      {\r\n         &quot;DownstreamPathTemplate&quot;: &quot;\/api\/customers&quot;,\r\n         &quot;DownstreamScheme&quot;: &quot;https&quot;,\r\n         &quot;DownstreamHostAndPorts&quot;: &#x5B;\r\n             {\r\n                 &quot;Host&quot;: &quot;localhost&quot;,\r\n                 &quot;Port&quot;: 2000\r\n             }\r\n         ],\r\n         &quot;UpstreamPathTemplate&quot;: &quot;\/api\/customers&quot;,\r\n         &quot;UpstreamHttpMethod&quot;: &#x5B; &quot;Get&quot; ]\r\n      },\r\n      {\r\n         &quot;DownstreamPathTemplate&quot;: &quot;\/api\/auths&quot;,\r\n         &quot;DownstreamScheme&quot;: &quot;https&quot;,\r\n         &quot;DownstreamHostAndPorts&quot;: &#x5B;\r\n             {\r\n                 &quot;Host&quot;: &quot;localhost&quot;,\r\n                 &quot;Port&quot;: 3000\r\n             }\r\n         ],\r\n         &quot;UpstreamPathTemplate&quot;: &quot;\/api\/auths&quot;,\r\n         &quot;UpstreamHttpMethod&quot;: &#x5B; &quot;Get&quot; ]\r\n      }\r\n   ],\r\n   &quot;GlobalConfiguration&quot;: {\r\n       &quot;BaseUrl&quot;: &quot;https:\/\/localhost:4000&quot;\r\n   }\r\n}\r\n<\/pre>\n<p>Tabi i\u00e7eri\u011fimizin devam\u0131nda buradaki template&#8217;lere uygun controller s\u0131n\u0131flar\u0131 yeri geldik\u00e7e ilgili projelerde olu\u015fturaca\u011f\u0131z.<\/p>\n<p>\u0130kinci olarak &#8216;AuthAPI&#8217; projesinden devam edelim. Bu servis, sadece token \u00fcretiminden sorumlu olacakt\u0131r. Bundan dolay\u0131 sadece bu i\u015fi yapabilecek bir controller geli\u015ftirilmesi yeterlidir. Misal; bu controller &#8216;AuthsController&#8217; isminde olabilir.<\/p>\n<p>JWT \u00fcretimi i\u00e7in &#8216;Security\/Secret Key&#8217;, &#8216;Issuer&#8217;, &#8216;Audience&#8217; gibi de\u011ferler gerekecektir. Bunlar\u0131 sabit olarak &#8216;appsettings.json&#8217; dosyas\u0131nda a\u015fa\u011f\u0131daki gibi tutabiliriz;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n  &quot;JWT&quot;: {\r\n    &quot;Security&quot;: &quot;ocelot authentication example project&quot;,\r\n    &quot;Issuer&quot;: &quot;https:\/\/localhost:4000&quot;,\r\n    &quot;Audience&quot;: &quot;Ocelot Example&quot;\r\n  }\r\n<\/pre>\n<p>Ard\u0131ndan token \u00fcretimi i\u00e7in bir &#8216;TokenHandler&#8217; s\u0131n\u0131f\u0131 olu\u015ftural\u0131m. <\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n   public static class TokenHandler\r\n   {\r\n      public static IConfiguration _configuration;\r\n      public static dynamic CreateAccessToken()\r\n      {\r\n         SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_configuration&#x5B;&quot;JWT:Security&quot;]));\r\n         TokenValidationParameters tokenValidationParameters = new TokenValidationParameters\r\n         {\r\n            ValidateIssuerSigningKey = true,\r\n            IssuerSigningKey = symmetricSecurityKey,\r\n            ValidateIssuer = true,\r\n            ValidIssuer = _configuration&#x5B;&quot;JWT:Issuer&quot;],\r\n            ValidateAudience = true,\r\n            ValidAudience = _configuration&#x5B;&quot;JWT:Audience&quot;],\r\n            ValidateLifetime = true,\r\n            ClockSkew = TimeSpan.Zero,\r\n            RequireExpirationTime = true\r\n         };\r\n         DateTime now = DateTime.UtcNow;\r\n         JwtSecurityToken jwt = new JwtSecurityToken(\r\n                  issuer: _configuration&#x5B;&quot;JWT:Issuer&quot;],\r\n                  audience: _configuration&#x5B;&quot;JWT:Audience&quot;],\r\n                  claims: new List&lt;Claim&gt; {\r\n                         new Claim(ClaimTypes.Name, &quot;gncy&quot;)\r\n                  },\r\n                  notBefore: now,\r\n                  expires: now.Add(TimeSpan.FromMinutes(2)),\r\n                  signingCredentials: new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256)\r\n              );\r\n         return new\r\n         {\r\n            AccessToken = new JwtSecurityTokenHandler().WriteToken(jwt),\r\n            Expires = TimeSpan.FromMinutes(2).TotalSeconds\r\n         };\r\n      }\r\n   }\r\n<\/pre>\n<p>Yukar\u0131daki kaynak kodun sa\u011fl\u0131kl\u0131 \u00e7al\u0131\u015fabilmesi i\u00e7in ilgili projeye &#8216;<a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.IdentityModel.Tokens\/\" rel=\"noopener noreferrer\" target=\"_blank\">Microsoft.IdentityModel.Tokens<\/a>&#8216; ve &#8216;<a href=\"https:\/\/www.nuget.org\/packages\/System.IdentityModel.Tokens.Jwt\" rel=\"noopener noreferrer\" target=\"_blank\">System.IdentityModel.Tokens.Jwt<\/a>&#8216; k\u00fct\u00fcphanelerinin eklenmesi gerekmektedir. Bunun i\u00e7in a\u015fa\u011f\u0131daki Dotnet CLI komutlar\u0131n\u0131 kullanabilirsiniz.<\/p>\n<p><code style=\"color:red;\">dotnet add package Microsoft.IdentityModel.Tokens<\/code><br \/>\n<code style=\"color:red;\">dotnet add package System.IdentityModel.Tokens.Jwt<\/code><\/p>\n<p>Olu\u015fturulan &#8216;TokenHandler&#8217; s\u0131n\u0131f\u0131n\u0131 kullanarak &#8216;AuthsController&#8217; controller&#8217;\u0131n\u0131 a\u015fa\u011f\u0131daki gibi geli\u015ftirelim.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n   &#x5B;ApiController]\r\n   &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n   public class AuthsController : ControllerBase\r\n   {\r\n      IConfiguration _configuration;\r\n      public AuthsController(IConfiguration configuration)\r\n      {\r\n         _configuration = configuration;\r\n      }\r\n      public IActionResult Login(string userName, string password)\r\n      {\r\n         TokenHandler._configuration = _configuration;\r\n         return Ok(userName == &quot;gncy&quot; &amp;&amp; password == &quot;12345&quot; ? TokenHandler.CreateAccessToken() : new UnauthorizedResult());\r\n      }\r\n   }\r\n<\/pre>\n<p>Burada &#8216;Login&#8217; action&#8217;\u0131nda farazi bir kullan\u0131c\u0131 ad\u0131 ve \u015fifre kontrol\u00fc yapm\u0131\u015f bulunmakta ve geriye ya token de\u011feri yahut &#8216;401&#8217; status code&#8217;u d\u00f6nmekteyiz.<\/p>\n<p>&#8216;AuthAPI&#8217; projesinin geli\u015fimini bu \u015fekilde tamamlam\u0131\u015f bulunmaktay\u0131z. Ocelot \u00fczerinden ilgili projeyi tetikleyebilmek i\u00e7in a\u015fa\u011f\u0131daki url&#8217;i kullanaca\u011f\u0131z.<\/p>\n<div style=\"text-align:center;\">\n<code style=\"color:blue;\">https:\/\/localhost:4000\/api\/auths?<span style=\"color:purple;\">userName<\/span>=gncy&<span style=\"color:purple;\">password<\/span>=12345<\/code>\n<\/div>\n<p><strong>Peki hocam, neden Startup.cs dosyas\u0131nda Authentication servisini uygulamaya dahil etmedik?<\/strong><br \/>\n&#8216;AuthAPI&#8217; projesi, yukar\u0131da ifade etti\u011fimiz gibi sade ve sadece token \u00fcretiminden sorumlu bir servistir. &#8216;Startup.cs&#8217; dosyas\u0131nda Authentication servisini eklemek demek, bu uygulamada kimlik do\u011frulama i\u015flemi yap\u0131lacak demektir. Halbuki bizler sadece token \u00fcretece\u011fiz. Amma velakin &#8216;ProductAPI&#8217;, &#8216;CustomerAPI&#8217; ve &#8216;APIGateway&#8217; sevislerinde kullan\u0131c\u0131 denetimi sa\u011flanaca\u011f\u0131 i\u00e7in &#8216;Startup.cs&#8217; dosyas\u0131nda authentication mod\u00fcl\u00fc y\u00fcklenecek ve b\u00f6ylece gelen isteklerde kimlik do\u011frulama i\u015flemleri aktifle\u015ftirilmi\u015f olacakt\u0131r.<\/p>\n<p>&#8216;AuthAPI&#8217; projesini de geli\u015ftirdikten sonra s\u0131ra &#8216;ProductAPI&#8217; ve &#8216;CustomerAPI&#8217; projelerine gelmi\u015f bulunmaktad\u0131r. \u00d6rneklendirmemizde authentication yap\u0131lanmas\u0131n\u0131n \u00e7al\u0131\u015f\u0131p \u00e7al\u0131\u015fmad\u0131\u011f\u0131n\u0131 daha net test edebilmek i\u00e7in bu projelerden birinde(ProductAPI) authorize ile kontrol i\u015flemi ger\u00e7ekle\u015ftirecek, di\u011ferinde(CustomerAPI) ise serbest eri\u015fim sa\u011flayaca\u011f\u0131z.<\/p>\n<p><u>ProductAPI;<\/u><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n   &#x5B;ApiController]\r\n   &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n   &#x5B;Authorize]\r\n   public class ProductsController : ControllerBase\r\n   {\r\n      public IActionResult Get()\r\n      {\r\n         return Ok(new List&lt;string&gt; {\r\n           &quot;Telefon&quot;, &quot;Terlik&quot;, &quot;Kalem&quot;, &quot;Ka\u011f\u0131t&quot;, &quot;Ampul&quot;, &quot;Ka\u011f\u0131t&quot;\r\n         });\r\n      }\r\n   }\r\n<\/pre>\n<p>Yukar\u0131da bahsedildi\u011fi gibi \u00fcr\u00fcn i\u015flemlerini ger\u00e7ekle\u015ftirece\u011fimiz &#8216;ProductAPI&#8217; i\u00e7erisindeki olu\u015fturulan bu farazi controller&#8217;da authorize i\u015flemi yap\u0131lmaktad\u0131r. Dolay\u0131s\u0131yla ilgili uygulama yap\u0131lan isteklerde bir kimlik do\u011frulamas\u0131 ger\u00e7ekle\u015ftirmek zorunda. Bunun i\u00e7in &#8216;Startup.cs&#8217; dosyas\u0131nda a\u015fa\u011f\u0131daki gibi &#8216;AddAuthentication&#8217; ile birlikte &#8216;AddJwtBearer&#8217; servislerinin eklenmesi ve temel konfig\u00fcrasyonlar\u0131n\u0131n yap\u0131lmas\u0131 gerekmektedir;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n   public class Startup\r\n   {\r\n      .\r\n      .\r\n      .\r\n      public void ConfigureServices(IServiceCollection services)\r\n      {\r\n         SymmetricSecurityKey signInKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration&#x5B;&quot;JWT:Security&quot;]));\r\n         string authenticationProviderKey = &quot;TestKey&quot;;\r\n         services.AddAuthentication(option =&gt; option.DefaultAuthenticateScheme = authenticationProviderKey)\r\n             .AddJwtBearer(authenticationProviderKey, options =&gt;\r\n             {\r\n                options.RequireHttpsMetadata = false;\r\n                options.TokenValidationParameters = new TokenValidationParameters\r\n                {\r\n                   ValidateIssuerSigningKey = true,\r\n                   IssuerSigningKey = signInKey,\r\n                   ValidateIssuer = true,\r\n                   ValidIssuer = _configuration&#x5B;&quot;JWT:Issuer&quot;],\r\n                   ValidateAudience = true,\r\n                   ValidAudience = _configuration&#x5B;&quot;JWT:Audience&quot;],\r\n                   ValidateLifetime = true,\r\n                   ClockSkew = TimeSpan.Zero,\r\n                   RequireExpirationTime = true\r\n                };\r\n             });\r\n         services.AddControllers();\r\n      }\r\n\r\n      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n      {\r\n         .\r\n         .\r\n         .\r\n         app.UseAuthentication();\r\n         app.UseAuthorization();\r\n         .\r\n         .\r\n         .\r\n      }\r\n   }\r\n<\/pre>\n<p>Bu servisler sayesinde bizler uygulamaya kimlik do\u011frulama niteli\u011fini kazand\u0131rm\u0131\u015f bulunmaktay\u0131z. Ayr\u0131ca bu sevisleri ekleyebilmek i\u00e7in &#8216;AuthAPI&#8217;da oldu\u011fu gibi bu uygulamayada  &#8216;<a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.IdentityModel.Tokens\/\" rel=\"noopener noreferrer\" target=\"_blank\">Microsoft.IdentityModel.Tokens<\/a>&#8216; ve &#8216;<a href=\"https:\/\/www.nuget.org\/packages\/System.IdentityModel.Tokens.Jwt\" rel=\"noopener noreferrer\" target=\"_blank\">System.IdentityModel.Tokens.Jwt<\/a>&#8216; k\u00fct\u00fcphanelerinin yan\u0131nda <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.Authentication.JwtBearer\" rel=\"noopener noreferrer\" target=\"_blank\">Microsoft.AspNetCore.Authentication.JwtBearer<\/a> k\u00fct\u00fcphanesinin eklenmesi gerekmektedir.<\/p>\n<blockquote><p>\n<code style=\"color:red;\">dotnet add package Microsoft.IdentityModel.Tokens<\/code><br \/>\n<code style=\"color:red;\">dotnet add package System.IdentityModel.Tokens.Jwt<\/code><br \/>\n<code style=\"color:red;\">dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer<\/code>\n<\/p><\/blockquote>\n<p>Velhas\u0131l yukar\u0131daki kod blo\u011funu inceledi\u011fimizde, <em><strong>11.<\/strong><\/em> sat\u0131rdaki &#8216;AddJwtBearer&#8217; servisine &#8216;authenticationProviderKey&#8217; de\u011fi\u015fkenindeki &#8216;TestKey&#8217; de\u011ferinin verildi\u011fine dikkatinizi \u00e7ekerim. Bu de\u011fer bizler i\u00e7in kimlik do\u011frulama s\u00fcrecinde bir authentication scheme g\u00f6revi g\u00f6recektir. \u0130\u00e7eri\u011fimizin devam\u0131nda &#8216;APIGateway&#8217; projesi i\u00e7inde yapaca\u011f\u0131m\u0131z birebir ayn\u0131 konfig\u00fcrasyonlar neticesinde, gelen ve Ocelot taraf\u0131ndan do\u011frulanacak iste\u011fi bu \u015fema ile ay\u0131rt edebilecek ve &#8216;ProductAPI&#8217; ile ili\u015fkilendirece\u011fiz. B\u00f6ylece orada(APIGateway) do\u011frulanan token burada da(ProductAPI) do\u011frulanm\u0131\u015f olacakt\u0131r. Ayriyetten <em><strong>35<\/strong><\/em> ve <em><strong>36.<\/strong><\/em> sat\u0131rlara g\u00f6z atarsan\u0131z e\u011fer &#8216;UseAuthentication&#8217; ve &#8216;UseAuthorization&#8217; middleware&#8217;leri \u00e7a\u011fr\u0131larak uygulamada \u00fczerine \u00e7al\u0131\u015f\u0131lan t\u00fcm servisler i\u015flevsel hale getirilmi\u015f olmaktad\u0131r.<\/p>\n<p>Son olarak &#8216;appsettings.json&#8217; dosyas\u0131na a\u015fa\u011f\u0131daki konfig\u00fcrasyon datalar\u0131n\u0131 yerle\u015ftirelim.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n  &quot;JWT&quot;: {\r\n    &quot;Security&quot;: &quot;ocelot authentication example project&quot;,\r\n    &quot;Issuer&quot;: &quot;https:\/\/localhost:4000&quot;,\r\n    &quot;Audience&quot;: &quot;Ocelot Example&quot;\r\n  }\r\n<\/pre>\n<p>Burada dikkat edilmesi gereken m\u00fchim bir husus mevcuttur! O da \u015fudur ki, token de\u011ferini \u00fcreten servisteki(AuthAPI) konfig\u00fcrasyon de\u011ferleri ile bu token&#8217;\u0131 kullanacak olan t\u00fcm servislerdeki konfig\u00fcrasyon de\u011ferlerinin birebir ayn\u0131 olmas\u0131 gerekti\u011fidir. Bunun nedeni, do\u011frulama esnas\u0131nda ilgili servisin gelen token&#8217;da ki \u015fifrelenmi\u015f datalar\u0131n\u0131n ge\u00e7erlili\u011fini verilen datalarla check etmesidir.<\/p>\n<blockquote style=\"color:purple;\"><p><strong><em>Token \u00fcreten servis ile o token&#8217;\u0131 kullanan servisler ayn\u0131 konfig\u00fcrasyon de\u011ferlerini baz almal\u0131d\u0131rlar.<\/em><\/strong><\/p><\/blockquote>\n<p><u>CustomerAPI;<\/u><br \/>\n&#8216;CustomerAPI&#8217; uygulamas\u0131 i\u00e7erisinde ise a\u015fa\u011f\u0131daki gibi bir controller tasarlanmas\u0131 i\u00e7eri\u011fimiz a\u00e7\u0131s\u0131ndan olduk\u00e7a yeterli olacakt\u0131r;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n   &#x5B;ApiController]\r\n   &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n   public class CustomersController : ControllerBase\r\n   {\r\n      public IActionResult Get()\r\n      {\r\n         return Ok(new List&lt;string&gt; {\r\n            &quot;Hilmi&quot;, &quot;H\u00fcseyin&quot;, &quot;R\u0131fk\u0131&quot;, &quot;Necati&quot;, &quot;\u015euayip&quot;, &quot;Muallim&quot;, &quot;Muiddin&quot;\r\n         });\r\n      }\r\n   }\r\n<\/pre>\n<p>\u0130lgili serviste herhangi bir authentication i\u015flemi yapmayaca\u011f\u0131m\u0131z\u0131 yukar\u0131daki sat\u0131rlarda belirtti\u011fimizden dolay\u0131 geli\u015ftirilmesi bu kadard\u0131r&#8230;<\/p>\n<p>\u015eimdi olu\u015fturdu\u011fumuz servisleri test etmek i\u00e7in hepsini <code style=\"color:red;\"><strong>dotnet build<\/strong><\/code> komutu ile derleyelim ve ard\u0131ndan <code style=\"color:red;\"><strong>dotnet run<\/strong><\/code> komutuyla aya\u011fa kald\u0131ral\u0131m. Ard\u0131ndan Postman uygulamas\u0131 arac\u0131l\u0131\u011f\u0131yla her bir servise ayr\u0131 ayr\u0131 ve biryandan da Ocelot arac\u0131l\u0131\u011f\u0131yla isteklerde bulunal\u0131m. B\u00f6ylece geli\u015ftirmede yapmam\u0131z gereken eksiklikleri daha rahat g\u00f6rebilecek ve taraf\u0131mca izah edebilece\u011fiz.<br \/>\nAyr\u0131 ayr\u0131 yap\u0131lan istekler;<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri.gif\" alt=\".NET Core Microservices - Ocelot \u0130le Authentication \u0130\u015flemleri\" width=\"800\" height=\"457\" class=\"aligncenter size-full wp-image-18146\" \/><\/a><br \/>\nYukar\u0131daki ekran g\u00f6r\u00fcnt\u00fcs\u00fcn\u00fc incelerseniz e\u011fer &#8216;ProductAPI&#8217; servisi d\u0131\u015f\u0131ndaki di\u011fer servisler kusursuz \u00e7al\u0131\u015fmaktad\u0131rlar. S\u00f6z konusu servis ise yap\u0131lan authentication konfig\u00fcrasyonundan dolay\u0131 \u015f\u00f6yle bir hata vermektedir;<\/p>\n<blockquote><p><em style=\"color:red;\"><br \/>\nSystem.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).<br \/>\n<\/em><\/p><\/blockquote>\n<p>Bu hatan\u0131n kayna\u011f\u0131 ilgili serviste yap\u0131lan authentication konfig\u00fcrasyonunun &#8216;TestKey&#8217; gibi farkl\u0131 bir \u015fema ismiyle isimlendirilmesidir. E\u011fer ki \u015fema ad\u0131 &#8216;Bearer&#8217; olsayd\u0131 bu hata ortadan kalkacak lakin herhangi bir token ile talepte bulunulmad\u0131\u011f\u0131ndan dolay\u0131 klasik 401 hatas\u0131 kar\u015f\u0131m\u0131za gelecekti. \u015eimdi yap\u0131lan bu \u00e7al\u0131\u015fmay\u0131 Ocelot \u00fczerinden test edelim ve tek tek t\u00fcm servislere istek g\u00f6nderelim.<\/p>\n<p>Ocelot arac\u0131l\u0131\u011f\u0131yla yap\u0131lan istekler;<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri-1.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri-1.gif\" alt=\".NET Core Microservices - Ocelot \u0130le Authentication \u0130\u015flemleri\" width=\"800\" height=\"457\" class=\"aligncenter size-full wp-image-18150\" \/><\/a><br \/>\nYukar\u0131daki ekran g\u00f6r\u00fcnt\u00fcs\u00fcn\u00fc de incelerseniz e\u011fer Ocelot \u00fczerinden(APIGateway) yap\u0131lan t\u00fcm istek y\u00f6nlendirmelerinde yine sadece &#8216;ProductAPI&#8217; hata vermektedir. Hatan\u0131n kayna\u011f\u0131 ve mesaj\u0131 \u00f6ncekiyle birebir ayn\u0131d\u0131r. Haliyle, istek Ocelot&#8217;dan da gelse de\u011fi\u015fen bi\u015fey olmamakta ve tekrardan hatayla kar\u015f\u0131la\u015f\u0131lmaktad\u0131r. \u0130\u015fte bu durumda Ocelot \u00fczerinden \u015femaya uygun authorization konfig\u00fcrasyonunun yap\u0131lmas\u0131 yeterli olacak ve hata ortadan kald\u0131r\u0131lacakt\u0131r. Bunun i\u00e7in &#8216;APIGateway&#8217; projesindeki &#8216;ocelot.json&#8217; dosyas\u0131nda a\u015fa\u011f\u0131daki ayarlaman\u0131n yap\u0131lmas\u0131 gerekmektedir;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n   &quot;Routes&quot;: &#x5B;\r\n      {\r\n         &quot;DownstreamPathTemplate&quot;: &quot;\/api\/products&quot;,\r\n         &quot;DownstreamScheme&quot;: &quot;https&quot;,\r\n         &quot;DownstreamHostAndPorts&quot;: &#x5B;\r\n             {\r\n                 &quot;Host&quot;: &quot;localhost&quot;,\r\n                 &quot;Port&quot;: 1000\r\n             }\r\n         ],\r\n         &quot;UpstreamPathTemplate&quot;: &quot;\/api\/products&quot;,\r\n         &quot;UpstreamHttpMethod&quot;: &#x5B; &quot;Get&quot; ],\r\n         &quot;AuthenticationOptions&quot;: {\r\n            &quot;AuthenticationProviderKey&quot;: &quot;TestKey&quot;,\r\n            &quot;AllowedScopes&quot;: &#x5B;]\r\n          }\r\n      },\r\n      {\r\n         &quot;DownstreamPathTemplate&quot;: &quot;\/api\/customers&quot;,\r\n         &quot;DownstreamScheme&quot;: &quot;https&quot;,\r\n         &quot;DownstreamHostAndPorts&quot;: &#x5B;\r\n             {\r\n                 &quot;Host&quot;: &quot;localhost&quot;,\r\n                 &quot;Port&quot;: 2000\r\n             }\r\n         ],\r\n         &quot;UpstreamPathTemplate&quot;: &quot;\/api\/customers&quot;,\r\n         &quot;UpstreamHttpMethod&quot;: &#x5B; &quot;Get&quot; ]\r\n      },\r\n      {\r\n         &quot;DownstreamPathTemplate&quot;: &quot;\/api\/auths&quot;,\r\n         &quot;DownstreamScheme&quot;: &quot;https&quot;,\r\n         &quot;DownstreamHostAndPorts&quot;: &#x5B;\r\n             {\r\n                 &quot;Host&quot;: &quot;localhost&quot;,\r\n                 &quot;Port&quot;: 3000\r\n             }\r\n         ],\r\n         &quot;UpstreamPathTemplate&quot;: &quot;\/api\/auths&quot;,\r\n         &quot;UpstreamHttpMethod&quot;: &#x5B; &quot;Get&quot; ]\r\n      }\r\n   ],\r\n   &quot;GlobalConfiguration&quot;: {\r\n       &quot;BaseUrl&quot;: &quot;https:\/\/localhost:4000&quot;\r\n   }\r\n}\r\n<\/pre>\n<p>Burada <strong><em>14<\/em><\/strong> ile <strong><em>17.<\/em><\/strong> sat\u0131rlar aras\u0131na dikkatimizi \u00e7ekersek e\u011fer &#8216;ProductAPI&#8217; route&#8217;una \u00f6zel bir &#8216;AuthenticationOptions&#8217; tan\u0131mland\u0131\u011f\u0131n\u0131 g\u00f6rece\u011fiz. Hemen ilgili alan\u0131 hususi olarak a\u015fa\u011f\u0131ya al\u0131rsak e\u011fer;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n         &quot;AuthenticationOptions&quot;: {\r\n            &quot;AuthenticationProviderKey&quot;: &quot;TestKey&quot;,\r\n            &quot;AllowedScopes&quot;: &#x5B;]\r\n          }\r\n<\/pre>\n<p>g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere ilgili route&#8217;a bir authentication konfig\u00fcrasyonu sa\u011flamaktad\u0131r. &#8216;AuthenticationProviderKey&#8217; alan\u0131 ile hangi \u015fema \u00fczerinden kimlik do\u011frulama i\u015flemi yap\u0131laca\u011f\u0131 bildirilmektedir. Ayriyetten bu tan\u0131mlaman\u0131n sade ve sadece authentication i\u015flemi yap\u0131lan route&#8217;lara yap\u0131lmas\u0131 gerekti\u011fini \u00f6zellikle vurgulamakta fayda g\u00f6rmekteyim.<\/p>\n<p>Bu konfig\u00fcrasyondan sonra &#8216;APIGateway&#8217; uygulamas\u0131na da ayn\u0131 \u015fema ad\u0131nda authentication servisinin dahil edilmesi gerekmektedir;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n   public class Startup\r\n   {\r\n      .\r\n      .\r\n      .\r\n      public void ConfigureServices(IServiceCollection services)\r\n      {\r\n         SymmetricSecurityKey signInKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration&#x5B;&quot;JWT:Security&quot;]));\r\n\r\n         string authenticationProviderKey = &quot;TestKey&quot;;\r\n         services.AddAuthentication(option =&gt; option.DefaultAuthenticateScheme = authenticationProviderKey)\r\n             .AddJwtBearer(authenticationProviderKey, options =&gt;\r\n             {\r\n                options.RequireHttpsMetadata = false;\r\n                options.TokenValidationParameters = new TokenValidationParameters\r\n                {\r\n                   ValidateIssuerSigningKey = true,\r\n                   IssuerSigningKey = signInKey,\r\n                   ValidateIssuer = true,\r\n                   ValidIssuer = _configuration&#x5B;&quot;JWT:Issuer&quot;],\r\n                   ValidateAudience = true,\r\n                   ValidAudience = _configuration&#x5B;&quot;JWT:Audience&quot;],\r\n                   ValidateLifetime = true,\r\n                   ClockSkew = TimeSpan.Zero,\r\n                   RequireExpirationTime = true\r\n                };\r\n             });\r\n         services.AddOcelot();\r\n         .\r\n         .\r\n         .\r\n      }\r\n\r\n      public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n      {\r\n         .\r\n         .\r\n         .\r\n         app.UseAuthentication();\r\n         app.UseAuthorization();\r\n         await app.UseOcelot();\r\n         .\r\n         .\r\n         .\r\n      }\r\n   }\r\n<\/pre>\n<p>T\u00fcm bu geli\u015ftirmelerden sonra servisleri derleyip, \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131m\u0131zda a\u015fa\u011f\u0131daki gibi bir i\u015flevsellikle kar\u015f\u0131la\u015faca\u011f\u0131z.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri-2.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/NET-Core-Microservices-Ocelot-Ile-Authentication-Islemleri-2.gif\" alt=\".NET Core Microservices - Ocelot \u0130le Authentication \u0130\u015flemleri\" width=\"800\" height=\"457\" class=\"aligncenter size-full wp-image-18156\" \/><\/a><br \/>\nG\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere istek neticesinde token ge\u00e7erliyse hedef data, aksi taktirde 401 durum kodu d\u00f6nd\u00fcr\u00fclmektedir.<\/p>\n<h3 style=\"color:#e83e8c;\">Alternatif Tasar\u0131m<\/h3>\n<p>T\u00fcm servislerde authentication konfig\u00fcrasyonu i\u00e7in \u015femaya alternatif olarak default de\u011feri kullanabilirsiniz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n         SymmetricSecurityKey signInKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration&#x5B;&quot;JWT:Security&quot;]));\r\n\r\n         services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)\r\n             .AddJwtBearer( options =&gt;\r\n             {\r\n                options.RequireHttpsMetadata = false;\r\n                options.TokenValidationParameters = new TokenValidationParameters\r\n                {\r\n                   ValidateIssuerSigningKey = true,\r\n                   IssuerSigningKey = signInKey,\r\n                   ValidateIssuer = true,\r\n                   ValidIssuer = _configuration&#x5B;&quot;JWT:Issuer&quot;],\r\n                   ValidateAudience = true,\r\n                   ValidAudience = _configuration&#x5B;&quot;JWT:Audience&quot;],\r\n                   ValidateLifetime = true,\r\n                   ClockSkew = TimeSpan.Zero,\r\n                   RequireExpirationTime = true\r\n                };\r\n             });\r\n<\/pre>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n         &quot;AuthenticationOptions&quot;: {\r\n            &quot;AuthenticationProviderKey&quot;: &quot;Bearer&quot;,\r\n            &quot;AllowedScopes&quot;: &#x5B;]\r\n          }\r\n<\/pre>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not: \u00d6rnek uygulamay\u0131 indirmek i\u00e7in <a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/10\/OcelotAuthenticationExample.zip\">buraya<\/a> t\u0131klay\u0131n\u0131z.<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, \u00d6nceki .NET Core Microservices \u2013 Ocelot API Gateway ba\u015fl\u0131kl\u0131 makalemizde bir Gateway k\u00fct\u00fcphanesi olan Ocelot&#8217;un; microservice&#8217;ler aras\u0131 ge\u00e7i\u015f g\u00f6revi g\u00f6ren sorumlulu\u011fundan, deploy tasar\u0131mlar\u0131ndan, pratik olarak nas\u0131l kullan\u0131ld\u0131\u011f\u0131ndan ve daha bir\u00e7ok \u00f6zelli\u011finden detayl\u0131ca bahsetmi\u015f&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":18075,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3573],"tags":[3825,3824],"class_list":["post-18073","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microservices","tag-microservice-authentication","tag-ocelot-authentication"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/18073","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=18073"}],"version-history":[{"count":84,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/18073\/revisions"}],"predecessor-version":[{"id":18162,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/18073\/revisions\/18162"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/18075"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=18073"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=18073"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=18073"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}