Click here to Skip to main content
Click here to Skip to main content

Cookieless ASP.NET forms authentication

By , 25 Aug 2002
 

Cookieless forms authentication

Why, when?

They say, its not possible. Well it is, and relatively easy to accomplish!

Lot of companies and people want to exclude cookie usage from their lives. Partly because its said to be insecure, partly because they see no reason to use it.

In my case, it was mandatory not to use cookies, but make a forms login page. Of course I've started with the normal forms authentication, cause I believed, that the big brother couldn't make such a mistake, to use cookies.

They did. After searching all the forums how to skip cookie usage, all I've found was this:

The hard way

If you pass the encoded cookie as a GET parameter to the Response.Redirect() function, the system will work as normal: the user will be signed in until the parser can find the cookie as a GET parameter, or a cookie is not easy, and makes no sense at all.

The code snippet to accomplish the "get" way of cookieless authentication is:

FormsAuthenticationTicket tkt;
string cookiestr;
HttpCookie ck;

//create a valid ticket for forms authentication
tkt = new FormsAuthenticationTicket(1, userName, DateTime.Now,
DateTime.Now.AddMinutes(30), false, "your custom data");<BR>

//get the string representation of the ticket
cookiestr = FormsAuthentication.Encrypt(tkt);

//redirect to the return URL using the cookie in the address field
//In the web.config, we called out auth. ASPXFORMSAUTH2, so set that value
string strRedirect = Request["ReturnUrl"] + "?.ASPXFORMSAUTH2=" + cookiestr;
Response.Redirect(strRedirect, true);

