ASP.NET MVC3 Forms Authentication user logon session renew - ajax

I have an AJAX method to call on server to return ".ASPXAUTH" cookie expiration time.
It works properly when the auth cookie presents.
Besides I want to renew user logon session with another AJAX call. I have a blank method "RenewSession" which is just for to make a call to the server. Is there any way to do this using Forms Authentication?
The problem is in that when I make a request to server to my "RenewSession" method to renew the session Response.Cookies array is always containing 0 items. But actually when the ".ASPXAUTH" cookie expiration time gets to 0 it renews.
So can anyone explain is it a browsers' or ASP.NET/MVCs' behaviour?
Maybe I need sliding expiration to be set to "true"?
Or maybe in my renew method I should re-login the user and put a new cookie in the response?
Thank you!

FormsAuthentication expiration is really a matter of two parts:
the expiration of the authentication ticket
the expiration of the cookie containing the ticket
If you want to leave sliding expiration off, and renew the ticket manually, you need to renew the ticket and return a new authentication cookie to the browser.
The Response.Cookies array is empty unless you (or other code) add something to it. It's only meant for adding cookies that are new or whose contents/expiration/whatever have changed. An empty Response.Cookies only means that nothing has changed - the browser will keep the cookies it already has (until they expire) and still send them on the next request.
The standard way of modifying cookie contents or expiration is to take a cookie the browser sent (from Request.Cookies), modify it, and then add it to Response.Cookies.
Here's a bit of sample code for manually renewing the authentication cookie (disclamer: Test thoroughly and think):
// You could also get the ticket from
// Request.Cookies using FormsAuthentication.Decode
FormsIdentity identity = HttpContext.Current.User.Identity as FormsIdentity;
if (identity == null) return; // User isn't authenticated
// Renew the ticket - you could also create a new ticket manually
// (see * below for an example), if you want to get rid of ASP.NET's
// rather confusing renew-if-old policy:
FormsAuthenticationTicket ticket =
FormsAuthentication.RenewTicketIfOld(identity.Ticket);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
encryptedTicket
);
// Better keep this (see * below):
cookie.Secure = FormsAuthentication.RequireSSL;
cookie.HttpOnly = true;
// Isn't a security issue if this is set too long - the ticket contained
// within will still expire after the set time, and the server will timeout
// the auth session on the next request.
// But let's just keep cookie and ticket in sync:
cookie.Expire = ticket.Expiration;
// Add cookie to response to send the changes to the browser:
HttpContext.Current.Response.Cookies.Add(cookie);
Note that FormsAuthentication.RenewTicketIfOld() won't always renew the ticket. It will only renew if less than half of the expiration time is left. I.e., if your timeout in web.config is set to 20 minutes and RenewTicketIfOld is called 7 minutes after the ticket was created, the ticket won't be renewed, and there'll still be 13 minutes left. If it's called after e.g. 12 minutes, it will be renewed to 20 minutes.
The reason for this is because RenewTicketIfOld is used by slidingExpiration on every request and so would send back a new cookie on every request (to reset the expiration to [timeout] minutes). Only sending a new ticket cookie back when at least half the time has elapsed gets rid of a lot of cookie overhead - at the expense of being confusing to developers and end users.
*) On cookie.Secure, see Hanselman: Weird Timeouts - this simply makes sure that if RequireSSL is set in web.config, the cookie will honor that, which avoids many a debugging nightmare if you ever move the site to SSL.

Related

Dynamically set session cookie max age

I'm using Jetty's session management and want to implement a simple login with a 'Remember me' option.
So if the user doesn't want to be remembered, I want the JSESSIONID cookie to live until the browser session is closed. If the user opts-in to be remembered, the cookie will expire within 30 days.
I'm using SessionCookieConfig to configure the cookie details on startup and I can't change that per request.
So is there a way to dynamically change the max age per login request?
The only way I can see is to get the cookie from the request and then change the max age:
//in LoginServlet
doPost(HttpServletRequest request, HttpServletResponse response) {
//... Get remember me option from request
request.getCookies();
//... Find cookie in array by name JSESSIONID
if (rememberMe) {
sessionCookie.setMaxAge(60 * 60 * 24 * 30);
} else {
sessionCookie.setMaxAge(-1);
}
}
However I want to refrain as much as possible from dealing with the session and leave it to the container.
Is there another option?
The jsessionid cookie is handled by the container and so I wouldn't recommend that you try and repurpose it. Instead, there's a wealth of info on stackoverflow on how to implement a "remember me" function: try here.

how to delete a value from session with revel

Is there a way to delete the value from session witch revel the go web framework?
I have a function for validate captcha for user input, and I set the value of captcha in session, and delete the captcha from session if there nothing to do for client after 1 minute. The code is like:
time.AfterFunc(time.Minute, func() {
delete(this.Session, CSecurityCode)
})
But I can still get the old value of captcha , why, and how to fix this?
Anybody who can help me?
The Session value is valid only while processing a client request. i.e. between the time you get the request and the time you respond to that request. Its contents are kept in a cookie on the client side and you'll get a new Session every time the client connects to your server. Thus if you keep it for later use (like the name of your AfterFunc suggests, triggered by a timer?), anything you do with it will be lost on the next client connection.
In order to achieve what you want to do, you'll need to add a "lastSeen" timestamp to the Session. When a request comes in, check Session["lastSeen"], and if it's older than 1 minute, then you can discard CSecurityCode from it.

