﻿
{"id":26411,"date":"2023-07-17T21:17:09","date_gmt":"2023-07-17T21:17:09","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=26411"},"modified":"2023-07-17T21:17:09","modified_gmt":"2023-07-17T21:17:09","slug":"openiddict-5-refresh-token","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/openiddict-5-refresh-token\/","title":{"rendered":"OpenIddict #5 &#8211; Refresh Token"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde OpenIddict k\u00fct\u00fcphanesinde refresh token kullan\u0131m\u0131n\u0131 nas\u0131l etkinle\u015ftirebilece\u011fimizi inceliyor olaca\u011f\u0131z.<\/p>\n<h3>Refresh Token Neydi?<\/h3>\n<p>Malumunuz refresh token, OAuth 2.0 tabanl\u0131 bir yetkilendirme mekanizmas\u0131d\u0131r. Access token&#8217;\u0131n ge\u00e7erlilik s\u00fcresi sona erdi\u011fi taktirde, kullan\u0131c\u0131y\u0131 login ekran\u0131na y\u00f6nlendirmeye gerek kalmaks\u0131z\u0131n, yani kullan\u0131c\u0131n\u0131n yapt\u0131\u011f\u0131 i\u015fin oda\u011f\u0131n\u0131 bozmaks\u0131z\u0131n yeniden bir access token alabilmesini sa\u011flayan bir davran\u0131\u015fa sahiptir. Yap\u0131sal olarak access token&#8217;dan daha uzun \u00f6m\u00fcrl\u00fc olan refresh token&#8217;lar uzun s\u00fcreli oturumlar\u0131 y\u00f6netmek i\u00e7in yayg\u0131n olarak kullan\u0131lmaktad\u0131rlar.<\/p>\n<h3>Refresh Token&#8217;\u0131 Etkinle\u015ftirme<\/h3>\n<p>Uygulaman\u0131zda OpenIddict ile refresh token&#8217;\u0131 etkinle\u015ftirebilmek i\u00e7in Authorization Server&#8217;da <code>AllowRefreshTokenFlow<\/code> fonksiyonu e\u015fli\u011finde a\u015fa\u011f\u0131daki gibi refresh token ak\u0131\u015f\u0131n\u0131 yap\u0131land\u0131rman\u0131z gerekmektedir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing Microsoft.AspNetCore.Authentication.Cookies;\r\nusing Microsoft.EntityFrameworkCore;\r\nusing OpenIddict.RefreshToken.Example.AuthorizationServer.Models;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddControllersWithViews();\r\n\r\nbuilder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)\r\n    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =&gt; options.LoginPath = &quot;\/account\/login&quot;);\r\n\r\nbuilder.Services.AddOpenIddict()\r\n    .AddCore(options =&gt; options.UseEntityFrameworkCore()\r\n                               .UseDbContext&lt;ApplicationDbContext&gt;())\r\n    .AddServer(options =&gt;\r\n    {\r\n        options.SetTokenEndpointUris(&quot;\/connect\/token&quot;)\r\n               .\r\n               .\r\n               .\r\n\r\n               .AllowClientCredentialsFlow()\r\n               .AllowAuthorizationCodeFlow()\r\n               .AllowRefreshTokenFlow()\r\n\r\n               .\r\n               .\r\n               .\r\n\r\n        options.RegisterScopes(&quot;read&quot;, &quot;write&quot;);\r\n    });\r\n\r\n.\r\n.\r\n.\r\napp.Run();\r\n\r\n<\/pre>\n<\/div>\n<p>Devam\u0131nda ise yine Authorization Server&#8217;daki &#8216;AuthorizationController&#8217; i\u00e7erisindeki <code>Exchange<\/code> fonksiyonunda a\u015fa\u011f\u0131daki gibi refresh token operasyonlar\u0131n\u0131 ger\u00e7ekle\u015ftiriniz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class AuthorizationController : Controller\r\n    {\r\n        .\r\n        .\r\n        .\r\n\r\n        &#x5B;HttpPost(&quot;~\/connect\/token&quot;)]\r\n        public async Task&lt;IActionResult&gt; Exchange()\r\n        {\r\n            var request = HttpContext.GetOpenIddictServerRequest();\r\n            ClaimsPrincipal principal = null;\r\n            if (request?.IsAuthorizationCodeFlow() is not null)\r\n            {\r\n                .\r\n                .\r\n                .\r\n            }\r\n            else if (request?.IsRefreshTokenGrantType() is not null)\r\n            {\r\n                principal = (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)).Principal;\r\n\r\n                principal.AddClaim(Claims.Name, &quot;Gen\u00e7ay&quot;);\r\n                principal.AddClaim(Claims.Profile, &quot;Gen\u00e7ay Profile&quot;);\r\n                principal.AddClaim(Claims.Email, &quot;Gen\u00e7ay Email&quot;);\r\n                principal.AddClaim(&quot;ornek-claim&quot;, &quot;\u00d6rnek Claim&quot;);\r\n                principal.AddClaim(JwtRegisteredClaimNames.Aud, &quot;Example-OpenIddict&quot;);\r\n\r\n                foreach (var claim in principal.Claims)\r\n                    claim.SetDestinations(Destinations.AccessToken, Destinations.IdentityToken);\r\n\r\n                \/\/Principal'\u0131 yani kullan\u0131c\u0131y\u0131 do\u011frula\r\n                \/\/if ((await _userManager.GetUserAsnyc(principal)) != null)\r\n                \/\/{\r\n\r\n                \/\/}\r\n            }\r\n            else if (request?.IsClientCredentialsGrantType() is not null)\r\n            {\r\n                .\r\n                .\r\n                .\r\n            }\r\n            else\r\n                throw new NotImplementedException(&quot;The specified grant type is not implemented.&quot;);\r\n            return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Authorization Server&#8217;da refresh token yap\u0131land\u0131rmas\u0131n\u0131 ger\u00e7ekle\u015ftirdikten sonra gerisi art\u0131k client taraf\u0131ndaki \u00e7al\u0131\u015fmalara kalmaktad\u0131r. Bizler burada izafi olarak refresh token&#8217;\u0131 kullanmay\u0131 ele alacak ve \u00f6ylece i\u00e7eri\u011fimizi sonland\u0131r\u0131yor olaca\u011f\u0131z.<\/p>\n<p>Misal olarak, client uygulamas\u0131n\u0131n &#8216;Index.cshtml&#8217; dosyas\u0131na a\u015fa\u011f\u0131daki gibi refresh token talebinde bulunabilece\u011fimiz bir adres eklememiz ve &#8216;AuthenticationController&#8217; i\u00e7erisinde gerekli \u00e7al\u0131\u015fmalar\u0131 yapmam\u0131z refresh token&#8217;\u0131 uygulama \u00e7ap\u0131nda test edebilmek i\u00e7in gayet yerinde olacakt\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n-- Index.cshtml\r\n\r\n@model string\r\n\r\n@{\r\n    ViewData&#x5B;&quot;Title&quot;] = &quot;Home Page&quot;;\r\n}\r\n\r\n&lt;div class=&quot;text-center&quot;&gt;\r\n    &lt;h1 class=&quot;display-4&quot;&gt;Welcome&lt;\/h1&gt;\r\n    &lt;p&gt;Learn about &lt;a href=&quot;https:\/\/docs.microsoft.com\/aspnet\/core&quot;&gt;building Web apps with ASP.NET Core&lt;\/a&gt;.&lt;\/p&gt;\r\n&lt;\/div&gt;\r\n\r\n&lt;form asp-action=&quot;Index&quot; asp-controller=&quot;Home&quot; asp-route-button=&quot;GET&quot;&gt;\r\n    &lt;button&gt;Get \u0130stek Yap&lt;\/button&gt;\r\n&lt;\/form&gt;\r\n\r\n&lt;form asp-action=&quot;Index&quot; asp-controller=&quot;Home&quot; asp-route-button=&quot;POST&quot;&gt;\r\n    &lt;button&gt;Post \u0130stek Yap&lt;\/button&gt;\r\n&lt;\/form&gt;\r\n\r\n&lt;form asp-action=&quot;Logout&quot; asp-controller=&quot;Authentication&quot; method=&quot;post&quot;&gt;\r\n    &lt;button class=&quot;btn btn-lg btn-danger&quot; type=&quot;submit&quot;&gt;Sign out&lt;\/button&gt;\r\n&lt;\/form&gt;\r\n\r\n&lt;a asp-action=&quot;Refresh&quot; asp-controller=&quot;Authentication&quot;&gt;Refresh Token&lt;\/a&gt;\r\n\r\n@if (ViewBag.Properties is not null)\r\n{\r\n    &lt;ul&gt;\r\n        @foreach (var property in ViewBag.Properties as IOrderedEnumerable&lt;KeyValuePair&lt;string, string&gt;&gt;)\r\n        {\r\n            &lt;li&gt;@property.Key ====&gt; @property.Value&lt;\/li&gt;\r\n        }\r\n    &lt;\/ul&gt;\r\n}\r\n\r\n&lt;p&gt;\r\n    @Model\r\n&lt;\/p&gt;\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing IdentityModel.Client;\r\nusing Microsoft.AspNetCore.Authentication;\r\nusing Microsoft.AspNetCore.Authentication.Cookies;\r\nusing Microsoft.AspNetCore.Mvc;\r\nusing Microsoft.IdentityModel.Protocols.OpenIdConnect;\r\nusing OpenIddict.Client.AspNetCore;\r\nusing System.Security.Claims;\r\nusing static OpenIddict.Abstractions.OpenIddictConstants;\r\n\r\nnamespace OpenIddict.RefreshToken.Example.Client1.Controllers\r\n{\r\n    public class AuthenticationController : Controller\r\n    {\r\n        &#x5B;HttpGet(&quot;~\/login&quot;)]\r\n        public IActionResult LogIn(string returnUrl)\r\n        {\r\n            var properties = new AuthenticationProperties(new Dictionary&lt;string, string?&gt;\r\n            {\r\n                &#x5B;OpenIddictClientAspNetCoreConstants.Properties.Issuer] = &quot;https:\/\/localhost:7249&quot;\r\n            });\r\n            properties.RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : &quot;\/&quot;;\r\n\r\n            \/\/Challenge metodu ile OpenIddict middleware'\u0131 sayesinde ilgili Issuer'a kar\u015f\u0131l\u0131k gelen client bilgilerini authorization server'a y\u00f6nlendiriyoruz.\r\n            return Challenge(properties, OpenIddictClientAspNetCoreDefaults.AuthenticationScheme);\r\n        }\r\n\r\n        &#x5B;HttpPost(&quot;~\/logout&quot;), ValidateAntiForgeryToken]\r\n        public async Task&lt;ActionResult&gt; LogOut(string returnUrl)\r\n        {\r\n            \/\/Elde bulunan authentication cookie bilgilerini elde ediyoruz. E\u011fer yoksa zaten kullan\u0131c\u0131n\u0131n hen\u00fcz oturum a\u00e7mad\u0131\u011f\u0131n\u0131 anl\u0131yoruz.\r\n            var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);\r\n            if (result is not { Succeeded: true })\r\n                return Redirect(Url.IsLocalUrl(returnUrl) ? returnUrl : &quot;\/&quot;);\r\n\r\n            \/\/SignOut yaparak mevcut authentication cookie bilgilerini temizliyoruz.\r\n            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);\r\n\r\n            var properties = new AuthenticationProperties(new Dictionary&lt;string, string?&gt;\r\n            {\r\n                &#x5B;OpenIddictClientAspNetCoreConstants.Properties.Issuer] = &quot;https:\/\/localhost:7249&quot;,\r\n                &#x5B;OpenIddictClientAspNetCoreConstants.Properties.IdentityTokenHint] = result.Properties.GetTokenValue(OpenIddictClientAspNetCoreConstants.Tokens.BackchannelIdentityToken)\r\n            });\r\n            properties.RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : &quot;\/&quot;;\r\n\r\n            return SignOut(properties, OpenIddictClientAspNetCoreDefaults.AuthenticationScheme);\r\n        }\r\n\r\n        &#x5B;HttpGet(&quot;~\/callback\/login\/{provider}&quot;), HttpPost(&quot;~\/callback\/login\/{provider}&quot;), IgnoreAntiforgeryToken]\r\n        public async Task&lt;ActionResult&gt; LogInCallback()\r\n        {\r\n            \/\/ OpenIddict taraf\u0131ndan do\u011frulanan yetkilendirme verilerini elde ediyoruz.\r\n            var result = await HttpContext.AuthenticateAsync(OpenIddictClientAspNetCoreDefaults.AuthenticationScheme);\r\n\r\n            if (result.Principal.Identity is not ClaimsIdentity { IsAuthenticated: true })\r\n                throw new InvalidOperationException(&quot;The external authorization data cannot be used for authentication.&quot;);\r\n\r\n            var claims = new List&lt;Claim&gt;(result.Principal.Claims\r\n                             .Select(claim =&gt; claim switch\r\n                             {\r\n                                 { Type: Claims.Subject } =&gt; new Claim(ClaimTypes.NameIdentifier, claim.Value, claim.ValueType, claim.Issuer),\r\n                                 { Type: Claims.Name } =&gt; new Claim(ClaimTypes.Name, claim.Value, claim.ValueType, claim.Issuer),\r\n                                 _ =&gt; claim\r\n                             }));\r\n\r\n            var identity = new ClaimsIdentity(claims,\r\n                authenticationType: CookieAuthenticationDefaults.AuthenticationScheme,\r\n                nameType: ClaimTypes.Name,\r\n                roleType: ClaimTypes.Role);\r\n\r\n            var properties = new AuthenticationProperties(result.Properties.Items);\r\n\r\n            \/\/Gerekirse authorization server taraf\u0131ndan d\u00f6nd\u00fcr\u00fclen tokenlar authentication cookie'de de saklanabilir.\r\n            properties.StoreTokens(result.Properties.GetTokens().Where(token =&gt; token switch\r\n            {\r\n                {\r\n                    Name: OpenIddictClientAspNetCoreConstants.Tokens.BackchannelAccessToken or\r\n                          OpenIddictClientAspNetCoreConstants.Tokens.BackchannelIdentityToken or\r\n                          OpenIddictClientAspNetCoreConstants.Tokens.RefreshToken\r\n                } =&gt; true,\r\n                _ =&gt; false\r\n            }));\r\n\r\n            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), properties);\r\n\r\n            return Redirect(properties.RedirectUri);\r\n        }\r\n\r\n        &#x5B;HttpGet(&quot;~\/callback\/logout\/{provider}&quot;), HttpPost(&quot;~\/callback\/logout\/{provider}&quot;), IgnoreAntiforgeryToken]\r\n        public async Task&lt;ActionResult&gt; LogOutCallback()\r\n        {\r\n            var result = await HttpContext.AuthenticateAsync(OpenIddictClientAspNetCoreDefaults.AuthenticationScheme);\r\n            return Redirect(result!.Properties!.RedirectUri);\r\n        }\r\n\r\n        &#x5B;HttpGet(&quot;~\/refresh&quot;)]\r\n        public async Task&lt;IActionResult&gt; Refresh()\r\n        {\r\n            string refreshToken = await HttpContext.GetTokenAsync(OpenIddictClientAspNetCoreConstants.Tokens.RefreshToken);\r\n            HttpClient httpClient = new HttpClient();\r\n            RefreshTokenRequest refreshTokenRequest = new RefreshTokenRequest()\r\n            {\r\n                ClientId = &quot;my-client1&quot;,\r\n                ClientSecret = &quot;my-client-secret1&quot;,\r\n                RefreshToken = refreshToken,\r\n                Address = (await httpClient.GetDiscoveryDocumentAsync(&quot;https:\/\/localhost:7249&quot;)).TokenEndpoint\r\n            };\r\n            TokenResponse tokenResponse = await httpClient.RequestRefreshTokenAsync(refreshTokenRequest);\r\n            AuthenticationProperties properties = (await HttpContext.AuthenticateAsync()).Properties;\r\n\r\n            properties.StoreTokens(\r\n                new List&lt;AuthenticationToken&gt; {\r\n              new AuthenticationToken\r\n                                     {\r\n                                         Name = OpenIddictClientAspNetCoreConstants.Tokens.BackchannelIdentityToken,\r\n                                         Value = tokenResponse.IdentityToken\r\n                                     },\r\n              new AuthenticationToken\r\n                                     {\r\n                                         Name = OpenIddictClientAspNetCoreConstants.Tokens.BackchannelAccessToken,\r\n                                         Value = tokenResponse.AccessToken\r\n                                     },\r\n              new AuthenticationToken\r\n                                     {\r\n                                         Name = OpenIddictClientAspNetCoreConstants.Tokens.RefreshToken,\r\n                                         Value = tokenResponse.RefreshToken\r\n                                     },\r\n              new AuthenticationToken\r\n                                     {\r\n                                         Name = OpenIdConnectParameterNames.ExpiresIn,\r\n                                         Value = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn).ToString(&quot;O&quot;)\r\n                                     },\r\n                                       });\r\n            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, (await HttpContext.AuthenticateAsync()).Principal, properties);\r\n            return RedirectToAction(&quot;Index&quot;, &quot;Home&quot;);\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>Burada <strong><em>97<\/em><\/strong> ile <strong><em>136.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131na g\u00f6z atarsan\u0131z e\u011fer resfresh token ile ilgili gerekli \u00e7al\u0131\u015fmalar y\u00fcr\u00fct\u00fclmektedir. \u00d6nce <strong><em>99.<\/em><\/strong> sat\u0131rda uygulamadaki refresh token elde edilmekte ve ard\u0131ndan Authorization Server&#8217;a bu refresh token e\u015fli\u011finde yap\u0131lan request neticesinde yeni bilgiler edinilmektedir. Burada dikkat ederseniz <code>RefreshTokenRequest<\/code>, <code>TokenResponse<\/code> vs. gibi s\u0131n\u0131flar\u0131 kullanabilmek yani bu operasyonu sa\u011fl\u0131kl\u0131 bir \u015fekilde y\u00fcr\u00fctebilmek i\u00e7in <a href=\"https:\/\/www.nuget.org\/packages\/IdentityModel\/\" rel=\"noopener\" target=\"_blank\">IdentityModel<\/a> k\u00fct\u00fcphanesinden istifade etmekteyiz. Velhas\u0131l, <strong><em>111<\/em><\/strong> ile <strong><em>133.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131nda ise gelen access token, identity token ve refresh token gibi yeni bilgiler uygulama baz\u0131nda g\u00fcncellenmekte ve <strong><em>134.<\/em><\/strong> sat\u0131rda <code>SignInAsync<\/code> metodu ile g\u00fcncel verilerle tekrardan oturum tazelenmektedir.<\/p>\n<p>Tabi burada client uygulamas\u0131n\u0131n konfig\u00fcrasyonlar\u0131nda da refresh token&#8217;\u0131n a\u015fa\u011f\u0131daki gibi <code>AllowRefreshTokenFlow<\/code> metodu e\u015fli\u011finde aktifle\u015ftirilmesi ve <code>offline_access<\/code> scope&#8217;u e\u015fli\u011finde refresh token de\u011ferinin auth server&#8217;dan talep edilmesi gerekmektedir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\nbuilder.Services.AddOpenIddict()\r\n                .AddCore(options =&gt;\r\n                {\r\n                    options.UseEntityFrameworkCore()\r\n                           .UseDbContext&lt;ApplicationDbContext&gt;();\r\n                })\r\n                .AddClient(options =&gt;\r\n                {\r\n                    options.SetRedirectionEndpointUris(&quot;\/callback\/login\/local&quot;)\r\n                           .SetPostLogoutRedirectionEndpointUris(&quot;\/callback\/logout\/local&quot;)\r\n\r\n                           .AddDevelopmentEncryptionCertificate()\r\n                           .AddDevelopmentSigningCertificate()\r\n\r\n                           .AllowAuthorizationCodeFlow()\r\n                           .AllowRefreshTokenFlow()\r\n\r\n                           .UseAspNetCore()\r\n                            .EnableStatusCodePagesIntegration()\r\n                            .EnableRedirectionEndpointPassthrough()\r\n                            .EnablePostLogoutRedirectionEndpointPassthrough();\r\n\r\n                    options.UseSystemNetHttp();\r\n\r\n                    options.AddRegistration(new OpenIddictClientRegistration\r\n                    {\r\n                        Issuer = new Uri(&quot;https:\/\/localhost:7249&quot;, UriKind.Absolute),\r\n\r\n                        ClientId = &quot;my-client1&quot;,\r\n                        ClientSecret = &quot;my-client-secret1&quot;,\r\n                        Scopes = { &quot;read&quot;, &quot;write&quot;, &quot;offline_access&quot; },\r\n\r\n                        RedirectUri = new Uri(&quot;https:\/\/localhost:7247\/callback\/login\/local&quot;, UriKind.Absolute),\r\n                        PostLogoutRedirectUri = new Uri(&quot;https:\/\/localhost:7247\/callback\/logout\/local&quot;, UriKind.Absolute)\r\n                    }); ;\r\n                })\r\n                .AddValidation(options =&gt;\r\n                {\r\n                    options.UseLocalServer();\r\n                    options.UseAspNetCore();\r\n                });\r\n\r\n.\r\n.\r\napp.Run();\r\n\r\n<\/pre>\n<\/div>\n<p>\u0130\u015fte bu kadar&#8230; <strong><em>19.<\/em><\/strong> sat\u0131rdaki yap\u0131land\u0131rman\u0131n yan\u0131nda <strong><em>34.<\/em><\/strong> sat\u0131rdaki <code>offline_access<\/code> scope&#8217;u e\u015fli\u011finde refresh token talebi ger\u00e7ekle\u015ftirilerek, art\u0131k uygulaman\u0131zda refresh token&#8217;\u0131 kullanabilir ve kullan\u0131c\u0131 aktifken biryandan da oturum s\u00fcrecini g\u00fcncelleyebilirsiniz. Tabi bunun i\u00e7in refresh token iznine sahip yeni bir client olu\u015fturulmas\u0131 gerekecektir. Ee haliyle Authorization Server uygulamas\u0131ndaki &#8216;ClientsController&#8217; i\u00e7erisindeki &#8216;CreateClient&#8217; metodunu a\u015fa\u011f\u0131daki gibi g\u00fcncelleyebilir ve ard\u0131ndan bu ayarlarda aray\u00fcz \u00fczerinden yeni bir client uygulamas\u0131 olu\u015fturabilirsiniz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class ClientsController : Controller\r\n    {\r\n        .\r\n        .\r\n        .\r\n        &#x5B;HttpPost]\r\n        public async Task&lt;IActionResult&gt; CreateClient(ClientCreateVM model)\r\n        {\r\n            if (ModelState.IsValid)\r\n            {\r\n                var client = await _openIddictApplicationManager.FindByClientIdAsync(model.ClientId);\r\n                if (client is null)\r\n                {\r\n                    await _openIddictApplicationManager.CreateAsync(new OpenIddictApplicationDescriptor\r\n                    {\r\n                        ClientId = model.ClientId,\r\n                        ClientSecret = model.ClientSecret,\r\n                        DisplayName = model.DisplayName,\r\n                        RedirectUris = { new(model.RedirectUrl) },\r\n                        PostLogoutRedirectUris = { new(model.PostLogoutRedirectUri) },\r\n                        Permissions = {\r\n                                        OpenIddictConstants.Permissions.Endpoints.Token,\r\n                                        OpenIddictConstants.Permissions.Endpoints.Authorization,\r\n                                        OpenIddictConstants.Permissions.Endpoints.Logout,\r\n\r\n                                        OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,\r\n                                        OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,\r\n                                        OpenIddictConstants.Permissions.GrantTypes.RefreshToken,\r\n\r\n                                        OpenIddictConstants.Permissions.Prefixes.Scope + &quot;read&quot;,\r\n                                        OpenIddictConstants.Permissions.Prefixes.Scope + &quot;write&quot;,\r\n\r\n                                        Permissions.Scopes.Email,\r\n                                        Permissions.Scopes.Profile,\r\n                                        Permissions.Scopes.Roles,\r\n\r\n                                        OpenIddictConstants.Permissions.ResponseTypes.Code\r\n                                      }\r\n                    });\r\n                    ViewBag.Message = &quot;Client ba\u015far\u0131yla olu\u015fturulmu\u015ftur.&quot;;\r\n                }\r\n                else\r\n                    ViewBag.Message = &quot;Client zaten mevcuttur.&quot;;\r\n                return View();\r\n            }\r\n\r\n            ViewBag.Message = &quot;L\u00fctfen client bilgilerini tam giriniz.&quot;;\r\n            return View(model);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p><strong><em>28.<\/em><\/strong> sat\u0131ra g\u00f6z atarsan\u0131z olu\u015fturulacak client&#8217;ta refresh token yetkisi verilmektedir.<\/p>\n<p>T\u00fcm bu \u00e7al\u0131\u015fmalardan sonra art\u0131k uygulamay\u0131 aya\u011fa kald\u0131r\u0131p test edebilirsiniz.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/07\/OpenIddict-5-Refresh-Token.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/07\/OpenIddict-5-Refresh-Token.gif\" alt=\"OpenIddict #5 - Refresh Token\" width=\"800\" height=\"485\" class=\"aligncenter size-full wp-image-26416\" \/><\/a>Yukar\u0131daki ekran g\u00f6r\u00fcnt\u00fcs\u00fcn\u00fc incelerseniz e\u011fer refresh token&#8217;\u0131n ba\u015far\u0131yla \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 g\u00f6zlemleyeceksiniz.<\/p>\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 \u00e7al\u0131\u015fmay\u0131 a\u015fa\u011f\u0131daki github adresinden edinebilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/OpenIddict.RefreshToken.Example\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/OpenIddict.RefreshToken.Example<\/a><\/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, Bu i\u00e7eri\u011fimizde OpenIddict k\u00fct\u00fcphanesinde refresh token kullan\u0131m\u0131n\u0131 nas\u0131l etkinle\u015ftirebilece\u011fimizi inceliyor olaca\u011f\u0131z. Refresh Token Neydi? Malumunuz refresh token, OAuth 2.0 tabanl\u0131 bir yetkilendirme mekanizmas\u0131d\u0131r. Access token&#8217;\u0131n ge\u00e7erlilik s\u00fcresi sona erdi\u011fi taktirde, kullan\u0131c\u0131y\u0131 login ekran\u0131na&#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":3014,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4665],"tags":[4895,4666,4894,4893,3134],"class_list":["post-26411","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-openiddict","tag-offline_access","tag-openiddict","tag-openiddict-offline_access","tag-openiddict-refresh-token","tag-refresh-token"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26411","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=26411"}],"version-history":[{"count":5,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26411\/revisions"}],"predecessor-version":[{"id":26417,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26411\/revisions\/26417"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/3014"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=26411"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=26411"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=26411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}