{"id":659,"date":"2022-08-05T23:01:40","date_gmt":"2022-08-05T23:01:40","guid":{"rendered":"https:\/\/okankaradag.com\/?p=659"},"modified":"2022-08-05T23:01:40","modified_gmt":"2022-08-05T23:01:40","slug":"net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso","status":"publish","type":"post","link":"https:\/\/okankaradag.com\/en\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso","title":{"rendered":"Single Sign Out in .Net 6.0 and IdentityServer v4"},"content":{"rendered":"<p>In this post, we'll create a centralized login system using IdentityServer, a .NET library, to handle our authentication processes. Various clients will utilize this shared login for access.<\/p>\n\n\n\n<h5 id=\"sso-single-sign-on-nedir\">What is SSO (Single Sign-On)<\/h5>\n\n\n\n<p>It enables centralized control and access with a single set of credentials for our identity and password information. Similar to companies like Google, Microsoft, or Facebook, where we don\u2019t create new usernames or passwords for different applications, but rather access other applications with a single username and password<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" width=\"877\" height=\"329\" src=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/ssologin.png\" alt=\"\" class=\"wp-image-666\" srcset=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/ssologin.png 877w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/ssologin-300x113.png 300w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/ssologin-768x288.png 768w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/ssologin-18x7.png 18w\" sizes=\"(max-width: 877px) 100vw, 877px\" \/><\/figure>\n\n\n\n<h5 id=\"projemizin-yapisi\"> Project Architecture<\/h5>\n\n\n\n<p>We'll create two different project: one will run on .net 6 and identityserver, other will use as client.<\/p>\n\n\n\n<h5 id=\"gelistirme-ortami\">Development Environment<\/h5>\n\n\n\n<ul><li>Windows 11<\/li><li>Visual Studio 2022<\/li><li>.Net 6.0<\/li><\/ul>\n\n\n\n<h5 id=\"projenin-baslangici\">Begin Project<\/h5>\n\n\n\n<p class=\" translation-block\">I'm creating my project with the <strong>.NET 6.0 MVC<\/strong> option because the login page and other identity-related processes for Single Sign-On (SSO) will be within this project.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" width=\"1002\" height=\"648\" src=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/create-asp.net6-mv-.png\" alt=\"\" class=\"wp-image-669\" srcset=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/create-asp.net6-mv-.png 1002w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/create-asp.net6-mv--300x194.png 300w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/create-asp.net6-mv--768x497.png 768w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/create-asp.net6-mv--18x12.png 18w\" sizes=\"(max-width: 1002px) 100vw, 1002px\" \/><\/figure>\n\n\n\n<p>We'll need a database to store our users. To set this up, we'll first configure Entity Framework and the database settings.<\/p>\n\n\n\n<p>Install The Following Packages<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true\">Install-Package Microsoft.EntityFrameworkCore\nInstall-Package Microsoft.EntityFrameworkCore.SqlServer\nInstall-Package Microsoft.EntityFrameworkCore.Tools<\/pre><\/div>\n\n\n\n<p>EntityFrameworkCore.SqlServer is used in the project to facilitate interaction and management of data with Microsoft SQL Server databases through Entity Framework Core,<br>EntityFrameworkCore.Tools : migration komutlar\u0131 i\u00e7in.<\/p>\n\n\n\n<p><strong>DbContext dependy injection<\/strong> \/Program.cs<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">builder.Services.AddDbContext&lt;ApplicationContext&gt;(\n    options =&gt; options.UseSqlServer(builder.Configuration.GetConnectionString(\"SqlServer\")));<\/pre><\/div>\n\n\n\n<p class=\" translation-block\">We are registering ApplicationDbContext inherited from DbContext and add <strong>Sql Server<\/strong> as database.<\/p>\n\n\n\n<p><strong>ApplicationContext.cs<\/strong><\/p>\n\n\n\n<p>AddDbContext k\u0131sm\u0131nda options nesnesini kullanabilmek i\u00e7in Context s\u0131n\u0131f\u0131n\u0131n constrcutor\u0131nda mutlaka <strong>DbContextOptions&lt;T><\/strong> implement etmeleyiz.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">public class ApplicationContext : DbContext\n{\n    public ApplicationContext(DbContextOptions&lt;ApplicationContext&gt; context)\n        : base(context) { }\n}<\/pre><\/div>\n\n\n\n<p class=\" translation-block\">User Entity: <strong>User.cs<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">public class User\n{\n    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]\n    public int Id { get; set; }\n    public string FirstName { get; set; }\n    public string LastName { get; set; }\n    public string Username { get; set; }\n    public string Password { get; set; }\n}<\/pre><\/div>\n\n\n\n<p>Id is auto identity<\/p>\n\n\n\n<p class=\" translation-block\">Let's write connection string to <strong>appsettings.json<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:js mark:8,9,10 decode:true\">{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n  \"ConnectionStrings\": {\n    \"SqlServer\": \"Server=(localdb)\\\\mssqllocaldb;Database=SingleSignOn;Trusted_Connection=True;\"\n  },\n  \"AllowedHosts\": \"*\"\n}<\/pre><\/div>\n\n\n\n<p>Add Users to ApplicationContext<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">public DbSet&lt;User&gt; Users { get; set; }<\/pre><\/div>\n\n\n\n<p>Migration Commands<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true\">add-migration initial\nupdate-database<\/pre><\/div>\n\n\n\n<p class=\" translation-block\">more information for migrations see: <a href=\"https:\/\/okankaradag.com\/entity-framewok\/entity-framework-migration-komutlari\" target=\"_self\">link <\/a><\/p>\n\n\n\n<p><strong>Sql <\/strong>S<strong>erver Management Studio <\/strong>ile veritaban\u0131n\u0131 kontrol edebiliriz<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" width=\"346\" height=\"347\" src=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/sql-table-scheme.png\" alt=\"\" class=\"wp-image-672\" srcset=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/sql-table-scheme.png 346w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/sql-table-scheme-300x300.png 300w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/sql-table-scheme-150x150.png 150w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/sql-table-scheme-12x12.png 12w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/sql-table-scheme-80x80.png 80w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/03\/sql-table-scheme-320x320.png 320w\" sizes=\"(max-width: 346px) 100vw, 346px\" \/><\/figure>\n\n\n\n<h5 id=\"identityserver\">IdentityServer<\/h5>\n\n\n\n<p>Ana konumuz olan identity server ayarlar\u0131n\u0131 yapal\u0131m. \u00d6ncelikle a\u015fa\u011f\u0131daki paketleri y\u00fckleyelim.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true\">Install-Package IdentityServer4\nInstall-Package IdentityServer4.EntityFramework\nInstall-Package IdentityServer4.Storage<\/pre><\/div>\n\n\n\n<p>Program.cs&#8217;ye identity server ile ilgili a\u015fa\u011f\u0131daki ayarlar\u0131 ekleyelim<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">var conStr = builder.Configuration.GetConnectionString(\"SqlServer\");\nvar assembly = typeof(Program).Assembly.GetName().Name;\nbuilder.Services.AddIdentityServer()\n    .AddConfigurationStore(\n        options =&gt; options.ConfigureDbContext =\n        config =&gt; config.UseSqlServer(conStr, opt =&gt; opt.MigrationsAssembly(assembly))\n    )\n    .AddOperationalStore(\n        options =&gt; options.ConfigureDbContext =\n        config =&gt; config.UseSqlServer(conStr, opt =&gt; opt.MigrationsAssembly(assembly))\n    ).AddDeveloperSigningCredential();\n...\n...\n...\napp.UseIdentityServer();<\/pre><\/div>\n\n\n\n<p>iki tane store edece\u011fimiz bilgileri ekledik, Bu store&#8217;lar\u0131n kendine ait contextleri var.<\/p>\n\n\n\n<ul><li><strong>ConfigurationStore<\/strong>: ad\u0131ndan anla\u015f\u0131laca\u011f\u0131 gibi clients, resources ve cors gibi ayarlar\u0131 depolamaya yarar<\/li><li><strong>OperationalStore<\/strong>: grants, consents, and token gibi authorization ayarlar\u0131n\u0131 sakl\u0131yor<\/li><\/ul>\n\n\n\n<blockquote class=\"wp-block-quote\"><p><mark>AddDeveloperSigningCredential<\/mark>: IdentityServer do\u011frulama ve imzalama i\u00e7in baz\u0131 anahtarlamalar kullan\u0131yor, Bu anahtarlarda RS256, RS384 gibi algoritmalarla \u015fifrelenir, baz\u0131 metotlarla da bu anahtar config\u00fcre edilebilir. AddSigningCredential, AddDeveloperSigningCredential, AddValidationKey gibi d\u00fczenlemeler var biz localhost i\u00e7in olan AddDeveloperSigningCredential&#8217;i kullanaca\u011f\u0131z.<\/p><\/blockquote>\n\n\n\n<p><strong>migration:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true\">add-migration identityServerConf -c PersistedGrantDbContext<\/pre><\/div>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true\">add-migration identityServerConf -c ConfigurationDbContext<\/pre><\/div>\n\n\n\n<p><strong>update-database<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true\">update-database -Context ConfigurationDbContext\nupdate-database -Context PersistedGrantDbContext <\/pre><\/div>\n\n\n\n<p>migration i\u015flemlerinden sonra tablolar\u0131m\u0131z\u0131n olu\u015ftu\u011fumu g\u00f6rece\u011fiz, bu tablolarla ilgili detaylar\u0131 a\u015fa\u011f\u0131da belirtmi\u015f olaca\u011f\u0131m. Bu olu\u015fturdu\u011fumuz tablolar\u0131 dolduracak bir seed data yazal\u0131m. Bu datalar \u00fczerinden identityserver&#8217;\u0131n objelerini yak\u0131ndan inceleyelim.<\/p>\n\n\n\n<p><strong>Identity Resources<\/strong><\/p>\n\n\n\n<p>Username,mail,id gibi unique user\/identity datalard\u0131r. buraya ekstra datalar eklenebilir (role gibi)<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true\">public static IEnumerable&lt;IdentityResource&gt; IdentityResources =&gt;\n        new List&lt;IdentityResource&gt; {\n            new IdentityResources.OpenId(),\n            new IdentityResources.Profile(),\n};<\/pre><\/div>\n\n\n\n<p><strong>Client<\/strong><\/p>\n\n\n\n<p>IdentityServer&#8217;dan token talep eden uygulamalard\u0131r. Bu uygulamalar web, mobile, spa, server gibi yaz\u0131l\u0131m teknolojileridir.<\/p>\n\n\n\n<p>Bir statik class \u00fczerinde \u00f6rnek bir client tan\u0131mlayal\u0131m.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\" >public static IEnumerable&lt;Client&gt; Clients =&gt;\nnew List&lt;Client&gt; {\n    new()\n    {\n        ClientId = \"mvc-app\",\n        ClientName = \"Mvc  App\",\n        AllowOfflineAccess = true,\n        RequirePkce = true,\n        AllowedGrantTypes = GrantTypes.Code,\n        ClientSecrets = { new(\"MvcApp\".Sha256())},\n        AllowedScopes = {\"openid\",\"profile\",\"roles\"},\n        RedirectUris = {\"https:\/\/localhost:7204\/signin-oidc\"},\n        FrontChannelLogoutUri = \"https:\/\/localhost:7204\/signout-oidc\",\n        PostLogoutRedirectUris = { \"https:\/\/localhost:7204\/Home\/Index\" },\n        RequireConsent = false,\n    }\n\n};<\/pre><\/div>\n\n\n\n<p>\u00d6rnek bir tane client ekledik, <strong>AllowedGrantTypes<\/strong> \u00f6zelli\u011fi client&#8217;\u0131n nas\u0131l kullan\u0131laca\u011f\u0131n\u0131 belirleyen \u00f6nemli bir parametre, bu \u00f6zellik e\u011fer code olarak set edilirse client&#8217;a bir kullan\u0131c\u0131 arac\u0131l\u0131\u011f\u0131yla bir giri\u015f yap\u0131laca\u011f\u0131n\u0131 belirtmi\u015f oluruz. Verilen Url&#8217;ler uygulaman\u0131n kendi url&#8217;leri olacak \u015fekildedir.<\/p>\n\n\n\n<p>Bu statik verilerimizi middleware taraf\u0131nda identity server&#8217;\u0131n memory&#8217;sine tan\u0131mlayal\u0131m.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">builder.Services.AddIdentityServer()\n    .AddConfigurationStore(\n        options =&gt; options.ConfigureDbContext =\n        config =&gt; config.UseSqlServer(conStr, opt =&gt; opt.MigrationsAssembly(assembly))\n    )\n    .AddOperationalStore(\n        options =&gt; options.ConfigureDbContext =\n        config =&gt; config.UseSqlServer(conStr, opt =&gt; opt.MigrationsAssembly(assembly))\n    )\n    .AddInMemoryApiResources(IdentityConfig.ApiResources)\n    .AddInMemoryApiScopes(IdentityConfig.ApiScopes)\n    .AddInMemoryClients(IdentityConfig.Clients)\n    .AddInMemoryIdentityResources(IdentityConfig.IdentityResources)\n    .AddDeveloperSigningCredential();<\/pre><\/div>\n\n\n\n<h5 id=\"login-controller-view\">Login Controller\/View<\/h5>\n\n\n\n<p>Merkezi login controller\u0131 ve view&#8217;\u0131n\u0131 identityserver projesine ekleyelim.<\/p>\n\n\n\n<p><strong>AccountController<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">public class AccountController : Controller\n{\n    private readonly IUserService _userService;\n\n    public AccountController(IIdentityServerInteractionService interaction,IUserService userService)\n    {\n        _userService = userService;\n    }\n\n\n    public IActionResult Login(string returnUrl)\n    {\n        return View(new LoginViewModel { ReturnUrl = returnUrl });\n    }\n    [HttpPost]\n    public async Task&lt;IActionResult&gt; Login(LoginViewModel model)\n    {\n        var user = _userService.GetByUsername(model.UserName);\n        if (user == null)\n        {\n            ModelState.AddModelError(\"UserName\", \"User or password are not correct\");\n            return View(model);\n        }\n        \/\/could do password check;\n        \n        var identityServerUser = new IdentityServerUser(user.Id.ToString());\n        await HttpContext.SignInAsync(identityServerUser);\n        return Redirect(model.ReturnUrl);\n    }\n}<\/pre><\/div>\n\n\n\n<p><strong>UserService <\/strong>i\u015flevi user,password vs gibi kontroller sizde burada istedi\u011finiz d\u00fczenlemeleri, validasyonlar\u0131 ekleyebilirsiniz. <strong>Login <\/strong>ekran\u0131na ise a\u015fa\u011f\u0131daki github adresinden ula\u015fabilirsiniz.<\/p>\n\n\n\n<h5 id=\"cookie-ayarlari\">Cookie Ayarlar\u0131<\/h5>\n\n\n\n<p>Identity sitemiz&#8217;de login olduktan sonra bilgiler cookie&#8217;ye set edilir, bu \u00e7erezlerden di\u011fer sitelerimizin eri\u015febilmesi i\u00e7in baz\u0131 ayarlar\u0131 yapmam\u0131z gerekiyor.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\" >builder.Services.ConfigureApplicationCookie(options =&gt;\n{\n    options.Cookie.Name = \"IdentityServer.Cookie\";\n    options.LoginPath = \"Account\/Login\";\n    options.LogoutPath = \"Account\/Logout\";\n});<\/pre><\/div>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\" >app.UseCookiePolicy(new CookiePolicyOptions\n{\n    HttpOnly = HttpOnlyPolicy.Always,\n    MinimumSameSitePolicy = SameSiteMode.Lax,\n    Secure = CookieSecurePolicy.Always\n});<\/pre><\/div>\n\n\n\n<h5 id=\"identityprofileservice\">IdentityProfileService<\/h5>\n\n\n\n<p>Burada kritik bir noktaya geldik, kullan\u0131c\u0131m\u0131z login olduktan sonra <strong>account\/login<\/strong> post olacak orada bir cookie atamas\u0131 yap\u0131yoruz. ama tabiki bu kadar atama yeterli de\u011fil kullan\u0131c\u0131n\u0131n ismi, maili, do\u011fum tarihi vs. gibi bilgileri istenilen clienta vermeliyiz. Bunun i\u00e7in identityserver&#8217;\u0131n sa\u011flad\u0131\u011f\u0131 <strong>IProfileService<\/strong> den miras al\u0131narak bir service yazal\u0131m.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">public class IdentityProfileService : IProfileService\n{\n    private readonly IUserService _userService;\n\n    public IdentityProfileService(IUserService userService)\n    {\n        _userService = userService;\n    }\n    public async Task GetProfileDataAsync(ProfileDataRequestContext context)\n    {\n        var userId = context.Subject.GetSubjectId();\n        if (userId.IsNullOrEmpty())\n        {\n            return;\n        }\n        var user = _userService.GetById(int.Parse(userId));\n        if (user == null) { return; }\n        var claims = new List&lt;Claim&gt;()\n            {\n                new Claim(JwtClaimTypes.Gender,user.Gender),\n                new Claim(JwtClaimTypes.PhoneNumber,\"+507\"),\n                new Claim(JwtClaimTypes.Name,user.Name),\n                new Claim(JwtClaimTypes.Email,user.Email),\n                new Claim(JwtClaimTypes.BirthDate,user.BirthDate.ToString()),\n                new Claim(JwtClaimTypes.Id,user.Id.ToString()),\n            };\n        user.Roles.ForEach(r =&gt; claims.Add(new Claim(JwtClaimTypes.Role, r)));\n        var requestedClaims = claims.Where(p =&gt; context.RequestedClaimTypes.Contains(p.Type)).ToList();\n        context.IssuedClaims = requestedClaims;\n        context.AddRequestedClaims(requestedClaims);\n    }\n\n\n    public async Task IsActiveAsync(IsActiveContext context)\n    {\n        var data = context.IsActive;\n        await Task.CompletedTask;\n    }\n}<\/pre><\/div>\n\n\n\n<p>Giri\u015f yapmak isteyen client&#8217;\u0131n talep etti\u011fi ve yetkisi olan claimler burada eklenecek. Dependecy injection i\u00e7in <strong>AddProfileService()&lt;IdentityProfileService>()<\/strong> eklemeyi unutmay\u0131n<\/p>\n\n\n\n<h5 id=\"mvc-uygulmasi\">Mvc uygulmas\u0131<\/h5>\n\n\n\n<p>\u015eimdi bir tane .net core  mvc projesi ekleyelim ve login olarak identity server&#8217;\u0131 ekleyelim.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">builder.Services.AddAuthentication(options =&gt;\n{\n    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;\n    options.DefaultChallengeScheme = \"oidc\"; \/\/OpenIdConnect\n})\n    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,\n      options =&gt;\n      {\n          options.ExpireTimeSpan = TimeSpan.FromHours(24);\n      })\n      .AddOpenIdConnect(\"oidc\", options =&gt;\n      {\n          options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;\n          options.ClientId = \"mvc-app\";\n          options.ClientSecret = \"MvcApp\";\n          options.Authority = \"https:\/\/localhost:7267\/\";\n          options.ResponseType = \"code\";\n          options.SaveTokens = true;\n          options.SignedOutCallbackPath = \"\/Home\/Index\";\n          options.Scope.Clear();\n          options.Scope.Add(\"openid\");\n          options.Scope.Add(\"profile\");\n          options.Scope.Add(\"roles\");\n          options.GetClaimsFromUserInfoEndpoint = true;\n          options.ClaimActions.MapJsonKey(\"role\", \"role\", \"role\");\n          options.ClaimActions.MapUniqueJsonKey(\"gender\", \"gender\", \"gender\");\n          options.TokenValidationParameters.RoleClaimType = \"role\";\n          options.TokenValidationParameters = new TokenValidationParameters\n          {\n              AuthenticationType = CookieAuthenticationDefaults.AuthenticationScheme\n          };\n          options.Events = new OpenIdConnectEvents\n          {\n              OnTokenValidated = async context =&gt;\n              {\n                  var identity = context.Principal?.Identity as ClaimsIdentity;\n                  if (identity == null)\n                  {\n                      return;\n                  }\n                  identity.AddClaim(new Claim(\"customClaim\", \"customValue\"));\/\/custom claim\n              }\n          };\n\n      });<\/pre><\/div>\n\n\n\n<p><strong>MapJsonKey<\/strong> gelen claimleri \u00e7\u00f6z\u00fcmlemesi gerekli bir fonksiyon sadece <strong>role <\/strong>ve <strong>gender <\/strong>i\u00e7in var o y\u00fczden phone gibi alanlar yetkisi olunsa bile cookie&#8217;ye eklenmez.<br><strong>OnTokenValidated <\/strong>ise art\u0131k giri\u015f i\u015flemleri ba\u015far\u0131l\u0131 olduktan sonra yakalanan <strong>event<\/strong>. Burada kendi client&#8217;\u0131n\u0131za \u00f6zel cliamleri ekleyebilirsiniz.<br><strong>Authority<\/strong>: SSO adresi<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">app.UseAuthentication();\napp.UseAuthorization();<\/pre><\/div>\n\n\n\n<p>Middleware yukar\u0131daki ayarlar\u0131 eklemeyi unutmay\u0131n.<\/p>\n\n\n\n<p>Identity server i\u00e7inde MvcApp i\u00e7in url bilgilerinde mutlaka aya\u011fa kalkan mvc uygulaman\u0131z\u0131n giri\u015f bilgilerini giriniz.<\/p>\n\n\n\n<p>\u015eimdi hem mvc uygulamas\u0131 i\u00e7inde bir endpoinete <strong>[Authorize]<\/strong> attribute ekleyelim.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\">public class HomeController : Controller\n{\n    private readonly ILogger&lt;HomeController&gt; _logger;\n\n    public HomeController(ILogger&lt;HomeController&gt; logger)\n    {\n        _logger = logger;\n    }\n\n    public IActionResult Index()\n    {\n        return View();\n    }\n    [Authorize]\n    public IActionResult Privacy()\n    {\n        return View();\n    }\n\n    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]\n    public IActionResult Error()\n    {\n        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });\n    }\n}<\/pre><\/div>\n\n\n\n<p>Privacy t\u0131klad\u0131\u011f\u0131m\u0131z an bizi login page&#8217;e atmas\u0131 gerekecek.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" width=\"849\" height=\"420\" src=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/mvcApp-authorize.png\" alt=\"\" class=\"wp-image-723\" srcset=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/mvcApp-authorize.png 849w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/mvcApp-authorize-300x148.png 300w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/mvcApp-authorize-768x380.png 768w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/mvcApp-authorize-18x9.png 18w\" sizes=\"(max-width: 849px) 100vw, 849px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"1024\" height=\"567\" src=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/redirect_url-1024x567.png\" alt=\"\" class=\"wp-image-724\" srcset=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/redirect_url-1024x567.png 1024w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/redirect_url-300x166.png 300w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/redirect_url-768x425.png 768w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/redirect_url-1536x851.png 1536w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/redirect_url-18x10.png 18w, https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/redirect_url.png 1607w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h5 id=\"logout\">Logout<\/h5>\n\n\n\n<p>\u00d6ncelikle account controller&#8217;a bir logout endpointi eklemeliyiz.<\/p>\n\n\n\n<p><strong>IdentityServer -> AccountController -> Logout<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\" > public async Task&lt;IActionResult&gt; Logout(string logoutId)\n    {\n        var client = await _interaction.GetLogoutContextAsync(logoutId);\n        if (string.IsNullOrEmpty(client.PostLogoutRedirectUri))\n        {\n            return RedirectToAction(\"Index\", \"Home\");\n        }\n        return Redirect(client.PostLogoutRedirectUri);\n    }<\/pre><\/div>\n\n\n\n<p><strong>MvcApp -> Logout<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true\" >public IActionResult Logout()\n{\n    return SignOut(\"Cookies\", \"oidc\");\n}<\/pre><\/div>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>Statik identity config \u00fczerinde PostLogoutRedirecturis alan\u0131n\u0131 do\u011fru yazmay\u0131 unutmay\u0131n\u0131z<\/p><\/blockquote>\n\n\n\n<h5 id=\"sonuc\">Sonu\u00e7<\/h5>\n\n\n\n<p>Merkezi bir sso ve bunu t\u00fcketecek bir tane de mvc uygulamas\u0131 yapt\u0131k. Sql ayarlar\u0131n\u0131 yapsak da verileri memory \u00fczerinden i\u015fledik. Uygulama&#8217;da kritik nokta cookiler&#8217;i payla\u015fma, bu payla\u015fma&#8217;da Client&#8217;\u0131n yetkili oldu\u011fu cliamlere g\u00f6re yap\u0131yoruz bunu da ProfileService i\u00e7inde yapt\u0131k. <br>\u0130\u015fler kar\u0131\u015f\u0131k gibi g\u00f6z\u00fckse de olay giri\u015f yapma, y\u00f6nlendirme ve cookie&#8217;leri payla\u015fmadan ibaret.<\/p>\n\n\n\n<p>Proje Linki: <a href=\"https:\/\/github.com\/okankrdg\/SingleSignOn\">https:\/\/github.com\/okankrdg\/SingleSignOn<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>How to do Single Sign Out using .net 6.0 and IdentityServer?<\/p>","protected":false},"author":1,"featured_media":731,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[87,22],"tags":[27,94,98,45,97,96],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v19.13 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>.Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO) - Okan Karada\u011f<\/title>\n<meta name=\"description\" content=\".Net 6.0 ve Identity Server kullanarak merkezi login sistemi (SSO) nas\u0131l yap\u0131l\u0131r? Tek bir yerden nas\u0131l authenticate olunur onu inceleyece\u011fiz.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/okankaradag.com\/en\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO) - Okan Karada\u011f\" \/>\n<meta property=\"og:description\" content=\".Net 6.0 ve Identity Server kullanarak merkezi login sistemi (SSO) nas\u0131l yap\u0131l\u0131r? Tek bir yerden nas\u0131l authenticate olunur onu inceleyece\u011fiz.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/okankaradag.com\/en\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\/\" \/>\n<meta property=\"og:site_name\" content=\"Okan Karada\u011f\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-05T23:01:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/key-lock-door.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"910\" \/>\n\t<meta property=\"og:image:height\" content=\"607\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Okan Karada\u011f\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Okan Karada\u011f\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#article\",\"isPartOf\":{\"@id\":\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\"},\"author\":{\"name\":\"Okan Karada\u011f\",\"@id\":\"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52\"},\"headline\":\".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO)\",\"datePublished\":\"2022-08-05T23:01:40+00:00\",\"dateModified\":\"2022-08-05T23:01:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\"},\"wordCount\":954,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52\"},\"keywords\":[\"Asp.Net identity\",\"authentication\",\"authorize\",\"dotnet core\",\"single sign out\",\"sso\"],\"articleSection\":[\".Net 6.0\",\"Oauth\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\",\"url\":\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\",\"name\":\".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO) - Okan Karada\u011f\",\"isPartOf\":{\"@id\":\"https:\/\/okankaradag.com\/#website\"},\"datePublished\":\"2022-08-05T23:01:40+00:00\",\"dateModified\":\"2022-08-05T23:01:40+00:00\",\"description\":\".Net 6.0 ve Identity Server kullanarak merkezi login sistemi (SSO) nas\u0131l yap\u0131l\u0131r? Tek bir yerden nas\u0131l authenticate olunur onu inceleyece\u011fiz.\",\"breadcrumb\":{\"@id\":\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/okankaradag.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/okankaradag.com\/#website\",\"url\":\"https:\/\/okankaradag.com\/\",\"name\":\"Okan Karada\u011f\",\"description\":\"Programlama \u00dczerine\",\"publisher\":{\"@id\":\"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/okankaradag.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52\",\"name\":\"Okan Karada\u011f\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/okankaradag.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ca08a5537d7e304914c37189abedd2a1?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/ca08a5537d7e304914c37189abedd2a1?s=96&d=mm&r=g\",\"caption\":\"Okan Karada\u011f\"},\"logo\":{\"@id\":\"https:\/\/okankaradag.com\/#\/schema\/person\/image\/\"},\"sameAs\":[\"https:\/\/okankaradag.com\"],\"url\":\"https:\/\/okankaradag.com\/en\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO) - Okan Karada\u011f","description":".Net 6.0 ve Identity Server kullanarak merkezi login sistemi (SSO) nas\u0131l yap\u0131l\u0131r? Tek bir yerden nas\u0131l authenticate olunur onu inceleyece\u011fiz.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/okankaradag.com\/en\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\/","og_locale":"en_US","og_type":"article","og_title":".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO) - Okan Karada\u011f","og_description":".Net 6.0 ve Identity Server kullanarak merkezi login sistemi (SSO) nas\u0131l yap\u0131l\u0131r? Tek bir yerden nas\u0131l authenticate olunur onu inceleyece\u011fiz.","og_url":"https:\/\/okankaradag.com\/en\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso\/","og_site_name":"Okan Karada\u011f","article_published_time":"2022-08-05T23:01:40+00:00","og_image":[{"width":910,"height":607,"url":"https:\/\/okankaradag.com\/wp-content\/uploads\/2022\/08\/key-lock-door.jpg","type":"image\/jpeg"}],"author":"Okan Karada\u011f","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Okan Karada\u011f","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#article","isPartOf":{"@id":"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso"},"author":{"name":"Okan Karada\u011f","@id":"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52"},"headline":".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO)","datePublished":"2022-08-05T23:01:40+00:00","dateModified":"2022-08-05T23:01:40+00:00","mainEntityOfPage":{"@id":"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso"},"wordCount":954,"commentCount":0,"publisher":{"@id":"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52"},"keywords":["Asp.Net identity","authentication","authorize","dotnet core","single sign out","sso"],"articleSection":[".Net 6.0","Oauth"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#respond"]}]},{"@type":"WebPage","@id":"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso","url":"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso","name":".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO) - Okan Karada\u011f","isPartOf":{"@id":"https:\/\/okankaradag.com\/#website"},"datePublished":"2022-08-05T23:01:40+00:00","dateModified":"2022-08-05T23:01:40+00:00","description":".Net 6.0 ve Identity Server kullanarak merkezi login sistemi (SSO) nas\u0131l yap\u0131l\u0131r? Tek bir yerden nas\u0131l authenticate olunur onu inceleyece\u011fiz.","breadcrumb":{"@id":"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/okankaradag.com\/net-6-0\/net-6-0-ve-identityserver-v4-ile-merkezi-login-sistemi-sso#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/okankaradag.com\/"},{"@type":"ListItem","position":2,"name":".Net 6.0 ve IdentityServer v4 ile Merkezi Login Sistemi (SSO)"}]},{"@type":"WebSite","@id":"https:\/\/okankaradag.com\/#website","url":"https:\/\/okankaradag.com\/","name":"Okan Karada\u011f","description":"Programlama \u00dczerine","publisher":{"@id":"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/okankaradag.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/okankaradag.com\/#\/schema\/person\/0196919c5e3b6a496101ded872640d52","name":"Okan Karada\u011f","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/okankaradag.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/ca08a5537d7e304914c37189abedd2a1?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ca08a5537d7e304914c37189abedd2a1?s=96&d=mm&r=g","caption":"Okan Karada\u011f"},"logo":{"@id":"https:\/\/okankaradag.com\/#\/schema\/person\/image\/"},"sameAs":["https:\/\/okankaradag.com"],"url":"https:\/\/okankaradag.com\/en\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/posts\/659"}],"collection":[{"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/comments?post=659"}],"version-history":[{"count":19,"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/posts\/659\/revisions"}],"predecessor-version":[{"id":917,"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/posts\/659\/revisions\/917"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/media\/731"}],"wp:attachment":[{"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/media?parent=659"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/categories?post=659"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/okankaradag.com\/en\/wp-json\/wp\/v2\/tags?post=659"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}