How to set expiration time to session in the controller?

I need to set a session with expiration time of 5min in controller. How do i do it?
I need something like:
$this->container->get('session')->set('mysession', 'value', 'expiration');
in symfony2 way?
Thanks!
Assuming your session is already created, you can achive your goal with:
$this->container->get('session')->migrate($destroy = false, $lifetime = null);
$destroy: Whether to delete the old session or leave it to garbage collection.
$lifetime: Sets the cookie lifetime for the session cookie. A null value will leave the system settings unchanged, 0 sets the cookie to expire with browser session. Time is in seconds, and is not a Unix timestamp.
This feature is added recently. You can update to this commit or patch. From the code it seems you can set expiry time by following way,
$this->container->get('session')->getMetadataBag()->stampNew(300);
To control the time of the active session (and idle time too) you have to do it in the controller this way (extract from: session configuration in the official doc):
$session->start();
if (time() - $session->getMetadataBag()->getCreated() > $maxTime) {
$session->invalidate();
throw new SessionExpired(); // redirect to expired session page
}
When time reaches your $maxTime session is "closed". You can put this code in the backend of your app as a function to call from the different methods to control the time.

Change form hash (token) expiration Zend Framework

I am using ZF's Zend_Form_Element_Hash to protect my form against CSRF.
The problem however is that the token generated expires too soon. I'm guessing the problem is with the session lifetime, because that is where it is stored.
I use this code to generate it:
$token = new Zend_Form_Element_Hash('tk');
$token->setSalt(md5(uniqid(mt_rand(), TRUE)));
Is there any way I can make the token valid for a longer period of time?
Am I doing it right or there is a better way? I am new to Zend Framework.
There is also a timeout property within Zend_Form_Element_Hash that serves as a TTL for the CSRF token. By default it is 300 seconds (5 minutes).
You can increase this timeout by passing a value for timeout as an option.
$token = new Zend_Form_Element_Hash('tk', array('timeout' => 900)); // 15 minute TTL
Zend_Form_Element_Hash API Doc

How do we do authentications in web applications?

Sorry, I wrote a lot to explain my situation, If you don't have time or not in mood to read all these just jump to the questions. Even answering one of them helps my situation, thanks :D
I'm trying to write a web application in node.js, but since I'm too new to web, I don't know how to write the web login system. I don't want to use basic or digest http authentications, I want it like normal login systems with http forms and different pages shows different content for different types of users. I searched a bit, I know the basics, but they're not enough.
This is what I got:
We check the user and pass from the
POST data in the database
If correct we give the client a new session, and save it in a database.
The client saves the session as a cookie and sends it in each page request.
The server checks the session and gives the content intended for the user.
Here's the part I don't know:
How do we generate a session?
How do we send it to the client?
How is it saved in cookies?
When is it supposed to expire?
What happens if it is expired? What
should we do?
Is there anything else that I should
know?
If you can please, give me some examples in node.
Thank you in advance :D
A session is simply a unique key (session ID) associated with an object/array, this way you can connect data to a user of your site.
You send the session ID to the client as a cookie, once sent, the client sends its session ID to your server with every HTTP request.
You send the HTTP Set-Cookie header (Set-Cookie: sessionid=abcdefg38974).
You can make it expire when you want it to, when the browser closes or after for example a year (this would keep you logged in for a year, after which you'll have to login again).
When a cookie expires it is simply thrown away, on the serverside it will just look like the user doesn't have a session ID set yet so he has to log in again.
You should know of things like session hijacking (stealing someone else's session ID). Have a look at it.
Little example, it might increate the visit number twice each time you request because your browser also requests /favicon.ico. Keep in mind that this example is not very safe as session hijacking is possible, this also keeps all sessions in memory and forgets them when the server is restarted. It would be wise to save sessions to a database.
var http = require('http');
var sessions = {};
http.createServer(function (req, res) {
var ssid;
var session;
if (req.headers.cookie) {
// Cookie already set, read it
var parts = req.headers.cookie.split('=');
ssid = parts[1];
// Is the session id known to us?
if (typeof(sessions[ssid]) != "undefined") {
session = sessions[ssid];
console.log('Loaded session with id ' + ssid);
}
}
if (typeof(session) == "undefined") {
// No cookie set, make one
ssid = Math.random();
session = {
'visitNumber': 0
}
console.log('Created session with id ' + ssid);
}
session.visitNumber++;
// Respond to the browser
res.writeHead(200, {
'Content-Type': 'text/plain',
'Set-Cookie': 'ssid=' + ssid
});
res.end('Visit number: ' + session.visitNumber + '\n');
// Save the changes we have made to the session data
sessions[ssid] = session;
}).listen(8080);

Resources