mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Fixed redirect due to unauthorized request.
This commit is contained in:
parent
0073e99c6d
commit
2c07ba868f
@ -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]
|
||||
|
@ -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;
|
||||
|
||||
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();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -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…
Reference in New Issue
Block a user