﻿
{"id":22101,"date":"2021-10-24T10:52:23","date_gmt":"2021-10-24T10:52:23","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=22101"},"modified":"2021-10-24T10:52:23","modified_gmt":"2021-10-24T10:52:23","slug":"asp-net-core-icin-grpcde-authentication-ve-authorization-islemleri","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-icin-grpcde-authentication-ve-authorization-islemleri\/","title":{"rendered":"Asp.NET Core \u0130\u00e7in gRPC&#8217;de Authentication ve Authorization \u0130\u015flemleri"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>gRPC, her ne kadar uzak sunuculardaki metotlar\u0131 sanki kendi ortam\u0131n\u0131n birer par\u00e7as\u0131ym\u0131\u015f gibi \u00e7a\u011f\u0131rabilen sistem olsa da kimlik do\u011frulama(authentication) ve yetkilendirme(authorization) nitelikleri sayesinde bir kullan\u0131c\u0131yla ili\u015fkilendirilebilmekte ve b\u00f6ylece daha korunakl\u0131 ve tan\u0131ml\u0131 veri ak\u0131\u015f\u0131 sa\u011flayabilmektedir. \u00d6zellikle g\u00fcn\u00fcm\u00fczde olduk\u00e7a pop\u00fcler olan JWT&#8217;ye dayal\u0131 yap\u0131land\u0131r\u0131lm\u0131\u015f bir kimlik do\u011frulama sayesinde s\u00fcre\u00e7 daha dinamik hale getirilebilmektedir.<\/p>\n<p>gRPC, gelen istekler \u00fczerinde kimlik do\u011frulamay\u0131 ger\u00e7ekle\u015ftirebilmek i\u00e7in temel Asp.NET Core mimarisinin authentication ve authorization \u00f6zelliklerini kullanarak gerekli yap\u0131lanmay\u0131 sa\u011flamaktad\u0131r. Bunun i\u00e7in yap\u0131lmas\u0131 gereken ilk i\u015f, gRPC Server uygulamas\u0131n\u0131n &#8216;Startup.cs&#8217; dosyas\u0131nda <code>UseAuthentication<\/code> ve <code>UseAuthorization<\/code> middleware&#8217;lerini s\u0131ras\u0131yla \u00e7a\u011f\u0131rmakt\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        .\r\n        .\r\n        .\r\n\r\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n        {\r\n            .\r\n            .\r\n            .\r\n            app.UseRouting();\r\n\r\n            app.UseAuthentication();\r\n            app.UseAuthorization();\r\n\r\n            app.UseEndpoints(endpoints =&gt;\r\n            {\r\n                endpoints.MapGrpcService&lt;MessageService&gt;();\r\n            });\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Ard\u0131ndan yap\u0131lmas\u0131 gereken ikinci i\u015flem ise kullan\u0131lacak kimlik do\u011frulama mekanizmas\u0131n\u0131n yap\u0131land\u0131rmas\u0131n\u0131 olu\u015fturmakt\u0131r. Haliyle bizler burada ilk paragrafta verdi\u011fimiz ipucundan da anla\u015f\u0131laca\u011f\u0131 \u00fczere JWT konfig\u00fcrasyonunu \u00f6rneklendirece\u011fiz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddGrpc();\r\n\r\n            services.AddAuthorization();\r\n\r\n            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)\r\n            .AddJwtBearer(options =&gt;\r\n            {\r\n                options.RequireHttpsMetadata = false;\r\n                options.SaveToken = true;\r\n                options.TokenValidationParameters = new()\r\n                {\r\n                    ValidateIssuerSigningKey = true,\r\n                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(&quot;sebepsiz bos yere ayrilacaksan...&quot;)),\r\n                    ValidateIssuer = false,\r\n                    ValidateAudience = false,\r\n                    NameClaimType = &quot;name&quot;\r\n                };\r\n            });\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Misal olarak yukar\u0131daki gibi bir JWT konfig\u00fcrasyonunu ger\u00e7ekle\u015ftirdikten sonra base servislerimizi a\u015fa\u011f\u0131daki gibi <code>Authorize<\/code> attribute&#8217;u ile i\u015faretleyebiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Authorize]\r\n    public class MessageService : MessageBase\r\n    {\r\n        public override async Task GetMessage(MessageRequest request, IServerStreamWriter&lt;MessageResponse&gt; responseStream, ServerCallContext context)\r\n        {\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Art\u0131k bu vaziyette, client taraf\u0131ndan gelecek olan ve do\u011frulanabilir JWT bar\u0131nd\u0131rmayan t\u00fcm istekler gRPC Server taraf\u0131ndan a\u015fa\u011f\u0131daki hatayla reddedilecektir.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/10\/Asp.NET-Core-Icin-gRPCde-Authentication-ve-Authorization-Islemleri.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/10\/Asp.NET-Core-Icin-gRPCde-Authentication-ve-Authorization-Islemleri.png\" alt=\"Asp.NET Core \u0130\u00e7in gRPC&#039;de Authentication ve Authorization \u0130\u015flemleri\" width=\"356\" height=\"68\" class=\"aligncenter size-full wp-image-23432\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/10\/Asp.NET-Core-Icin-gRPCde-Authentication-ve-Authorization-Islemleri.png 356w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/10\/Asp.NET-Core-Icin-gRPCde-Authentication-ve-Authorization-Islemleri-300x57.png 300w\" sizes=\"auto, (max-width: 356px) 100vw, 356px\" \/><\/a><br \/>\nHaliyle bu durumda art\u0131k client, ya gRPC Server&#8217;dan ya da farkl\u0131 bir sunucudan(auth server misali) JWT talebinde bulunmal\u0131d\u0131r. Bunun i\u00e7in a\u015fa\u011f\u0131daki gibi bir JWT handler s\u0131n\u0131f\u0131 tasarlayal\u0131m ve \u00f6rnek olarak gRPC Server uygulamas\u0131 \u00fczerinden bir API a\u00e7arak client&#8217;\u0131n talebi neticesinde JWT&#8217;yi \u00fcretip g\u00f6nderelim.<br \/>\n&#8216;TokenHandler.cs&#8217; :<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public static class TokenHandler\r\n    {\r\n        public static string CreateAccessToken()\r\n        {\r\n            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(&quot;sebepsiz bos yere ayrilacaksan...&quot;));\r\n            SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);\r\n            JwtSecurityToken securityToken = new JwtSecurityToken(\r\n                notBefore: DateTime.Now,\r\n                signingCredentials: signingCredentials,\r\n                claims: new List&lt;Claim&gt; { new(&quot;name&quot;, &quot;Gen\u00e7ay&quot;) },\r\n                expires: DateTime.Now.AddDays(1)\r\n                );\r\n            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();\r\n            string accessToken = tokenHandler.WriteToken(securityToken);\r\n            return accessToken;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>&#8216;AuthController.cs&#8217; :<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class AuthController : ControllerBase\r\n    {\r\n        public IActionResult GetToken()\r\n            =&gt; Ok(TokenHandler.CreateAccessToken());\r\n    }\r\n<\/pre>\n<\/div>\n<p>&#8216;Startup.cs&#8217; :<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            .\r\n            .\r\n            .\r\n            services.AddGrpc();\r\n            services.AddControllers();\r\n            .\r\n            .\r\n            .\r\n        }\r\n\r\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n        {\r\n            .\r\n            .\r\n            .\r\n            app.UseEndpoints(endpoints =&gt;\r\n            {\r\n                endpoints.MapGrpcService&lt;MessageService&gt;();\r\n                endpoints.MapControllers();\r\n            });\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki \u00e7al\u0131\u015fmadan da anla\u015f\u0131laca\u011f\u0131 \u00fczere client, https:\/\/localhost:5001\/api\/auth adresinden JWT talebinde bulunabilecek ve elde etti\u011fi JWT ile a\u015fa\u011f\u0131daki gibi istek g\u00f6nderebilecektir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    class Program\r\n    {\r\n        static async Task Main(string&#x5B;] args)\r\n        {\r\n            var channel = GrpcChannel.ForAddress(&quot;https:\/\/localhost:5001&quot;);\r\n            var messageClient = new Message.MessageClient(channel);\r\n\r\n            var headers = new Metadata();\r\n            headers.Add(&quot;Authorization&quot;, &quot;Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiR2Vuw6dheSIsIm5iZiI6MTYzNTAzMTQzMiwiZXhwIjoxNjM1MTE3ODMyfQ.gIiKIVZugwIcOrW-TQPls6vCvL5klhVYXQllKf1zeJw&quot;);\r\n\r\n            var response = messageClient.GetMessage(new MessageRequest() { Message = &quot;Messajlar\u0131 g\u00f6nder...&quot; }, headers: headers);\r\n            var cancellationToken = new CancellationToken();\r\n            while (await response.ResponseStream.MoveNext(cancellationToken))\r\n                Console.WriteLine(response.ResponseStream.Current.Message);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki kod blo\u011funda 8 ile 11. sat\u0131r aral\u0131\u011f\u0131n\u0131 incelerseniz e\u011fer bir &#8216;Metadata&#8217; t\u00fcr\u00fcnden nesne \u00fcretilmekte ve bu nesneye &#8216;Add&#8217; fonksiyonuyla ilgili JWT verilmektedir. Ard\u0131ndan 11. sat\u0131rda ilgili client nesnesi \u00fczerinden server&#8217;da ki fonksiyonu(GetMessage) tetiklerken &#8216;headers&#8217; parametresine ilgili nesne verilerek kullan\u0131c\u0131 do\u011frulamas\u0131 yap\u0131lmak istenmektedir.<\/p>\n<p>Kimlik do\u011frulamas\u0131 in\u015fa edildikten sonra gRPC Server&#8217;da kullan\u0131c\u0131 bilgilerine eri\u015febilmek i\u00e7in &#8216;ServerCallContext&#8217; t\u00fcr\u00fcnden olan &#8216;context&#8217; parametresi a\u015fa\u011f\u0131daki gibi kullan\u0131labilir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Authorize]\r\n    public class MessageService : MessageBase\r\n    {\r\n        public override async Task GetMessage(MessageRequest request, IServerStreamWriter&lt;MessageResponse&gt; responseStream, ServerCallContext context)\r\n        {\r\n            .\r\n            .\r\n            .\r\n            var user = context.GetHttpContext().User;\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<h5>gRPC Client Factory \u0130le Token Kullan\u0131m\u0131<\/h5>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/grpc-ile-client-factory-integration\/\" target=\"_blank\" rel=\"noopener\">gRPC Client Factory<\/a> ile kimlik do\u011frulamay\u0131 ger\u00e7ekle\u015ftirmek istiyorsan\u0131z e\u011fer bu i\u015flem a\u015fa\u011f\u0131daki gibi basit\u00e7e halledilebilmektedir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            string token = &quot;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiR2Vuw6dheSIsIm5iZiI6MTYzNTAzMTQzMiwiZXhwIjoxNjM1MTE3ODMyfQ.gIiKIVZugwIcOrW-TQPls6vCvL5klhVYXQllKf1zeJw&quot;;\r\n            services.AddGrpcClient&lt;MessageClient&gt;(options =&gt;\r\n            {\r\n                options.Address = new Uri(&quot;https:\/\/localhost:5001&quot;);\r\n            }).ConfigureChannel(options =&gt;\r\n            {\r\n                var credentials = CallCredentials.FromInterceptor((context, metadata) =&gt;\r\n                {\r\n                    if (!string.IsNullOrEmpty(token))\r\n                        metadata.Add(&quot;Authorization&quot;, $&quot;Bearer {token}&quot;);\r\n                    return Task.CompletedTask;\r\n                });\r\n\r\n                options.Credentials = ChannelCredentials.Create(new SslCredentials(), credentials);\r\n            });\r\n            services.AddControllers();\r\n        }\r\n<\/pre>\n<\/div>\n<h5>gRPC Claim Tabanl\u0131 Yetkilendirme<\/h5>\n<p>gRPC \u00e7al\u0131\u015fmalar\u0131nda t\u0131pk\u0131 Asp.NET Core uygulamalar\u0131nda oldu\u011fu gibi <a href=\"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-identity-claim-bazli-kimlik-dogrulama-xvii\/\" rel=\"noopener\" target=\"_blank\">claim tabanl\u0131 yetkilendirme<\/a>leri kolayl\u0131kla ger\u00e7ekle\u015ftirebilmekteyiz. Bunun i\u00e7in a\u015fa\u011f\u0131daki gibi bir politika tan\u0131mlanmas\u0131 yeterlidir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddGrpc();\r\n            .\r\n            .\r\n            .\r\n            services.AddAuthorization(options =&gt;\r\n            {\r\n                options.AddPolicy(&quot;RolePolicy&quot;, policy =&gt; policy.RequireClaim(ClaimTypes.Role, &quot;admin&quot;));\r\n            });\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Bu tan\u0131mdan sonra art\u0131k token \u00fcreticisi, generate edilecek JWT de\u011ferine i\u00e7erisinde role de\u011feri bar\u0131nd\u0131ran bir claim eklemelidir. Farazi olarak a\u015fa\u011f\u0131daki 12. sat\u0131r buna bir \u00f6rnektir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public static class TokenHandler\r\n    {\r\n        public static string CreateAccessToken()\r\n        {\r\n            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(&quot;sebepsiz bos yere ayrilacaksan...&quot;));\r\n            SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);\r\n            JwtSecurityToken securityToken = new JwtSecurityToken(\r\n                notBefore: DateTime.Now,\r\n                signingCredentials: signingCredentials,\r\n                claims: new List&lt;Claim&gt; {\r\n                    new(&quot;name&quot;, &quot;Gen\u00e7ay&quot;) ,\r\n                    new(ClaimTypes.Role,&quot;admin&quot;)\r\n                },\r\n                expires: DateTime.Now.AddDays(1)\r\n                );\r\n            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();\r\n            string accessToken = tokenHandler.WriteToken(securityToken);\r\n            return accessToken;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Ve son olarak <code>Authorize<\/code> attribute&#8217;u ile i\u015faretlenen ilgili gRPC servisinde a\u015fa\u011f\u0131daki gibi olu\u015fturulan politika belirtilmelidir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Authorize(Policy = &quot;RolePolicy&quot;)]\r\n    public class MessageService : MessageBase\r\n    {\r\n        public override async Task GetMessage(MessageRequest request, IServerStreamWriter&lt;MessageResponse&gt; responseStream, ServerCallContext context)\r\n        {\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Tabi burada yetkilendirmeyi metot bazl\u0131 olacak \u015fekilde de yapabilece\u011finizi bildi\u011finizi varsay\u0131yorum.<\/p>\n<h5>gRPC Politika Tabanl\u0131 Yetkilendirme<\/h5>\n<p>Ayr\u0131ca claim bazl\u0131 yetkilendirmenin d\u0131\u015f\u0131nda farkl\u0131 politikalar e\u015fli\u011finde de yetkilendirme usulleri olu\u015fturabilirsiniz. Buna bildi\u011finiz klasik <a href=\"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-identity-politika-bazli-kimlik-dogrulama-xvi\/\" rel=\"noopener\" target=\"_blank\">politika bazl\u0131 yetkilendirme<\/a> denmektedir.<\/p>\n<p>Misal olarak hafta sonu hizmet vermeyecek olan bir gRPC servisi i\u00e7in a\u015fa\u011f\u0131daki gibi bir politika olu\u015fturabiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class DateRequirement : IAuthorizationRequirement\r\n    {\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class DateHandler : AuthorizationHandler&lt;DateRequirement&gt;\r\n    {\r\n        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DateRequirement requirement)\r\n        {\r\n            if (DateTime.Now.DayOfWeek != DayOfWeek.Saturday &amp;&amp; DateTime.Now.DayOfWeek != DayOfWeek.Sunday)\r\n                context.Succeed(requirement);\r\n            else\r\n                context.Fail();\r\n            return Task.CompletedTask;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddGrpc();\r\n            .\r\n            .\r\n            .\r\n            services.AddAuthorization(options =&gt;\r\n            {\r\n                options.AddPolicy(&quot;RolePolicy&quot;, policy =&gt; policy.RequireClaim(ClaimTypes.Role, &quot;admin&quot;));\r\n                options.AddPolicy(&quot;DatePolicy&quot;, policy =&gt; policy.Requirements.Add(new DateRequirement()));\r\n            });\r\n            services.AddSingleton&lt;IAuthorizationHandler, DateHandler&gt;();\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Ard\u0131ndan kullan\u0131m\u0131 yine a\u015fa\u011f\u0131daki gibi olacakt\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Authorize(Policy = &quot;DatePolicy&quot;)]\r\n    public class MessageService : MessageBase\r\n    {\r\n        public override async Task GetMessage(MessageRequest request, IServerStreamWriter&lt;MessageResponse&gt; responseStream, ServerCallContext context)\r\n        {\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\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<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, gRPC, her ne kadar uzak sunuculardaki metotlar\u0131 sanki kendi ortam\u0131n\u0131n birer par\u00e7as\u0131ym\u0131\u015f gibi \u00e7a\u011f\u0131rabilen sistem olsa da kimlik do\u011frulama(authentication) ve yetkilendirme(authorization) nitelikleri sayesinde bir kullan\u0131c\u0131yla ili\u015fkilendirilebilmekte ve b\u00f6ylece daha korunakl\u0131 ve tan\u0131ml\u0131 veri&#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":20414,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4032],"tags":[4327,4328,4329,4325,4326,4428,4427,4429,4426],"class_list":["post-22101","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-grpc","tag-asp-net-core-grpc","tag-asp-net-core-grpc-authentication","tag-asp-net-core-grpc-authorization","tag-grpc-authentication","tag-grpc-authorization","tag-grpc-claim-base-authorization","tag-grpc-claim-tabanli-yetkilendirme","tag-grpc-policy-base-authorization","tag-grpc-politika-tabanli-yetkilendirme"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/22101","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=22101"}],"version-history":[{"count":25,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/22101\/revisions"}],"predecessor-version":[{"id":23448,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/22101\/revisions\/23448"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/20414"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=22101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=22101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=22101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}