From 0bece14ea07d9ddf42eaa2a802c76698cd5a1b33 Mon Sep 17 00:00:00 2001 From: kailash-b Date: Thu, 14 Aug 2025 14:21:43 +0530 Subject: [PATCH 1/4] Support .NET 8 in playground --- .../Auth0.AspNetCore.Authentication.Playground.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Auth0.AspNetCore.Authentication.Playground.csproj b/playground/Auth0.AspNetCore.Authentication.Playground/Auth0.AspNetCore.Authentication.Playground.csproj index d1fcdd0..e0c22d9 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Auth0.AspNetCore.Authentication.Playground.csproj +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Auth0.AspNetCore.Authentication.Playground.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0;net8.0 From db123914c64c0713d846a9f157430e2ad45e3ce9 Mon Sep 17 00:00:00 2001 From: kailash-b Date: Thu, 14 Aug 2025 14:23:21 +0530 Subject: [PATCH 2/4] Use file scoped namespaces in playground --- .../Controllers/AccountController.cs | 134 ++++++----- .../Controllers/HomeController.cs | 31 ++- .../CustomClearSessionLogoutTokenHandler.cs | 33 ++- .../CustomDistributedLogoutTokenHandler.cs | 40 ++-- .../CustomInMemoryTicketStore.cs | 61 +++-- .../CustomLogoutTokenHandler.cs | 38 ++-- .../Models/ErrorViewModel.cs | 13 +- .../Models/UserProfileViewModel.cs | 17 +- .../PlaygroundConstants.cs | 41 ++-- .../Program.cs | 26 +-- .../Startup.cs | 213 ++++++------------ 11 files changed, 282 insertions(+), 365 deletions(-) diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs index 15ae278..1f766cc 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs @@ -7,85 +7,83 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace Auth0.AspNetCore.Authentication.Playground.Controllers +namespace Auth0.AspNetCore.Authentication.Playground.Controllers; + +public class AccountController : Controller { - - public class AccountController : Controller + public async Task Login(string returnUrl = "/") { - public async Task Login(string returnUrl = "/") - { - var authenticationProperties = new LoginAuthenticationPropertiesBuilder() - .WithRedirectUri(returnUrl) - .Build(); + var authenticationProperties = new LoginAuthenticationPropertiesBuilder() + .WithRedirectUri(returnUrl) + .Build(); - await HttpContext.ChallengeAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); - } + await HttpContext.ChallengeAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); + } - public async Task Login2(string returnUrl = "/") - { - var authenticationProperties = new LoginAuthenticationPropertiesBuilder() - .WithRedirectUri(returnUrl) - .Build(); + public async Task Login2(string returnUrl = "/") + { + var authenticationProperties = new LoginAuthenticationPropertiesBuilder() + .WithRedirectUri(returnUrl) + .Build(); - await HttpContext.ChallengeAsync(PlaygroundConstants.AuthenticationScheme2, authenticationProperties); - } + await HttpContext.ChallengeAsync(PlaygroundConstants.AuthenticationScheme2, authenticationProperties); + } - [Authorize] - public async Task Logout() - { - // Indicate here where Auth0 should redirect the user after a logout. - // Note that the resulting absolute Uri must be whitelisted in the - // **Allowed Logout URLs** settings for the client. - var authenticationProperties = new LogoutAuthenticationPropertiesBuilder() - .WithRedirectUri(Url.Action("Index", "Home")) - .Build(); + [Authorize] + public async Task Logout() + { + // Indicate here where Auth0 should redirect the user after a logout. + // Note that the resulting absolute Uri must be whitelisted in the + // **Allowed Logout URLs** settings for the client. + var authenticationProperties = new LogoutAuthenticationPropertiesBuilder() + .WithRedirectUri(Url.Action("Index", "Home")) + .Build(); - await HttpContext.SignOutAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); - await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); - } + await HttpContext.SignOutAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + } - [Authorize] - public async Task Logout2() - { - // Indicate here where Auth0 should redirect the user after a logout. - // Note that the resulting absolute Uri must be whitelisted in the - // **Allowed Logout URLs** settings for the client. - var authenticationProperties = new LogoutAuthenticationPropertiesBuilder() - .WithRedirectUri(Url.Action("Index", "Home")) - .Build(); + [Authorize] + public async Task Logout2() + { + // Indicate here where Auth0 should redirect the user after a logout. + // Note that the resulting absolute Uri must be whitelisted in the + // **Allowed Logout URLs** settings for the client. + var authenticationProperties = new LogoutAuthenticationPropertiesBuilder() + .WithRedirectUri(Url.Action("Index", "Home")) + .Build(); - await HttpContext.SignOutAsync(PlaygroundConstants.AuthenticationScheme2, authenticationProperties); - await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); - } + await HttpContext.SignOutAsync(PlaygroundConstants.AuthenticationScheme2, authenticationProperties); + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + } - [Authorize] - public async Task Profile() + [Authorize] + public async Task Profile() + { + var accessToken = await HttpContext.GetTokenAsync("access_token"); + var idToken = await HttpContext.GetTokenAsync("id_token"); + var refreshToken = await HttpContext.GetTokenAsync("refresh_token"); + return View(new UserProfileViewModel() { - var accessToken = await HttpContext.GetTokenAsync("access_token"); - var idToken = await HttpContext.GetTokenAsync("id_token"); - var refreshToken = await HttpContext.GetTokenAsync("refresh_token"); - return View(new UserProfileViewModel() - { - Name = User.Identity.Name, - EmailAddress = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value, - ProfileImage = User.Claims.FirstOrDefault(c => c.Type == "picture")?.Value - }); - } + Name = User.Identity.Name, + EmailAddress = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value, + ProfileImage = User.Claims.FirstOrDefault(c => c.Type == "picture")?.Value + }); + } - /// - /// This is just a helper action to enable you to easily see all claims related to a user. It helps when debugging your - /// application to see the in claims populated from the Auth0 ID Token - /// - /// - [Authorize] - public IActionResult Claims() - { - return View(); - } + /// + /// This is just a helper action to enable you to easily see all claims related to a user. It helps when debugging your + /// application to see the in claims populated from the Auth0 ID Token + /// + /// + [Authorize] + public IActionResult Claims() + { + return View(); + } - public IActionResult AccessDenied() - { - return View(); - } + public IActionResult AccessDenied() + { + return View(); } -} +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/HomeController.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/HomeController.cs index 5cc5e99..84c458d 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/HomeController.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/HomeController.cs @@ -3,24 +3,23 @@ using Microsoft.AspNetCore.Mvc; using System.Diagnostics; -namespace Auth0.AspNetCore.Authentication.Playground.Controllers +namespace Auth0.AspNetCore.Authentication.Playground.Controllers; + +public class HomeController : Controller { - public class HomeController : Controller + public IActionResult Index() { - public IActionResult Index() - { - return View(); - } + return View(); + } - [Authorize(Roles = "Admin")] - public IActionResult Admin() - { - return View(); - } + [Authorize(Roles = "Admin")] + public IActionResult Admin() + { + return View(); + } - public IActionResult Error() - { - return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); - } + public IActionResult Error() + { + return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } -} +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/CustomClearSessionLogoutTokenHandler.cs b/playground/Auth0.AspNetCore.Authentication.Playground/CustomClearSessionLogoutTokenHandler.cs index 83beab8..91d13cf 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/CustomClearSessionLogoutTokenHandler.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/CustomClearSessionLogoutTokenHandler.cs @@ -3,25 +3,24 @@ using System.Threading.Tasks; using Auth0.AspNetCore.Authentication.BackchannelLogout; -namespace Auth0.AspNetCore.Authentication.Playground +namespace Auth0.AspNetCore.Authentication.Playground; + +public class CustomClearSessionLogoutTokenHandler : ILogoutTokenHandler { - public class CustomClearSessionLogoutTokenHandler : ILogoutTokenHandler - { - private readonly ITicketStore store; + private readonly ITicketStore store; - public CustomClearSessionLogoutTokenHandler(ITicketStore store) - { - this.store = store; - } + public CustomClearSessionLogoutTokenHandler(ITicketStore store) + { + this.store = store; + } - public async Task OnTokenReceivedAsync(string issuer, string sid, string logoutToken, TimeSpan expiration) - { - await store.RemoveAsync(sid); - } + public async Task OnTokenReceivedAsync(string issuer, string sid, string logoutToken, TimeSpan expiration) + { + await store.RemoveAsync(sid); + } - public Task IsLoggedOutAsync(string issuer, string sid) - { - return Task.FromResult(false); - } + public Task IsLoggedOutAsync(string issuer, string sid) + { + return Task.FromResult(false); } -} +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/CustomDistributedLogoutTokenHandler.cs b/playground/Auth0.AspNetCore.Authentication.Playground/CustomDistributedLogoutTokenHandler.cs index da10d8b..acff9f9 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/CustomDistributedLogoutTokenHandler.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/CustomDistributedLogoutTokenHandler.cs @@ -4,30 +4,28 @@ using System.Threading.Tasks; using Auth0.AspNetCore.Authentication.BackchannelLogout; -namespace Auth0.AspNetCore.Authentication.Playground -{ - public class CustomDistributedLogoutTokenHandler : ILogoutTokenHandler - { - private readonly IDistributedCache _cache; +namespace Auth0.AspNetCore.Authentication.Playground; - public CustomDistributedLogoutTokenHandler(IDistributedCache cache) - { - _cache = cache; - } +public class CustomDistributedLogoutTokenHandler : ILogoutTokenHandler +{ + private readonly IDistributedCache _cache; - public async Task OnTokenReceivedAsync(string issuer, string sid, string logoutToken, TimeSpan expiration) - { - await _cache.SetAsync($"{issuer}|{sid}", Encoding.ASCII.GetBytes(logoutToken), new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = expiration - }); - } + public CustomDistributedLogoutTokenHandler(IDistributedCache cache) + { + _cache = cache; + } - public async Task IsLoggedOutAsync(string issuer, string sid) + public async Task OnTokenReceivedAsync(string issuer, string sid, string logoutToken, TimeSpan expiration) + { + await _cache.SetAsync($"{issuer}|{sid}", Encoding.ASCII.GetBytes(logoutToken), new DistributedCacheEntryOptions { - var token = await _cache.GetAsync($"{issuer}|{sid}"); - return token != null; - } + AbsoluteExpirationRelativeToNow = expiration + }); } -} + public async Task IsLoggedOutAsync(string issuer, string sid) + { + var token = await _cache.GetAsync($"{issuer}|{sid}"); + return token != null; + } +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/CustomInMemoryTicketStore.cs b/playground/Auth0.AspNetCore.Authentication.Playground/CustomInMemoryTicketStore.cs index 542d80f..7e417b8 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/CustomInMemoryTicketStore.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/CustomInMemoryTicketStore.cs @@ -4,46 +4,45 @@ using System.Linq; using System.Threading.Tasks; -namespace Auth0.AspNetCore.Authentication.Playground +namespace Auth0.AspNetCore.Authentication.Playground; + +public class CustomInMemoryTicketStore : ITicketStore { - public class CustomInMemoryTicketStore : ITicketStore - { - private readonly IMemoryCache _cache; + private readonly IMemoryCache _cache; - public CustomInMemoryTicketStore(IMemoryCache cache) - { - _cache = cache; - } + public CustomInMemoryTicketStore(IMemoryCache cache) + { + _cache = cache; + } - public Task RemoveAsync(string key) - { - _cache.Remove(key); + public Task RemoveAsync(string key) + { + _cache.Remove(key); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task RetrieveAsync(string key) - { - var ticket = _cache.Get(key); + public Task RetrieveAsync(string key) + { + var ticket = _cache.Get(key); - return Task.FromResult(ticket); - } + return Task.FromResult(ticket); + } - public Task RenewAsync(string key, AuthenticationTicket ticket) - { - _cache.Set(key, ticket); + public Task RenewAsync(string key, AuthenticationTicket ticket) + { + _cache.Set(key, ticket); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task StoreAsync(AuthenticationTicket ticket) - { - var key = ticket.Principal.Claims - .First(c => c.Type == "sid").Value; + public Task StoreAsync(AuthenticationTicket ticket) + { + var key = ticket.Principal.Claims + .First(c => c.Type == "sid").Value; - _cache.Set(key, ticket); + _cache.Set(key, ticket); - return Task.FromResult(key); - } + return Task.FromResult(key); } -} +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/CustomLogoutTokenHandler.cs b/playground/Auth0.AspNetCore.Authentication.Playground/CustomLogoutTokenHandler.cs index 5b529dc..2636c17 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/CustomLogoutTokenHandler.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/CustomLogoutTokenHandler.cs @@ -3,29 +3,27 @@ using System.Threading.Tasks; using Auth0.AspNetCore.Authentication.BackchannelLogout; -namespace Auth0.AspNetCore.Authentication.Playground -{ - public class CustomLogoutTokenHandler : ILogoutTokenHandler - { - private readonly IMemoryCache _memoryCache; +namespace Auth0.AspNetCore.Authentication.Playground; - public CustomLogoutTokenHandler(IMemoryCache memoryCache) - { - _memoryCache = memoryCache; - } +public class CustomLogoutTokenHandler : ILogoutTokenHandler +{ + private readonly IMemoryCache _memoryCache; - public Task OnTokenReceivedAsync(string issuer, string sid, string logoutToken, TimeSpan expiration) - { - _memoryCache.Set($"{issuer}|{sid}", logoutToken, expiration); + public CustomLogoutTokenHandler(IMemoryCache memoryCache) + { + _memoryCache = memoryCache; + } - return Task.CompletedTask; - } + public Task OnTokenReceivedAsync(string issuer, string sid, string logoutToken, TimeSpan expiration) + { + _memoryCache.Set($"{issuer}|{sid}", logoutToken, expiration); - public Task IsLoggedOutAsync(string issuer, string sid) - { - var token = _memoryCache.Get($"{issuer}|{sid}"); - return Task.FromResult(token != null); - } + return Task.CompletedTask; } -} + public Task IsLoggedOutAsync(string issuer, string sid) + { + var token = _memoryCache.Get($"{issuer}|{sid}"); + return Task.FromResult(token != null); + } +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Models/ErrorViewModel.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Models/ErrorViewModel.cs index 5a3087d..7a12eb5 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Models/ErrorViewModel.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Models/ErrorViewModel.cs @@ -1,9 +1,8 @@ -namespace Auth0.AspNetCore.Authentication.Playground.Models +namespace Auth0.AspNetCore.Authentication.Playground.Models; + +public class ErrorViewModel { - public class ErrorViewModel - { - public string RequestId { get; set; } + public string RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - } -} + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs index d66cb51..0f94610 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs @@ -1,13 +1,12 @@ -namespace Auth0.AspNetCore.Authentication.Playground.Models +namespace Auth0.AspNetCore.Authentication.Playground.Models; + +public class UserProfileViewModel { - public class UserProfileViewModel - { - public string Country { get; set; } + public string Country { get; set; } - public string EmailAddress { get; set; } + public string EmailAddress { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public string ProfileImage { get; set; } - } -} + public string ProfileImage { get; set; } +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/PlaygroundConstants.cs b/playground/Auth0.AspNetCore.Authentication.Playground/PlaygroundConstants.cs index 8196685..432b4be 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/PlaygroundConstants.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/PlaygroundConstants.cs @@ -1,22 +1,21 @@ -namespace Auth0.AspNetCore.Authentication.Playground +namespace Auth0.AspNetCore.Authentication.Playground; + +internal class PlaygroundConstants { - internal class PlaygroundConstants - { - /// - /// The Authentication Scheme, used when configuring OpenIdConnect - /// - public static string AuthenticationScheme = "Auth0"; - /// - /// The second Authentication Scheme, used when configuring OpenIdConnect - /// - public static string AuthenticationScheme2 = "Auth02"; - /// - /// The Authentication Scheme, used when configuring OpenIdConnect - /// - public static string CookieAuthenticationScheme = "Auth0.Cookies"; - /// - /// The Authentication Scheme, used when configuring OpenIdConnect - /// - public static string CookieAuthenticationScheme2 = "Auth02.Cookies"; - } -} + /// + /// The Authentication Scheme, used when configuring OpenIdConnect + /// + public static string AuthenticationScheme = "Auth0"; + /// + /// The second Authentication Scheme, used when configuring OpenIdConnect + /// + public static string AuthenticationScheme2 = "Auth02"; + /// + /// The Authentication Scheme, used when configuring OpenIdConnect + /// + public static string CookieAuthenticationScheme = "Auth0.Cookies"; + /// + /// The Authentication Scheme, used when configuring OpenIdConnect + /// + public static string CookieAuthenticationScheme2 = "Auth02.Cookies"; +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs index 8ae72b9..5341de5 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs @@ -1,20 +1,18 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; -namespace Auth0.AspNetCore.Authentication.Playground +namespace Auth0.AspNetCore.Authentication.Playground; +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + CreateHostBuilder(args).Build().Run(); } -} + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); +} \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs index f008ce0..4a9d3a0 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs @@ -9,181 +9,112 @@ using Auth0.AspNetCore.Authentication.BackchannelLogout; using Microsoft.Extensions.Caching.Distributed; -namespace Auth0.AspNetCore.Authentication.Playground +namespace Auth0.AspNetCore.Authentication.Playground; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services - .AddAuth0WebAppAuthentication(PlaygroundConstants.AuthenticationScheme, options => - { - options.Domain = Configuration["Auth0:Domain"]; - options.ClientId = Configuration["Auth0:ClientId"]; - options.ClientSecret = Configuration["Auth0:ClientSecret"]; - }) - .WithAccessToken(options => - { - options.Audience = Configuration["Auth0:Audience"]; - options.UseRefreshTokens = true; + Configuration = configuration; + } - options.Events = new Auth0WebAppWithAccessTokenEvents - { - OnMissingRefreshToken = async (context) => - { - await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); - var authenticationProperties = new LoginAuthenticationPropertiesBuilder().WithRedirectUri("/").Build(); - await context.ChallengeAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); - } - }; - }).WithBackchannelLogout(); + public IConfiguration Configuration { get; } + public void ConfigureServices(IServiceCollection services) + { + services + .AddAuth0WebAppAuthentication(PlaygroundConstants.AuthenticationScheme, options => + { + options.Domain = Configuration["Auth0:Domain"]; + options.ClientId = Configuration["Auth0:ClientId"]; + options.ClientSecret = Configuration["Auth0:ClientSecret"]; + }) + .WithAccessToken(options => + { + options.Audience = Configuration["Auth0:Audience"]; + options.UseRefreshTokens = true; + options.Events = new Auth0WebAppWithAccessTokenEvents + { + OnMissingRefreshToken = async (context) => + { + await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + var authenticationProperties = new LoginAuthenticationPropertiesBuilder().WithRedirectUri("/").Build(); + await context.ChallengeAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); + } + }; + }).WithBackchannelLogout(); - // The above configuration works but is not suitable for production as it uses an InMemory cache to store the logout token - // Instead, for production use any of the following, additional, configuration. - // Note: For the statefull scenario's, ensure to uncomment `ConfigureStatefullSessions` as well. - // ** STATELESS ** + // The above configuration works but is not suitable for production as it uses an InMemory cache to store the logout token + // Instead, for production use any of the following, additional, configuration. + // Note: For the statefull scenario's, ensure to uncomment `ConfigureStatefullSessions` as well. - // 1. Configure the SDK to use a custom LogoutTokenHandler to store the tokens. - // - // ConfigureServicesAuth0CustomStore(services); + // ** STATELESS ** - // ** STATEFUL ** + // 1. Configure the SDK to use a custom LogoutTokenHandler to store the tokens. + // + // ConfigureServicesAuth0CustomStore(services); - // Ensure to uncomment this when using any of the below configurations - // ConfigureStatefullSessions(services); + // ** STATEFUL ** - // 2. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens. - // - // ConfigureServicesAuth0StatfullCustomStore(services); + // Ensure to uncomment this when using any of the below configurations + // ConfigureStatefullSessions(services); - // 3. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens that relies on IDistributedCache. - // - // ConfigureServicesAuth0StatfullCustomStoreUsingDistributedCache(services); + // 2. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens. + // + // ConfigureServicesAuth0StatfullCustomStore(services); - // 4. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to not store the tokens but immediatly clear the session. - // - // ConfigureServicesAuth0StatfullInstantSessionClear(services); + // 3. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens that relies on IDistributedCache. + // + // ConfigureServicesAuth0StatfullCustomStoreUsingDistributedCache(services); + // 4. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to not store the tokens but immediatly clear the session. + // + // ConfigureServicesAuth0StatfullInstantSessionClear(services); - services.AddControllersWithViews(); - } - /// - /// Configure the SDK to use a custom LogoutTokenHandler to store the tokens. - /// This means the logout token is stored in memory. - /// - /// - private void ConfigureServicesAuth0CustomStore(IServiceCollection services) - { - // Configure a custom LogoutTokenHandler, allowing you to store the logout token wherever you want - // The Identity information is still stored stateless, in the cookie. - services.AddTransient(); - } + services.AddControllersWithViews(); + } - /// - /// Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens. - /// - /// - private void ConfigureServicesAuth0StatfullCustomStore(IServiceCollection services) - { - // Configure a custom LogoutTokenHandler, allowing you to store the logout token wherever you want - services.AddTransient(); - } + - /// - /// Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens that relies on IDistributedCache. - /// - /// - private void ConfigureServicesAuth0StatfullCustomStoreUsingDistributedCache(IServiceCollection services) - { - // Configure a Distributed Cache - services.AddSingleton(); - // Configure a custom LogoutTokenHandler, allowing you to store the logout token wherever you want - services.AddTransient(); - } - /// - /// Configure the SDK to use Stateful session and a custom LogoutTokenHandler to not store the tokens but immediately clear the session. - /// - /// - private void ConfigureServicesAuth0StatfullInstantSessionClear(IServiceCollection services) + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) { - // Configure a custom LogoutTokenHandler, allowing you to clear the stateful session - services.AddTransient(); + app.UseDeveloperExceptionPage(); } - - private void ConfigureStatefullSessions(IServiceCollection services) + else { - // Configure a custom ITicketStore to store the Identity Information on the server - services.AddTransient(); - // Configure the Cookie Middleware to use the CustomInMemoryTicketStore - services.AddSingleton, ConfigureCookieAuthenticationOptions>(); + app.UseExceptionHandler("/Home/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); } + app.UseHttpsRedirection(); + app.UseStaticFiles(); + app.UseRouting(); - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Home/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - app.UseHttpsRedirection(); - app.UseStaticFiles(); + app.UseAuthentication(); + app.UseAuthorization(); - app.UseRouting(); - - app.UseAuthentication(); - app.UseAuthorization(); - - app.UseBackchannelLogout(); + app.UseBackchannelLogout(); - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); - }); - } - } - - public class ConfigureCookieAuthenticationOptions - : IPostConfigureOptions - { - private readonly ITicketStore _ticketStore; - - public ConfigureCookieAuthenticationOptions(ITicketStore ticketStore) + app.UseEndpoints(endpoints => { - _ticketStore = ticketStore; - } - - public void PostConfigure(string name, - CookieAuthenticationOptions options) - { - options.SessionStore = _ticketStore; - } + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); + }); } } From cabef9de4f8ad80e64797f81512cc837caac6a14 Mon Sep 17 00:00:00 2001 From: kailash-b Date: Thu, 14 Aug 2025 14:27:03 +0530 Subject: [PATCH 3/4] Get rid of Startup.cs in playground --- .../Program.cs | 173 ++++++++++++++++-- .../Startup.cs | 120 ------------ 2 files changed, 162 insertions(+), 131 deletions(-) delete mode 100644 playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs index 5341de5..f39bef8 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Program.cs @@ -1,18 +1,169 @@ -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Builder; +using Auth0.AspNetCore.Authentication; +using Auth0.AspNetCore.Authentication.BackchannelLogout; +using Auth0.AspNetCore.Authentication.Playground; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; -namespace Auth0.AspNetCore.Authentication.Playground; -public class Program +var builder = WebApplication.CreateBuilder(args); +builder.Services + .AddAuth0WebAppAuthentication(PlaygroundConstants.AuthenticationScheme, options => + { + options.Domain = builder.Configuration["Auth0:Domain"]; + options.ClientId = builder.Configuration["Auth0:ClientId"]; + options.ClientSecret = builder.Configuration["Auth0:ClientSecret"]; + }) + .WithAccessToken(options => + { + options.Audience = builder.Configuration["Auth0:Audience"]; + options.UseRefreshTokens = true; + + options.Events = new Auth0WebAppWithAccessTokenEvents + { + OnMissingRefreshToken = async (context) => + { + await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + var authenticationProperties = new LoginAuthenticationPropertiesBuilder().WithRedirectUri("/").Build(); + await context.ChallengeAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); + } + }; + }).WithBackchannelLogout(); + + +// The above configuration works but is not suitable for production as it uses an InMemory cache to store the logout token +// Instead, for production use any of the following, additional, configuration. +// Note: For the statefull scenario's, ensure to uncomment `ConfigureStatefullSessions` as well. + + +// ** STATELESS ** + +// 1. Configure the SDK to use a custom LogoutTokenHandler to store the tokens. +// +// ConfigureServicesAuth0CustomStore(services); + + +// ** STATEFUL ** + +// Ensure to uncomment this when using any of the below configurations +// ConfigureStatefullSessions(services); + + +// 2. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens. +// +// ConfigureServicesAuth0StatfullCustomStore(services); + + +// 3. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens that relies on IDistributedCache. +// +// ConfigureServicesAuth0StatfullCustomStoreUsingDistributedCache(services); + + +// 4. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to not store the tokens but immediatly clear the session. +// +// ConfigureServicesAuth0StatfullInstantSessionClear(services); + +builder.Services.AddControllersWithViews(); + +var app = builder.Build(); +if (app.Environment.IsDevelopment()) +{ + app.UseDeveloperExceptionPage(); +} +else +{ + app.UseExceptionHandler("/Home/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +app.UseHttpsRedirection(); +app.UseStaticFiles(); + +app.UseRouting(); + +app.UseAuthentication(); +app.UseAuthorization(); + +app.UseBackchannelLogout(); + +app.UseEndpoints(endpoints => +{ + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); +}); +app.Run(); + +/// +/// Configure the SDK to use a custom LogoutTokenHandler to store the tokens. +/// This means the logout token is stored in memory. +/// +/// +void ConfigureServicesAuth0CustomStore(IServiceCollection services) +{ + // Configure a custom LogoutTokenHandler, allowing you to store the logout token wherever you want + // The Identity information is still stored stateless, in the cookie. + services.AddTransient(); +} + + +/// +/// Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens. +/// +/// +void ConfigureServicesAuth0StatfullCustomStore(IServiceCollection services) +{ + // Configure a custom LogoutTokenHandler, allowing you to store the logout token wherever you want + services.AddTransient(); +} + +/// +/// Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens that relies on IDistributedCache. +/// +/// +void ConfigureServicesAuth0StatfullCustomStoreUsingDistributedCache(IServiceCollection services) +{ + // Configure a Distributed Cache + services.AddSingleton(); + // Configure a custom LogoutTokenHandler, allowing you to store the logout token wherever you want + services.AddTransient(); +} + +/// +/// Configure the SDK to use Stateful session and a custom LogoutTokenHandler to not store the tokens but immediately clear the session. +/// +/// +void ConfigureServicesAuth0StatfullInstantSessionClear(IServiceCollection services) { - public static void Main(string[] args) + // Configure a custom LogoutTokenHandler, allowing you to clear the stateful session + services.AddTransient(); +} + +void ConfigureStatefullSessions(IServiceCollection services) +{ + // Configure a custom ITicketStore to store the Identity Information on the server + services.AddTransient(); + // Configure the Cookie Middleware to use the CustomInMemoryTicketStore + services.AddSingleton, ConfigureCookieAuthenticationOptions>(); +} + +public class ConfigureCookieAuthenticationOptions + : IPostConfigureOptions +{ + private readonly ITicketStore _ticketStore; + + public ConfigureCookieAuthenticationOptions(ITicketStore ticketStore) { - CreateHostBuilder(args).Build().Run(); + _ticketStore = ticketStore; } - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + public void PostConfigure(string name, + CookieAuthenticationOptions options) + { + options.SessionStore = _ticketStore; + } } \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs deleted file mode 100644 index 4a9d3a0..0000000 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Startup.cs +++ /dev/null @@ -1,120 +0,0 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Options; -using Auth0.AspNetCore.Authentication.BackchannelLogout; -using Microsoft.Extensions.Caching.Distributed; - -namespace Auth0.AspNetCore.Authentication.Playground; - -public class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services - .AddAuth0WebAppAuthentication(PlaygroundConstants.AuthenticationScheme, options => - { - options.Domain = Configuration["Auth0:Domain"]; - options.ClientId = Configuration["Auth0:ClientId"]; - options.ClientSecret = Configuration["Auth0:ClientSecret"]; - }) - .WithAccessToken(options => - { - options.Audience = Configuration["Auth0:Audience"]; - options.UseRefreshTokens = true; - - options.Events = new Auth0WebAppWithAccessTokenEvents - { - OnMissingRefreshToken = async (context) => - { - await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); - var authenticationProperties = new LoginAuthenticationPropertiesBuilder().WithRedirectUri("/").Build(); - await context.ChallengeAsync(PlaygroundConstants.AuthenticationScheme, authenticationProperties); - } - }; - }).WithBackchannelLogout(); - - - - // The above configuration works but is not suitable for production as it uses an InMemory cache to store the logout token - // Instead, for production use any of the following, additional, configuration. - // Note: For the statefull scenario's, ensure to uncomment `ConfigureStatefullSessions` as well. - - - // ** STATELESS ** - - // 1. Configure the SDK to use a custom LogoutTokenHandler to store the tokens. - // - // ConfigureServicesAuth0CustomStore(services); - - - // ** STATEFUL ** - - // Ensure to uncomment this when using any of the below configurations - // ConfigureStatefullSessions(services); - - - // 2. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens. - // - // ConfigureServicesAuth0StatfullCustomStore(services); - - - // 3. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to store the tokens that relies on IDistributedCache. - // - // ConfigureServicesAuth0StatfullCustomStoreUsingDistributedCache(services); - - - // 4. Configure the SDK to use Stateful session and a custom LogoutTokenHandler to not store the tokens but immediatly clear the session. - // - // ConfigureServicesAuth0StatfullInstantSessionClear(services); - - - - services.AddControllersWithViews(); - } - - - - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Home/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseAuthentication(); - app.UseAuthorization(); - - app.UseBackchannelLogout(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); - }); - } -} From 69825e2e80b7fea526601e923b779136507a4ddf Mon Sep 17 00:00:00 2001 From: kailash-b Date: Thu, 14 Aug 2025 16:57:03 +0530 Subject: [PATCH 4/4] Display tokens on Profile page for easier debugging --- .../Controllers/AccountController.cs | 5 ++- .../Models/UserProfileViewModel.cs | 9 +++--- .../Views/Account/Profile.cshtml | 31 +++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs index 1f766cc..60388ea 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Controllers/AccountController.cs @@ -67,7 +67,10 @@ public async Task Profile() { Name = User.Identity.Name, EmailAddress = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value, - ProfileImage = User.Claims.FirstOrDefault(c => c.Type == "picture")?.Value + ProfileImage = User.Claims.FirstOrDefault(c => c.Type == "picture")?.Value, + AccessToken = accessToken, + IdToken = idToken, + RefreshToken = refreshToken }); } diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs b/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs index 0f94610..789f243 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Models/UserProfileViewModel.cs @@ -2,11 +2,10 @@ public class UserProfileViewModel { - public string Country { get; set; } - - public string EmailAddress { get; set; } - public string Name { get; set; } - + public string EmailAddress { get; set; } public string ProfileImage { get; set; } + public string AccessToken { get; set; } + public string IdToken { get; set; } + public string RefreshToken { get; set; } } \ No newline at end of file diff --git a/playground/Auth0.AspNetCore.Authentication.Playground/Views/Account/Profile.cshtml b/playground/Auth0.AspNetCore.Authentication.Playground/Views/Account/Profile.cshtml index ff03419..089d22e 100644 --- a/playground/Auth0.AspNetCore.Authentication.Playground/Views/Account/Profile.cshtml +++ b/playground/Auth0.AspNetCore.Authentication.Playground/Views/Account/Profile.cshtml @@ -19,5 +19,36 @@

+
+
+
+ +
+
@Model.AccessToken
+ +
+
+
+ +
+
@Model.IdToken
+ +
+
+
+ +
+
@Model.RefreshToken
+ +
+
+ +
+
\ No newline at end of file