#22 API for session renewal

This commit is contained in:
Hamid Reza Mohammadi 2020-10-20 19:07:52 +03:30
parent eed7c53ab8
commit e808966f9f
4 changed files with 126 additions and 3 deletions

View File

@ -53,6 +53,30 @@ namespace RSecurityBackend.Controllers
return Ok(res.Result);
}
/// <summary>
/// renew an expired session
/// </summary>
/// <param name="sessionId">user session id</param>
/// <returns>LoggedOnUserModel</returns>
[HttpPut]
[AllowAnonymous]
[Route("relogin/{sessionId}")]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(LoggedOnUserModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task<IActionResult> ReLogin(
Guid sessionId
)
{
string clientIPAddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
RServiceResult<LoggedOnUserModel> res = await _appUserService.ReLogin(sessionId, clientIPAddress);
if (res.Result == null)
{
return BadRequest(res.ExceptionString);
}
return Ok(res.Result);
}
/// <summary>
/// Logout user (users need user:delothersession to logout other users)
/// </summary>

View File

@ -70,6 +70,13 @@
<param name="loginViewModel">loginViewModel</param>
<returns>LoggedOnUserModel</returns>
</member>
<member name="M:RSecurityBackend.Controllers.AppUserControllerBase.ReLogin(System.Guid)">
<summary>
renew an expired session
</summary>
<param name="sessionId">user session id</param>
<returns>LoggedOnUserModel</returns>
</member>
<member name="M:RSecurityBackend.Controllers.AppUserControllerBase.Logout(System.Guid,System.Guid)">
<summary>
Logout user (users need user:delothersession to logout other users)
@ -1820,6 +1827,14 @@
<param name="clientIPAddress"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.ReLogin(System.Guid,System.String)">
<summary>
replace a (probably expired session) with a new one
</summary>
<param name="sessionId"></param>
<param name="clientIPAddress"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.Logout(System.Guid,System.Guid)">
<summary>
Logout
@ -2131,6 +2146,14 @@
<param name="clientIPAddress"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.ReLogin(System.Guid,System.String)">
<summary>
replace a (probably expired session) with a new one
</summary>
<param name="sessionId"></param>
<param name="clientIPAddress"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.AddUserToRole(System.Guid,System.String)">
<summary>
add user to role

View File

@ -24,6 +24,14 @@ namespace RSecurityBackend.Services
/// <returns></returns>
Task<RServiceResult<LoggedOnUserModel>> Login(LoginViewModel loginViewModel, string clientIPAddress);
/// <summary>
/// replace a (probably expired session) with a new one
/// </summary>
/// <param name="sessionId"></param>
/// <param name="clientIPAddress"></param>
/// <returns></returns>
Task<RServiceResult<LoggedOnUserModel>> ReLogin(Guid sessionId, string clientIPAddress);
/// <summary>
/// Logout
/// </summary>

View File

@ -16,7 +16,6 @@ using RSecurityBackend.Models.Auth.Db;
using RSecurityBackend.Models.Auth.ViewModels;
using RSecurityBackend.Models.Generic;
using RSecurityBackend.DbContext;
using RSecurityBackend.Utilities;
using RSecurityBackend.Models.Image;
using RSecurityBackend.Models.Auth.Memory;
using RSecurityBackend.Models.Audit.Db;
@ -28,7 +27,7 @@ namespace RSecurityBackend.Services.Implementation
/// Authentication Service
/// </summary>
public class AppUserService : IAppUserService
{
{
/// <summary>
/// Login user, if failed return LoggedOnUserModel is null
@ -41,7 +40,7 @@ namespace RSecurityBackend.Services.Implementation
try
{
//we ignore loginViewModel in automatic auditing to prevent loginng password data, so we would add a manual auditing to have enough data on login intrusion and ...
//we ignore loginViewModel in automatic auditing to prevent logging password data, so we would add a manual auditing to have enough data on login intrusion and ...
REvent log = new REvent()
{
EventType = "AppUser/Login (POST)(Manual)",
@ -130,6 +129,75 @@ namespace RSecurityBackend.Services.Implementation
}
}
/// <summary>
/// replace a (probably expired session) with a new one
/// </summary>
/// <param name="sessionId"></param>
/// <param name="clientIPAddress"></param>
/// <returns></returns>
public async Task<RServiceResult<LoggedOnUserModel>> ReLogin(Guid sessionId, string clientIPAddress)
{
try
{
RTemporaryUserSession oldSession = await _context.Sessions.Include(s => s.RAppUser).Where(s => s.Id == sessionId).SingleOrDefaultAsync();
if (oldSession == null)
{
return new RServiceResult<LoggedOnUserModel>(null, "Invalid session");
}
RAppUser appUser = oldSession.RAppUser;
if (appUser.Status == RAppUserStatus.Inactive)
{
return new RServiceResult<LoggedOnUserModel>(null, "User is disabled by an admin.");
}
RServiceResult<SecurableItem[]> securableItems = await GetUserSecurableItemsStatus(appUser.Id);
if (!string.IsNullOrEmpty(securableItems.ExceptionString))
return new RServiceResult<LoggedOnUserModel>(null, securableItems.ExceptionString);
RTemporaryUserSession newSession =
new RTemporaryUserSession()
{
RAppUserId = appUser.Id,
ClientIPAddress = clientIPAddress,
ClientAppName = oldSession.ClientAppName,
Language = oldSession.Language,
LoginTime = DateTime.Now,
LastRenewal = DateTime.Now,
ValidUntil = DateTime.Now + TimeSpan.FromSeconds(DefaultTokenExpirationInSeconds),
Token = ""
};
await _context.Sessions.AddAsync(newSession);
_context.Sessions.Remove(oldSession);
await _context.SaveChangesAsync();
RServiceResult<string> userToken = await GenerateToken(appUser.UserName, appUser.Id, newSession.Id);
if (userToken.Result == null)
{
return new RServiceResult<LoggedOnUserModel>(null, userToken.ExceptionString);
}
newSession.Token = userToken.Result;
_context.Sessions.Update(newSession);
_context.SaveChanges();
return
new RServiceResult<LoggedOnUserModel>(
new LoggedOnUserModel()
{
SessionId = newSession.Id,
User = new PublicRAppUser(appUser),
Token = userToken.Result,
SecurableItem = securableItems.Result
}
);
}
catch (Exception exp)
{
return new RServiceResult<LoggedOnUserModel>(null, exp.ToString());
}
}
/// <summary>
/// add user to role
/// </summary>