/// <inheritdoc /> public async Task RenewAsync(string key, AuthenticationTicket ticket) { ArgumentNullException.ThrowIfNull(ticket); var session = await _store.GetSessionAsync(key); if (session == null) { throw new InvalidOperationException($"No matching item in store for key `{key}`"); } _logger.LogDebug("Renewing AuthenticationTicket for key {key}, with expiration: {expiration}", key, ticket.GetExpiration()); var sub = ticket.GetSubjectId(); var sid = ticket.GetSessionId(); var name = String.IsNullOrWhiteSpace(_options.ServerSideSessions.UserDisplayNameClaimType) ? null : ticket.Principal.FindFirst(_options.ServerSideSessions.UserDisplayNameClaimType)?.Value; var isNew = session.SubjectId != sub || session.SessionId != sid; if (isNew) { session.Created = ticket.GetIssued(); session.SubjectId = sub; session.SessionId = sid; } session.Renewed = ticket.GetIssued(); session.Expires = ticket.GetExpiration(); session.DisplayName = name; session.Ticket = ticket.Serialize(_protector); await _store.UpdateSessionAsync(session); }
/// <inheritdoc/> public virtual async Task <bool> ValidateSessionAsync(SessionValidationRequest request) { if (ServerSideSessionStore != null) { var shouldCoordinate = request.Client.CoordinateLifetimeWithUserSession == true || (Options.Authentication.CoordinateClientLifetimesWithUserSession && request.Client.CoordinateLifetimeWithUserSession != false); if (shouldCoordinate) { var sessions = await ServerSideSessionStore.GetSessionsAsync(new SessionFilter { SubjectId = request.SubjectId, SessionId = request.SessionId }); var valid = sessions.Count > 0 && sessions.Any(x => x.Expires == null || DateTime.UtcNow < x.Expires.Value); if (!valid) { Logger.LogDebug("Due to missing/expired server-side session, failing token validation for subject id {subjectId} and session id {sessionId}", request.SubjectId, request.SessionId); return(false); } Logger.LogDebug("Due to client token use, extending server-side session for subject id {subjectId} and session id {sessionId}", request.SubjectId, request.SessionId); foreach (var session in sessions) { if (session.Expires.HasValue) { // setting the Expires flag on the entity (and not in the AuthenticationTicket) // since we know that when loading from the DB that column will overwrite the // expires in the AuthenticationTicket. var diff = session.Expires.Value.Subtract(session.Renewed); session.Renewed = DateTime.UtcNow; session.Expires = session.Renewed.Add(diff); await ServerSideSessionStore.UpdateSessionAsync(session); } } } } return(true); }
public async Task corrupted_server_side_session_should_logout_user() { await _pipeline.LoginAsync("bob"); var sessions = await _sessionStore.GetSessionsAsync(new SessionFilter { SubjectId = "bob" }); var session = await _sessionStore.GetSessionAsync(sessions.Single().Key); session.Ticket = "invalid"; await _sessionStore.UpdateSessionAsync(session); (await IsLoggedIn()).Should().BeFalse(); (await _sessionStore.GetSessionsAsync(new SessionFilter { SubjectId = "bob" })).Should().BeEmpty(); }