This is useless, I tell you. Completely unpleasant, and insecure (you have to change all the links, which of course you won't)

And here is the way, you can do it:

The configuration

No authentication tag needed beside the "none". The next line in the web.config will tell the framework not to store the session ID in a cookie, but add as a special directory to the address field.

<sessionState cookieless="true" timeout="20" />

After adding this line, the address field will always look like:

http://localhost/samplecookieless/(lvymatawljpjtl55d4awjg55)/login.aspx

As you can see, on each request, the session ID is passed as a directory. Very smart solution from MS! When you want to create a link with get parameters to another page, you have to pay attention to it, since calling an aspx without the session ID in the address will create a new session. So, to create a link, that has GET parameters, do this:

string url =
string.Format(
// we build the whole link. Firstly, we get our host name
 "http://" + Request.Headers["Host"] + "/" + 
// then the path of the request, and append the session ID, as shown above
 Request.ApplicationPath + 
 "/(" + Session.SessionID + 
// simply add the target page with the HTTP-GET parameters.
 ")/Main.aspx?{0}={1}&{2}={3}",
 "State", state.ToString(),
 "Lang", langID.ToString()
);

(OK, I needed it. Usually people don't care about GET parameters, so probably you won't need it.)

The coding part

In global.asax.cs, add:

private void InitializeComponent()
{  // This tells the global to catch all session initialization events,
   // So before every page load, we will have the Global_Acq. called! Good starting!
   this.AcquireRequestState += new
   System.EventHandler(this.Global_AcquireRequestState);
}
private
void Global_AcquireRequestState(object sender, System.EventArgs e)
{ 
	//This tells the global to check whether code "Name-John" is in the session 
	//variable, called "Authenticated". To say it simple, 
	//checks, whether someone set this 
	//variable.
	if((string)Session["Authenticated"] != "Name-John")
	// If yes, do nothing, so the requested page will load.
		{
		// If it's not set yet, redirect to the login page, 
		// if the caller is not the login page already. If it is, we don't 
		//want loops, so let is load
		if(!Request.Path.EndsWith("login.aspx"))
		{
			Response.Redirect("login.aspx");
			Response.End();
		}
	}
}

If the user entered valid codes (check them however you like), in login.apsx.cs, set the session variable Authenticated to code Name-John, so the global will let the users download pages.

Session["Authenticated"] = "Name-John";
//the auth is successfull, so send the user to the page
Response.Redirect("default.aspx", true);

As you see, this is a pure redirect function. No ASP.NET forms authentication is used. On the default.aspx, place whatever you want. Those controls will be in safety. If you want to sign out the user, call this code:

//signs out
Session.Abandon();
//redirects to itself. This will redirect to login.aspx, cos we are signed out
Response.Redirect(Request.Path,true);

Misc good to knows

After clicking the sign-out, the user will be back on login.aspx. If he presses back, he can see the page from his browser's cache, but cannot click anything. It could be wise to set the cache expiration.

If you press [Back], then [Refresh], the explorer will asks for "The page cannot be refreshed without resending the information", and prompts for "Retry/Cancel".

Usually, when someone presses retry, the password is sent again, and the user is signed in again. Well, not in our case

You can try, that this method really doesn't use cookies: in Internet Explorer, go Tools / Internet Options. Go Privacy, and block all cookies, then try to sign in'n'out.

If you have any questions/comments, please send it to me!

Sincerely, Adam

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

brutal
Hungary Hungary
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerRe: URGENT : Cookies-Transfer frm one application to anothermemberstixoffire1 Apr '08 - 23:15 
Take a look at this article - hope it helps.
 
http://www.codeproject.com/KB/web-security/aspnetsinglesignon.aspx[^]
 

Questioncookieless at runtimememberAlexandru Stanciu26 Mar '07 - 5:00 
any idea about setting this cookieless thing at runtime? i'd like to serve the response with or without the sessionid embedded in the url based on the browser capability to store cookies.
AnswerRe: cookieless at runtimememberchestnutt27 Mar '07 - 5:09 
Actually, the default settings in ASP.NET will use cookies if the browser supports it, and go cookieless if it doesn't.
 

GeneralRe: cookieless at runtimememberFernando L Rodriguez, MCP2 Jul '08 - 8:14 
as long as forms authentication is properly implemented
 
Fernando L Rodriguez, MCPD

Generalpage Refreashmembers70284028 Jan '06 - 0:58 
page Refreash in asp.net after few minute on the basis on user code
Questionpossibe security problem?memberlandonjb4 Nov '05 - 12:06 
Possible security problem with this code. The problem is when you check to see if the current page is the login.aspx page. Say you have a page secure.aspx at www.website.com/secure.aspx and when a user goes to this page you check with this code. The user should be redirected if not logged in, however what if a user does this
www.website.com/secure.aspx?login.aspx would they pass threw? the code thinks that the page is the login.aspx page and lets the secure.aspx page load. I am I wrong?

AnswerRe: possibe security problem?memberstixoffire1 Apr '08 - 23:12 
You have the login.aspx as part of the request string - the path is not the same thing.
If you were to run a small sample of code from that to get request path and the request string - you would see that the path request is strictly the path and the request is everything after the ?
Generaltrace.axdsussThijs Cobben19 Oct '04 - 5:00 
Great article, however, trace.axd is bugged now, complaining Sessions are not valid in this context (in Global.Acq ), which is a pity.
 
Anyone think of a good workaround?
 
We thought of putting e.g. a check in glob.acq (if not EndsWith(axd) or sthg) but looks a bit ugly.
QuestionWhat about webfarmssussAnonymous9 Dec '03 - 13:23 
Would this method work with web farms?
AnswerRe: What about webfarmsmembertoen_work19 Jan '04 - 0:41 
I believe it would. Just make sure you abandon InProc session state handling for ServerState or SQLState.
GeneralCookies and SessionssussAnonymous27 Oct '03 - 6:57 
Well a session is a cookie in reality for the book. The server hands the sessionID around but the difference is the way the cookie works. If there is no path information, it is assumed to be a state cookie and never writes the cookie to the disk. The browser actaully might not even send that or display it as a cookie however its in the headers as a cookie with no expiration or path.
 
There are bigger issues with this type of state management with sessions. as they can not be correctly handled in a load balanced manner. The will fail unless you set your servers to communicate session state. With high load servers this extra networking traffic is not a good idea.
 
Beleive it or not Cookies w/paths and expirations are mostlikely the best method to handle large scale sites without placing more load on the server to place more information on the server.
 
A session actaully sends the session ID around but the server is responible for maintaining the information in the session which now increases your memory usage.
 
I would take another look at the development docs if I were you.
Generalweb.config inn subdirectorymemberMajid Shahabfar26 Oct '03 - 23:57 
Hi dear,
I have a main ASP.NET project in my wwwroot directory in web server.
now I want to create second ASP.NET project in a subdirectory for example wwwroot\subdir\
and also I want to add form based authentication to the second project. as you know I must do
appropriate changes in web.config files and place it in wwwroot\subdir\ directory because I don't
want change my main project web.config file. but when I place web.config file with authentication
in wwwroot\subdir\ directory my second web application doesn't work properly.

\wwwroot\
main web application
main web.config file
\wwwroot\subdir\
second web application
second web.config file

 
now how can I do this job that my two web.config files don't have conflict with each other?
Thank you in advance.

Generalweb.configsussAnonymous23 Oct '03 - 7:52 
first of all thanks for sharing your code with us...
 
I guess your method don't use the settings in web.config file, even further you need to set the authentication mode to "None" instead of "Forms", is this true ? Confused | :confused:
 
Does the hard method (adding the cookie in the query string) use the settings (like loginUrl, deny users, ...) in the web.config file ? Confused | :confused:
 
thanks,
Rolando

QuestionCookieless not cookieless?sussbhbattaglin25 Aug '03 - 23:42 
I have tried using the web.config file below (which is placed in the initial webroot directory of my website) to create a cookieless session.
 
Unfortunely even the first page (which uses no "session" variables, seems to require session cookies! Could someone tell me what I am doing wrong? Thanks!
 
Here is my web.config file:
 

 





GeneralStill a lot of thinking on session.memberwyx20007 Jun '03 - 11:06 
Smile | :) A good article!
 
I used to create sessionid in my SQL Server, and then encrypted it and put it in cookie or pass it as a url parameter. It worked fine.
Confused | :confused:
But now I try to make my software work more close with .NET, so I read a lot of articles about .NET session, but I still have no clear idea how to use it, here is my several questions, hope someone can point out a way for me.
 
1, Microsoft provide three ways to maintain session data, inproc,session server and sql server, but in my case, I have my own session table, I only need a sessionid, I want to use the asp.net sessionid, the 120bit one, I think in this case, there is no worry about load-balance, inproc is fine to maintain the sessionid when there are several webserver hooked by load-balance, is it true?
 
2, We want to support users without cookie, so there is a cookieless setting, but it is a setting in web.config, I think most time we will just check if the client side support cookie and then decide we use cookie way or cookieless way, how can we dynamically do that?
 
3, Suppose I use cookieless, the sessionid will be in the url, I think it is hard to find out what sessionid are currently activated, and it is quite safe just as some people said. But what I should do in this case, I am logged in and browse a site and then I want to share someone with one image on the site, so I just send the image link to the one, and he can see the image, in the same time, he can just take over my session since he get the sessionid from the link I send out. I just think this happens a lot, what is your suggesion to deal with it?

GeneralRe: Still a lot of thinking on session.memberUUmapathi24 Mar '05 - 4:49 
wyx2000 wrote:
I am logged in and browse a site and then I want to share someone with one image on the site, so I just send the image link to the one, and he can see the image, in the same time, he can just take over my session since he get the sessionid from the link I send out. I just think this happens a lot, what is your suggesion to deal with it?
 

Here's the solution for the above security issue:
 
Instead of the following code in your Global_AcquireRequestState ..........
 
if((string)Session["Authenticated"] != "Name-John")
{
if(!Request.Path.EndsWith("login.aspx"))
{
Response.Redirect("login.aspx");
Response.End();
}
}
 
try using the following:
 
if(!Session["IsAuthenticated"].Equals(true))
{
if(!Request.Path.EndsWith("login.aspx"))
{
Response.Redirect("login.aspx");
Response.End();
}
}
else if(!Session["ClientIP"].Equals(Request.UserHostAddress))
{
if(!Request.Path.EndsWith("InvalidSessionState.aspx"))
{
Response.Redirect("InvalidSessionState.aspx");
Response.End();
}
}
 
Worked for me!!!
 
UMAPATHI UTTHAMARAJ,
System Analyst,
Peakpoint Technologies, Inc.
MA USA.
GeneralSession problemsmemberAgyklon30 May '03 - 1:48 
Hi!
 
Can you solve this problem?:
 
Do not loose SessionVariables when switching webapplications?
(I have a "FRAME" webapplication, which makes the authentication, menu,
and so on.
I wish to have more modules. These modules are optionally and i wont install all of them.
(possible way 1?)
I have my own SessionHandler wrapper, which can convert Requests into SessionVariables if it is neccessary. But, it seems to be a strange way. (not recommented, i think)
 
Problem:
i have more frames on clientside.
When i choose from menu (msiewebcontrols.TreeCtrl), i loose Session variables.
I fill up my menu from xml.(possible way?) so it is hard to encode runtime the xml.
 
so:
what about the same SessionHandleing in different webapplications?OMG | :OMG:
 


 
Agyklon
GeneralThe same thing in VBmemberdavegrr21 May '03 - 18:21 
Dont know what the feeling is here about VB, but I'm stuck with it for the moment.
 
Anyway, AcquireRequestState doesn't exist in VB.
So, I create a little CS project, with code which accepts the (VB) HttpApplication and EventHandler and adds it as per your code.
 
Seems to work perfectly, not much testing yet.
 
You'd think you shoud be able to do it directly in VB!
Am I missing something obvious?
 

 
Just to say thanks, in case you still look at this.
GeneralRe: The same thing in VBsussPaul Bentley12 Aug '03 - 22:31 
Private Sub Global_AcquireRequestState(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.AcquireRequestState
'Your Code Here
End Sub
GeneralHttpContext.Current.User disapears with your methodmemberxwing2k121 Apr '03 - 19:21 
I implemented my security along your guidlines, setting the security mode to none. I'm trying to use HttpContext.Current.User to store a GenericPrincipal object so that I can store a user's name and roles. I can store the object, but when I call Response.Redirect, the object vanishes (HttpContext.Current.User's name and roles become empty). The session is not being abandoned during the page navigation. Why is this happening? If HttpContext.Current.User does not work with "None" authentication, can you tell me where to find an article on cookieless forms authentication?
GeneralRe: HttpContext.Current.User disapears with your methodsussVinay Chopra26 Apr '04 - 13:12 
http://www.codeproject.com/aspnet/cookieless.asp#xx479923xx
GeneralThey say, its not possible. Well it is, and relatively easy to accomplish!memberSchoenholzer27 Mar '03 - 6:08 
How says it? MS self has examples to doing it without cookies. Cool | :cool:
GeneralRe: They say, its not possible. Well it is, and relatively easy to accomplish!membermstachura16 Jun '03 - 21:45 
Hi,
 
could you give some link to these examples?
 
Thanks a lot.
Maras
 
P.S. Good article
GeneralRe: They say, its not possible. Well it is, and relatively easy to accomplish!memberSchoenholzer3 Jul '03 - 3:39 

The problem is that you need to be sure that for every request a parameter will be added to the url. This parameter is a encrypted cookie. And for every request you need to validate the cookie. It's a lot of work.Frown | :(
 
More or less during login you do the following:
 
if (customAuthenticate(tbName.Text, tbPwd.Text))
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(tbName.Text,false,20);
string strEncrypted = FormsAuthentication.Encrypt(ticket);
string strURL = FormsAuthentication.GetRedirectUrl(tbName.Text,false);
if (strURL.IndexOf("?") == -1)
{
strURL += "?" + FormsAuthentication.FormsCookieName + "=" + strEncrypted;
}
else
{
strURL += "&" + FormsAuthentication.FormsCookieName + "=" + strEncrypted;
}
}
Response.Redirect(strURL);
 
More you can find here:
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemwebsecurityformsauthenticationticketclasstopic.asp
 
http://www.dotnethell.it/articles/article.aspx?ArticleID=56 (italian)
 

GeneralEasy WaymemberSefai Tandoğan26 Mar '03 - 23:09 
Try this in every pages Page_Load:
 
Response.Cache.SetCacheability(HttpCacheability.NoCache);

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 26 Aug 2002
Article Copyright 2002 by brutal
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid