Detect idle users and auto logout them in .NET Core 5 Razor pages - session

I am working on a ASP.NET Core 5 web application using Razor pages.
My task to detect idle users (being idle for 5 minutes) and auto logout them from the application. They need to login again to continue.
I've used this code in Startup.cs:
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(5);
options.Cookie.Name = "cookie_name";
});
How can I detect users idle time and logout them?

I think you could set as below:
builder.Services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.SlidingExpiration = true;
options.LoginPath = ".....";
options.AccessDeniedPath = "....";
});
idle users have to login again after 5 minutes,and if The SlidingExpiration is set to true , a new cookie with a new expiration time woould be re-issued any time it processes a request which is more than halfway through the expiration window.you could check this document

Related

ASP.NET Core MVC - cookie authentication: can a malicious user edit their cookie to give themselves more permissions?

TL;DR Can a malicious user modify their cookie so they have claims they should not, or is the cookie string encrypted or protected in some way?
I've implemented cookie authentication in my ASP.NET Core 6.0 MVC application.
Program.cs
builder.Services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
options.SlidingExpiration = true;
options.AccessDeniedPath = "/Forbidden/";
options.Cookie.Name = "IANSW_Session";
options.Cookie.HttpOnly = true;
});
In my login controller the SignInAsync method is called like this:
var authProperties = new AuthenticationProperties();
var claims = await _claimsService.GetClaimsForUsername(userResult.Username);
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
Now, one of these claims will be a CanEditPosts claim. The 'EditPost' action looks something like this:
[Authorize("CanEditPosts")]
public async Task<IActionResult> EditPost(int postId)
{
if (!User.Identity.IsAuthenticated) return Json("Error");
var userPosts = _userPostService.GetAllUserPostsIDs(User.Identity.Name);
if (userPosts.Contains(postId))
{
// User is trying to edit one of their own posts
}
// etc...
}
My question: is it possible for a user to edit their own cookie to give themselves the CanEditPosts claim, or perhaps change their Name in the cookie so the code thinks someone else's posts belongs to them?
I can see in my browsers dev tools the cookie looks like this, but I have no idea if this is encrypted or protected in some other way.
From microsoft documentation:
SignInAsync creates an encrypted cookie and adds it to the current response.
ASP.NET Core's Data Protection system is used for encryption.

OIDC Logging out issue , How to control the browser programatically/manually?

I’m using OIDC client in my Xamarin App(Code below) So when I make the call oidcClient.LogoutAsync browser opens, and while I’m awaiting the response back from the browser to the app if I need to minimise the app for some reason. The call then gets interrupted and the app stays on the browser, Never gives a response back, unless user manually closes the browser. Now I have no control over the browser from my app, Is there a way to avoid this. Maybe not open the browser altogether and logout silently. Please suggest a workaround.
private OidcClient InitializeAuthClient()
{
var options = new OidcClientOptions
{
Authority = Config.AuthorityURL,
ClientId = Config.ClientId,
Scope = Config.Scope,
RedirectUri = Config.RedirectUri,
ClientSecret = Config.ClientSecret,
PostLogoutRedirectUri = Config.RedirectUri,
Browser = new WebAuthenticatorBrowser(),
};
return new OidcClient(options);
}
OidcClient oidcClient = InitializeAuthClient();
LogoutResult logoutResult = await oidcClient.LogoutAsync(new LogoutRequest
{ BrowserDisplayMode = IdentityModel.OidcClient.Browser.DisplayMode.Hidden, IdTokenHint = authData.idToken });

MVC Core Google External Provider SignIn Task Timeout

I need some help with implementing of Google External Provider in MVC Core 5 :
I just added Google External Provider in my project , and every thing works fine, but some things is wrong!
here is what I do in my code , and the problem description:
startup.cs :
services.AddIdentity<User, Role>(config =>
{
config.User.RequireUniqueEmail = true;
config.Password.RequireDigit = true;
config.Password.RequireLowercase = true;
config.Password.RequireNonAlphanumeric = false;
config.Password.RequireUppercase = true;
config.Password.RequiredLength = 6;
config.Lockout.AllowedForNewUsers = true;
config.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
config.Lockout.MaxFailedAccessAttempts = 3;
})
.AddErrorDescriber<CustomIdentityErrorDescriber>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddAuthentication()
.AddGoogle("google", opt =>
{
var googleAuth = _config.GetSection("GoogleExternalSignIn");
opt.ClientId = googleAuth["ClientId"];
opt.ClientSecret = googleAuth["ClientSecret"];
opt.SignInScheme = IdentityConstants.ExternalScheme;
//opt.BackchannelTimeout = new TimeSpan(0, 5, 0);
})
;
with this implementation , after I going to login with google , google accounts page will open and I can chose to login with any account, but the problem is,
that it works for every account just for the first time, after that whenever you wanna login with an account , It throw an exception like below :
System.Threading.CancellationToken.ThrowOperationCanceledException()
TimeoutException: The operation was canceled.
System.Threading.CancellationToken.ThrowOperationCanceledException()
TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 300 seconds elapsing.
System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, bool async, bool emitTelemetryStartStop, CancellationToken cancellationToken)
Exception: An error was encountered while handling the remote login.
I tried to set opt.BackchannelTimeout = new TimeSpan(0, 5, 0); in AddGoogle configuration , but after 5 minute taking to trying login, It returns above Exception.
How can I solve it ?
where is the problem ?

OpenID and Individual User Accounts in same MVC application

I want to have an MVC application support individual user accounts for external users and accept tokens from ADFS using an OpenID endpoint for employees.
I created 2 mvc applications. One is setup to use OpenId only and it works correctly by redirecting me to the on-premises ADFS server and sets a cookie so I am authorized to a controller decorated with the [Authorize] attribute.
I have another mvc application on the same server as the first mvc site which is setup to use individual user accounts. I have added code in the Startup.Auth to add OpenId Connect to the OWIN pipeline.
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
MetadataAddress = metadataAddress,
RedirectUri = redirectUri,
//PostLogoutRedirectUri = postLogoutRedirectUri
});
}
I assumed this was all I needed to user OpenID in this second application.
I first access the first mvc (OpenId only) application and sign in. I can access authorized controller actions on that application.
I then try to access the second application (individual user accounts and OpenID) and assumed I would be authorized.
Instead I get redirected a few times between the ADFS server and the mvc app until the "Microsoft.IdentityServer.Web.InvalidRequestException: MSIS7042: The same client browser session has made '6' requests in the last '1' seconds. " error gets thrown.
A fiddler trace shows:
302 TestApp2
200 adfs server
302 TestApp2
302 TestApp2
200 adfs server
etc.
I was able to get this working using this Startup.ConfigureAuth.
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
MetadataAddress = metadataAddress,
RedirectUri = redirectUri,
//PostLogoutRedirectUri = postLogoutRedirectUri
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}

ASP.NET MVC3 - Anti-CSRF and Session timeout

I am implementing Anti-Forgery framework as described here:
http://weblogs.asp.net/srkirkland/archive/2010/04/14/guarding-against-csrf-attacks-in-asp-net-mvc2.aspx
Plus, to minimize the coding effort, I did the token insertion part at client side handling form.onsumit and ajaxsend events. Everything works fine – until the session expires.
In my application, I display a popup when the user session gets timed out where the user can re-login and continue without refreshing the current page so that the work-in-progress will be safe. But this doesn't go well with the Anti-CSRF logic. When the user tries to re-login after a timed-out session, this throws a CSRF exception as the cookie (__RequestVerificationToken_Lw__) is already expired and all the future POSTs will be invalid until next page refresh.
Is there any way to set the cookie end time to a future date rather than 'session'? I tried to edit Response.Cookie but that made the cookie invalid.
Any help would be appreciated.
Thanks
At the time of user session out (when displaying a popup) is it possible for you to set the httpcookie with expiry in server side.
I have extracted some code from the microsofts antiforgery token implementation.
internal static string GetAntiForgeryTokenName(string appPath)
{
if (string.IsNullOrEmpty(appPath))
{
return "__RequestVerificationToken";
}
return "__RequestVerificationToken_" + Base64EncodeForCookieName(appPath);
}
private static string Base64EncodeForCookieName(string s)
{
byte[] bytes = Encoding.UTF8.GetBytes(s);
string text = Convert.ToBase64String(bytes);
return text.Replace('+', '.').Replace('/', '-').Replace('=', '_');
}
Below code which set the cookie in server side.
string antiForgeryTokenName = GetAntiForgeryTokenName(HttpContext.Request.ApplicationPath);
HttpCookie httpCookie = HttpContext.Request.Cookies[antiForgeryTokenName];
HttpCookie httpCookie2 = new HttpCookie(antiForgeryTokenName, httpCookie.Value)
{
HttpOnly = true
//// your domain Domain = ,
//// path Path = ,
//// set path Expires =
};
HttpContext.Response.Cookies.Set(httpCookie2);
Please note that I haven't tested this code, just give a try if you dont have any other options.

Resources