From 2c07ba868f4635d6598c29987bc4de068beb058f Mon Sep 17 00:00:00 2001 From: Uncled1023 Date: Thu, 17 Jan 2019 19:26:49 -0800 Subject: [PATCH] Fixed redirect due to unauthorized request. --- .../Areas/User/Controllers/UserController.cs | 85 ++----------------- Teknik/Security/CookieEventHandler.cs | 35 ++++---- Teknik/Security/LogoutSessionManager.cs | 3 +- 3 files changed, 26 insertions(+), 97 deletions(-) diff --git a/Teknik/Areas/User/Controllers/UserController.cs b/Teknik/Areas/User/Controllers/UserController.cs index 6ba2d34..314e825 100644 --- a/Teknik/Areas/User/Controllers/UserController.cs +++ b/Teknik/Areas/User/Controllers/UserController.cs @@ -49,7 +49,7 @@ namespace Teknik.Areas.Users.Controllers private readonly IHttpContextAccessor _httpContextAccessor; private ISession _session => _httpContextAccessor.HttpContext.Session; - public LogoutSessionManager _logoutSessions { get; } + private readonly LogoutSessionManager _logoutSessions; public UserController(ILogger logger, Config config, TeknikEntities dbContext, LogoutSessionManager logoutSessions, IHttpContextAccessor httpContextAccessor) : base(logger, config, dbContext) { @@ -83,87 +83,14 @@ namespace Teknik.Areas.Users.Controllers [HttpGet] public async Task Logout() { + // these are the sub & sid to signout + //var sub = User.FindFirst("sub")?.Value; + //var sid = User.FindFirst("sid")?.Value; + await HttpContext.SignOutAsync("Cookies"); await HttpContext.SignOutAsync("oidc"); - } - [HttpPost] - [AllowAnonymous] - public async Task Logout(string logout_token) - { - Response.Headers.Add("Cache-Control", "no-cache, no-store"); - Response.Headers.Add("Pragma", "no-cache"); - - try - { - var user = await ValidateLogoutToken(logout_token); - - // these are the sub & sid to signout - var sub = user.FindFirst("sub")?.Value; - var sid = user.FindFirst("sid")?.Value; - - _logoutSessions.Add(sub, sid); - - return Ok(); - } - catch { } - - return BadRequest(); - } - - private async Task ValidateLogoutToken(string logoutToken) - { - var claims = await ValidateJwt(logoutToken); - - if (claims.FindFirst("sub") == null && claims.FindFirst("sid") == null) throw new Exception("Invalid logout token"); - - var nonce = claims.FindFirstValue("nonce"); - if (!String.IsNullOrWhiteSpace(nonce)) throw new Exception("Invalid logout token"); - - var eventsJson = claims.FindFirst("events")?.Value; - if (String.IsNullOrWhiteSpace(eventsJson)) throw new Exception("Invalid logout token"); - - var events = JObject.Parse(eventsJson); - var logoutEvent = events.TryGetValue("http://schemas.openid.net/event/backchannel-logout"); - if (logoutEvent == null) throw new Exception("Invalid logout token"); - - return claims; - } - - private async Task ValidateJwt(string jwt) - { - // read discovery document to find issuer and key material - var disco = await DiscoveryClient.GetAsync(_config.UserConfig.IdentityServerConfig.Authority); - - var keys = new List(); - foreach (var webKey in disco.KeySet.Keys) - { - var e = Base64Url.Decode(webKey.E); - var n = Base64Url.Decode(webKey.N); - - var key = new RsaSecurityKey(new RSAParameters { Exponent = e, Modulus = n }) - { - KeyId = webKey.Kid - }; - - keys.Add(key); - } - - var parameters = new TokenValidationParameters - { - ValidIssuer = disco.Issuer, - ValidAudience = _config.UserConfig.IdentityServerConfig.ClientId, - IssuerSigningKeys = keys, - - NameClaimType = JwtClaimTypes.Name, - RoleClaimType = JwtClaimTypes.Role - }; - - var handler = new JwtSecurityTokenHandler(); - handler.InboundClaimTypeMap.Clear(); - - var user = handler.ValidateToken(jwt, parameters, out var _); - return user; + //_logoutSessions.Add(sub, sid); } [AllowAnonymous] diff --git a/Teknik/Security/CookieEventHandler.cs b/Teknik/Security/CookieEventHandler.cs index 9b5d26d..72a4103 100644 --- a/Teknik/Security/CookieEventHandler.cs +++ b/Teknik/Security/CookieEventHandler.cs @@ -15,26 +15,29 @@ namespace Teknik.Security { public CookieEventHandler(LogoutSessionManager logoutSessions) { - LogoutSessions = logoutSessions; + _LogoutSessions = logoutSessions; } - public LogoutSessionManager LogoutSessions { get; } + private static LogoutSessionManager _LogoutSessions; - public override async Task ValidatePrincipal(CookieValidatePrincipalContext context) + public override async Task RedirectToAccessDenied(RedirectContext context) { - if (context.Principal.Identity.IsAuthenticated) - { - var sub = context.Principal.FindFirst("sub")?.Value; - var sid = context.Principal.FindFirst("sid")?.Value; - - if (LogoutSessions.IsLoggedOut(sub, sid)) - { - context.RejectPrincipal(); - await context.HttpContext.SignOutAsync(); - - // todo: if we have a refresh token, it should be revoked here. - } - } + context.Response.StatusCode = 403; } + + //public override async Task ValidatePrincipal(CookieValidatePrincipalContext context) + //{ + // if (context.Principal.Identity.IsAuthenticated) + // { + // var sub = context.Principal.FindFirst("sub")?.Value; + // var sid = context.Principal.FindFirst("sid")?.Value; + + // if (LogoutSessions.IsLoggedOut(sub, sid)) + // { + // context.RejectPrincipal(); + // await context.HttpContext.SignOutAsync(); + // } + // } + //} } } diff --git a/Teknik/Security/LogoutSessionManager.cs b/Teknik/Security/LogoutSessionManager.cs index a674b4c..701a9b9 100644 --- a/Teknik/Security/LogoutSessionManager.cs +++ b/Teknik/Security/LogoutSessionManager.cs @@ -7,8 +7,7 @@ namespace Teknik.Security { public class LogoutSessionManager { - // yes - that needs to be thread-safe, distributed etc (it's a sample) - List _sessions = new List(); + private static List _sessions = new List(); public void Add(string sub, string sid) {