Browse Source

Fixed redirect due to unauthorized request.

tags/3.0.0^2
Teknikode 10 months ago
parent
commit
2c07ba868f

+ 6
- 79
Teknik/Areas/User/Controllers/UserController.cs View File

@@ -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> 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<IActionResult> 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<ClaimsPrincipal> 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<ClaimsPrincipal> 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<SecurityKey>();
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]

+ 18
- 15
Teknik/Security/CookieEventHandler.cs View File

@@ -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<CookieAuthenticationOptions> context)
{
if (context.Principal.Identity.IsAuthenticated)
{
var sub = context.Principal.FindFirst("sub")?.Value;
var sid = context.Principal.FindFirst("sid")?.Value;
context.Response.StatusCode = 403;
}

if (LogoutSessions.IsLoggedOut(sub, sid))
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync();
//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;

// todo: if we have a refresh token, it should be revoked here.
}
}
}
// if (LogoutSessions.IsLoggedOut(sub, sid))
// {
// context.RejectPrincipal();
// await context.HttpContext.SignOutAsync();
// }
// }
//}
}
}

+ 1
- 2
Teknik/Security/LogoutSessionManager.cs View File

@@ -7,8 +7,7 @@ namespace Teknik.Security
{
public class LogoutSessionManager
{
// yes - that needs to be thread-safe, distributed etc (it's a sample)
List<Session> _sessions = new List<Session>();
private static List<Session> _sessions = new List<Session>();

public void Add(string sub, string sid)
{

Loading…
Cancel
Save