Deserialize viewstate string after Page.ViewStateUserKey is set - asp.net

I am using the auto-generated code for preventing cross site forgery attacks with asp.net web applications - ie:
protected const string AntiXsrfTokenKey = "__AntiXsrfToken";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
When using an Ajax/Webmethod request, I would also like to validate the request before altering the database, by posting back the value of the _VIEWSTATE hidden input.
However, when I try
internal static void Validate(string encodedViewstate)
{
var request = HttpContext.Current.Request;
var requestCookie = request.Cookies[AntiXsrfTokenKey];
var antiXsrfTokenValue = requestCookie.Value;
var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
var xsrfData = los.Deserialize(encodedViewstate);
the los.Deserialize method fails with:
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm
ie the UserKey alone is not the correct key for the encoded viewstate string.
Can anyone please help in how to deserialize the viewstate, encoded after setting the ViewStateUserKey property (ie some combination of the MAC and UserKey). Thanks for your thoughts/expertise.

You'll need to use the same PageStatePersister instance that the Page itself uses. Otherwise this check won't work reliably. For example, consider this instance method in your Page's code-behind:
private void CheckCsrfToken() {
var persister = this.PageStatePersister;
persister.Load();
if (persister.ViewState == null) {
throw new Exception("Validation failed.");
}
}
As long as Page.ViewStateUserKey is already set, the returned persister instance will have its modifier also set appropriately.

Related

preventing cross-site request forgery (csrf) attacks in asp.net web forms

I have created an ASP.Net Web Forms application using Visual Studio 2013 and I am using .NET Framework 4.5. I want to make sure my site is secure from Cross-Site Request Forgery (CSRF), I have found many articles talking about how this feature is implemented on MVC apps, but very few talking about Web Forms. On this StackOverflow question one comment states that
"This is an old question, but the latest Visual Studio 2012 ASP.NET
template for web forms includes anti-CSRF code baked into the master
page. If you don't have the templates, here's the code it
generates:..."
My master page does not contain the code mentioned in that answer. Is it really included in new applications? If not, what is the best way to add it?
You could try the following. In the Web-Form add:
<%= System.Web.Helpers.AntiForgery.GetHtml() %>
This will add a hidden field and a cookie. So if you fill out some form data and post it back to the server you need a simple check:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
AntiForgery.Validate(); // throws an exception if anti XSFR check fails.
}
AntiForgery.Validate(); throws an exception if anti XSFR check fails.
ViewStateUserKey & Double Submit Cookie
Starting with Visual Studio 2012, Microsoft added built-in CSRF protection to new web forms application projects. To utilize this code, add a new ASP .NET Web Forms Application to your solution and view the Site.Master code behind page. This solution will apply CSRF protection to all content pages that inherit from the Site.Master page.
The following requirements must be met for this solution to work:
All web forms making data modifications must use the Site.Master page.
All requests making data modifications must use the ViewState.
The web site must be free from all Cross-Site Scripting (XSS) vulnerabilities. See how to fix Cross-Site Scripting (XSS) using Microsoft .Net Web Protection Library for details.
public partial class SiteMaster : MasterPage
{
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
//First, check for the existence of the Anti-XSS cookie
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
//If the CSRF cookie is found, parse the token from the cookie.
//Then, set the global page variable and view state user
//key. The global variable will be used to validate that it matches
//in the view state form field in the Page.PreLoad method.
if (requestCookie != null
&& Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
//Set the global token variable so the cookie value can be
//validated against the value in the view state form field in
//the Page.PreLoad method.
_antiXsrfTokenValue = requestCookie.Value;
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
//If the CSRF cookie is not found, then this is a new session.
else
{
//Generate a new Anti-XSRF token
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
//Create the non-persistent CSRF cookie
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
//Set the HttpOnly property to prevent the cookie from
//being accessed by client side script
HttpOnly = true,
//Add the Anti-XSRF token to the cookie value
Value = _antiXsrfTokenValue
};
//If we are using SSL, the cookie should be set to secure to
//prevent it from being sent over HTTP connections
if (FormsAuthentication.RequireSSL &&
Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
//Add the CSRF cookie to the response
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
//During the initial page load, add the Anti-XSRF token and user
//name to the ViewState
if (!IsPostBack)
{
//Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
//If a user name is assigned, set the user name
ViewState[AntiXsrfUserNameKey] =
Context.User.Identity.Name ?? String.Empty;
}
//During all subsequent post backs to the page, the token value from
//the cookie should be validated against the token in the view state
//form field. Additionally user name should be compared to the
//authenticated users name
else
{
//Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] !=
(Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of " +
"Anti-XSRF token failed.");
}
}
}
}
Source
When you create a new 'Web Form Application' project in VS 2013, the site.master.cs will automatically include the XSRF/CSRF code in the Page_Init section of the class. If you still dont get the generated code, you can manually Copy + Paste the code. If you are using C#, then use the below:-
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
}
}
You could use below piece of code, which will check the request where it is coming from
if ((context.Request.UrlReferrer == null || context.Request.Url.Host != context.Request.UrlReferrer.Host))
{
context.Response.Redirect("~/error.aspx", false);
}
It works great for me!!!

protecting against CSRF in asp.net web application when using ajax

I have an asp web application I wanted to update to prevent cross site request forgery attacks.
I have used the Microsoft auto-generated code from VS 2012, and added it to the master page as described here. It is working well, but one page posts JSON via an AJAX request to a webmethod
I would like to check this ajax request as well.
The forseeable problems are:
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
//Set the HttpOnly property to prevent the cookie from
//being accessed by client side script
HttpOnly = true,
this can obviously be changed, but this would then seem to increase site vulnerability. Is this a significant issue?
I can send the value of the viewstate hidden input with the ajax request, but this will then need to be decoded back into key value pairs to do the equivalent of:
(string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
Is there an easy way to use existing asp.net methods to do this?
Thank you for any help.
Here is what i have discovered. I ended up using the LosFormatter, as described by geedubb, by adding the following code to the MasterPage, and assigning the value to a hidden input which is posted back with the ajax request. I did not realise when I posted the question that HttpCookie.HttpOnly property still posts back the cookie on an ajax request, and so can be left set to false.
internal string GetToken()
{
// call the static method to guarantee LosFormatter remains threadsafe
return GetToken(_antiXsrfTokenValue);
}
private static string GetCurrentUserName()
{
var currentUser = HttpContext.Current.User.Identity;
return (currentUser == null) ? string.Empty : currentUser.Name;
}
private static string GetToken(string token)
{
var los = new System.Web.UI.LosFormatter(true, token);
var writer = new System.IO.StringWriter();
var data = new Dictionary<string,string>();
data.Add("TokenValue",token);
data.Add("UserNameKey", GetCurrentUserName());
los.Serialize(writer, data);
return writer.ToString();
}
internal static void Validate(string token)
{
var request = HttpContext.Current.Request;
var requestCookie = request.Cookies[AntiXsrfTokenKey];
var antiXsrfTokenValue = requestCookie.Value;
var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
var xsrfData = (Dictionary<string,string>)los.Deserialize(token);
if (xsrfData["TokenValue"] != antiXsrfTokenValue || xsrfData["UserNameKey"] != GetCurrentUserName())
{
throw new System.Security.Authentication.AuthenticationException("Validation of Anti-XSRF token failed.");
}
}
Initially, I had tried sending the value of the _VIEWSTATE hidden input, using the same code
var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
var ajaxViewState = los.Deserialize(token)
but this threw an error stating the supplied key could not deserialze the string. obviously setting
Page.ViewStateUserKey = _antiXsrfTokenValue;
has a more complex key than the supplied key alone. I would be interested if anyone knew how to deserialize a viewstate string with a userKey.
The only problem with the method I have provided is the size of the string posted back - 1976 characters long for a GUID + 6 character username!!!!
If approaching this problem again, I would reference the System.Web.WebPages.dll (used in an mvc project), and use the same methods which create the Html.AntiForgeryToken in MVC
namespace System.Web.Helpers
{
/// <summary>
/// Provides access to the anti-forgery system, which provides protection against
/// Cross-site Request Forgery (XSRF, also called CSRF) attacks.
/// </summary>
public static class AntiForgery
{
public static void GetTokens(string oldCookieToken, out string newCookieToken, out string formToken)
public static void Validate()

Re-inventing my authentication strategy with ASP.NET

Currently, I use custom written authentication code for my site, which is built on .NET. I didn't take the standard Forms Auth route, as all the examples I could find were tightly integrated with WebForms, which I do not use. For all intents and purposes, I have all static HTML, and any logic is done through Javascript and web service calls. Things like logging in, logging off, and creating a new account are done without even leaving the page.
Here's how it works now: In the database, I have a User ID, a Security ID, and a Session ID. All three are UUIDs, and the first two never change. Each time the user logs on, I check the user table for a row that matches that username and hashed password, and I update the Session ID to a new UUID. I then create a cookie that's a serialized representation of all three UUIDs. In any secure web service calls, I deserialize that cookie that make sure there's a row in the users table with those 3 UUIDs. It's a fairly simple system and works well, however I don't really like the fact that a user can only be logged on with one client at a time. It's going to cause issues when I create mobile and tablet apps, and already creates issues if they have multiple computers or web browsers. For this reason, I'm thinking about throwing away this system and going with something new. Since I wrote it years ago, I figure there might be something much more recommended.
I've been reading up on the FormsAuthentication class in the .NET Framework, which handles auth cookies, and runs as an HttpModule to validate each request. I'm wondering if I can take advantage of this in my new design.
It looks like cookies are stateless, and sessions don't have to be tracked within the database. This is done through the fact that cookies are encrypted with a private key on the server, that can also be shared across a cluster of web servers. If I do something like:
FormsAuthentication.SetAuthCookie("Bob", true);
Then in later requests, I can be assured that Bob is indeed a valid user as a cookie would be very difficult if not impossible to forge.
Would I be wise to use the FormsAuthentication class to replace my current authentication model with? Rather than have a Session ID column in the database, I'd rely on encrypted cookies to represent valid sessions.
Are there third party/open source .NET authentication frameworks that might work better for my architecture?
Will this authentication mechanism cause any grief with code running on mobile and tablet clients, such as an iPhone app or Windows 8 Surface app? I would assume this would work, as long as these apps could handle cookies. Thanks!
Since I didn't get any responses, I decided to take a shot at this myself. First, I found an open source project that implements session cookies in an algorithm agnostic way. I used this as a starting point to implement a similar handler.
One issue I had with the built in ASP.NET implementation, which is a similar restriction in the AppHarbor implementation, is sessions are only keyed by a string username. I wanted to be able to store arbitrary data to identify a user, such as their UUID in the database as well as their logon name. As much of my existing code assumes this data is available in the cookie, it would take a lot of refactoring if this data were no longer available. Plus, I like the idea of being able to store basic user information without having to hit the database.
Another issue with the AppHarbor project, as pointed out in the this open issue, is the encryption algorithm isn't verified. This is not exactly true, as AppHarbor is algorithm agnostic, however it was requested that the sample project should show how to use PBKDF2. For that reason, I decided to use this algorithm (implemented in the .NET Framework through the Rfc2898DeriveBytes class) in my code.
Here's what I was able to come up with. It's meant as a starting point for someone looking to implement their own session management, so feel free to use it for whatever purpose you see fit.
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Web;
namespace AuthTest
{
[Serializable]
public class AuthIdentity : IIdentity
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public AuthIdentity() { }
public AuthIdentity(Guid id, string name)
{
Id = id;
Name = name;
}
public string AuthenticationType
{
get { return "CookieAuth"; }
}
public bool IsAuthenticated
{
get { return Id != Guid.Empty; }
}
}
[Serializable]
public class AuthToken : IPrincipal
{
public IIdentity Identity { get; set; }
public bool IsInRole(string role)
{
return false;
}
}
public class AuthModule : IHttpModule
{
static string COOKIE_NAME = "AuthCookie";
//Note: Change these two keys to something else (VALIDATION_KEY is 72 bytes, ENCRYPTION_KEY is 64 bytes)
static string VALIDATION_KEY = #"MkMvk1JL/ghytaERtl6A25iTf/ABC2MgPsFlEbASJ5SX4DiqnDN3CjV7HXQI0GBOGyA8nHjSVaAJXNEqrKmOMg==";
static string ENCRYPTION_KEY = #"QQJYW8ditkzaUFppCJj+DcCTc/H9TpnSRQrLGBQkhy/jnYjqF8iR6do9NvI8PL8MmniFvdc21sTuKkw94jxID4cDYoqr7JDj";
static byte[] key;
static byte[] iv;
static byte[] valKey;
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.AuthenticateRequest += OnAuthenticateRequest;
context.EndRequest += OnEndRequest;
byte[] bytes = Convert.FromBase64String(ENCRYPTION_KEY); //72 bytes (8 for salt, 64 for key)
byte[] salt = bytes.Take(8).ToArray();
byte[] pw = bytes.Skip(8).ToArray();
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pw, salt, 1000);
key = k1.GetBytes(16);
iv = k1.GetBytes(8);
valKey = Convert.FromBase64String(VALIDATION_KEY); //64 byte validation key to prevent tampering
}
public static void SetCookie(AuthIdentity token, bool rememberMe = false)
{
//Base64 encode token
var formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, token);
byte[] buffer = stream.GetBuffer();
byte[] encryptedBytes = EncryptCookie(buffer);
string str = Convert.ToBase64String(encryptedBytes);
var cookie = new HttpCookie(COOKIE_NAME, str);
cookie.HttpOnly = true;
if (rememberMe)
{
cookie.Expires = DateTime.Today.AddDays(100);
}
HttpContext.Current.Response.Cookies.Add(cookie);
}
public static void Logout()
{
HttpContext.Current.Response.Cookies.Remove(COOKIE_NAME);
HttpContext.Current.Response.Cookies.Add(new HttpCookie(COOKIE_NAME, "")
{
Expires = DateTime.Today.AddDays(-1)
});
}
private static byte[] EncryptCookie(byte[] rawBytes)
{
TripleDES des = TripleDES.Create();
des.Key = key;
des.IV = iv;
MemoryStream encryptionStream = new MemoryStream();
CryptoStream encrypt = new CryptoStream(encryptionStream, des.CreateEncryptor(), CryptoStreamMode.Write);
encrypt.Write(rawBytes, 0, rawBytes.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] encBytes = encryptionStream.ToArray();
//Add validation hash (compute hash on unencrypted data)
HMACSHA256 hmac = new HMACSHA256(valKey);
byte[] hash = hmac.ComputeHash(rawBytes);
//Combine encrypted bytes and validation hash
byte[] ret = encBytes.Concat<byte>(hash).ToArray();
return ret;
}
private static byte[] DecryptCookie(byte[] encBytes)
{
TripleDES des = TripleDES.Create();
des.Key = key;
des.IV = iv;
HMACSHA256 hmac = new HMACSHA256(valKey);
int valSize = hmac.HashSize / 8;
int msgLength = encBytes.Length - valSize;
byte[] message = new byte[msgLength];
byte[] valBytes = new byte[valSize];
Buffer.BlockCopy(encBytes, 0, message, 0, msgLength);
Buffer.BlockCopy(encBytes, msgLength, valBytes, 0, valSize);
MemoryStream decryptionStreamBacking = new MemoryStream();
CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, des.CreateDecryptor(), CryptoStreamMode.Write);
decrypt.Write(message, 0, msgLength);
decrypt.Flush();
byte[] decMessage = decryptionStreamBacking.ToArray();
//Verify key matches
byte[] hash = hmac.ComputeHash(decMessage);
if (valBytes.SequenceEqual(hash))
{
return decMessage;
}
throw new SecurityException("Auth Cookie appears to have been tampered with!");
}
private void OnAuthenticateRequest(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
var cookie = context.Request.Cookies[COOKIE_NAME];
if (cookie != null && cookie.Value.Length > 0)
{
try
{
var formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
var bytes = Convert.FromBase64String(cookie.Value);
var decBytes = DecryptCookie(bytes);
stream.Write(decBytes, 0, decBytes.Length);
stream.Seek(0, SeekOrigin.Begin);
AuthIdentity auth = formatter.Deserialize(stream) as AuthIdentity;
AuthToken token = new AuthToken() { Identity = auth };
context.User = token;
//Renew the cookie for another 100 days (TODO: Should only renew if cookie was originally set to persist)
context.Response.Cookies[COOKIE_NAME].Value = cookie.Value;
context.Response.Cookies[COOKIE_NAME].Expires = DateTime.Today.AddDays(100);
}
catch { } //Ignore any errors with bad cookies
}
}
private void OnEndRequest(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
var response = context.Response;
if (response.Cookies.Keys.Cast<string>().Contains(COOKIE_NAME))
{
response.Cache.SetCacheability(HttpCacheability.NoCache, "Set-Cookie");
}
}
}
}
Also, be sure to include the following module in your web.config file:
<httpModules>
<add name="AuthModule" type="AuthTest.AuthModule" />
</httpModules>
In your code, you can lookup the currently logged on user with:
var id = HttpContext.Current.User.Identity as AuthIdentity;
And set the auth cookie like so:
AuthIdentity token = new AuthIdentity(Guid.NewGuid(), "Mike");
AuthModule.SetCookie(token, false);

ASP.NET private member field loses value on postback

Consider the following code:
public partial class TeacherControlPanel : System.Web.UI.Page
{
protected string username = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
username = (string)Request.QueryString["username"];
Ice_Web_Portal.BO.Teacher teacher = Ice_Web_Portal.BO.Teacher.GetTeacherByUsername(username);
if (teacher != null)
{
labUsername.Text = username;
labName.Text = teacher.TeacherName;
labTeacherCode.Text = teacher.TeacherCode;
Dept dept = teacher.Department;
if (dept != null)
{
labDepartment.Text = dept.DeptName;
}
}
else
{
//labErrorMessage.Text = "No teacher found";
}
}
protected void btnSendMail_Click(object sender, EventArgs e)
{
Response.Redirect(#"~/Teacher/TeacherComposeMail.aspx?username=mahabub" + username);
}
}
In this code, when I am declaring 'username' as private, it is initialized to null after subsequent post backs.
Why?
What is the secret?
Because ASP.NET is stateless meaning it does not keep it state from post back to postback. Save the user to the viewstate, session, or application to see it on postback to postback.
#region UserName
public string UserName
{
get
{
if (this.ViewState["UserName"] == null)
return string.Empty;
return (string)this.ViewState["UserName"];
}
set { this.ViewState["UserName"] = value; }
}
#endregion
Every time you do any postback, even for "simple" things like button click events, you're working with a new instance of the page class. That's ASP.Net 101.
Declaring the username field as private or protected has no bearing on this situation. The only bearing protected/private would have is the accessibility of the variable outside the class or in inherited members.
I believe this is likely a lifecycle problem.
When you navigate to this page for the first time, user name will only have a value if the query string was set for the request. So, "/TeacherControlPanel.aspx" will have a user name with no value, but "/TeacherControlPanel.aspx?username=SomeUserName". In these cases, the field username is only going to have a value if one is set. And if no querystring is set, then when the page processes the button click event, the load will fire, no query string set means that username will be null, which means that the click event will have nothing to append to the redirect string.
So the question is, in your application, what navigation path are you using to get to TeacherControlPanel.aspx?

ASP.NET 2.0: Problem in Httpcontext.current.session.add()

Can anybody help me to find out solution of following problem.
In ASP.NET website: at Application_OnPostAuthenticate() event, whatever code i write is executed for every request. therefore due to this customidentity object, countryid and weatherid is called everytime for each request (call for database for value). It effect response time of page and unneccessary code execute.
void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
{
// Get a reference to the current User
IPrincipal objIPrincipal = HttpContext.Current.User;
// If we are dealing with an authenticated forms authentication request
if ((objIPrincipal.Identity.IsAuthenticated) && (objIPrincipal.Identity.AuthenticationType == "Forms"))
{
CustomPrincipal objCustomPrincipal = new CustomPrincipal();
objCustomPrincipal = objCustomPrincipal.GetCustomPrincipalObject(objIPrincipal.Identity.Name);
HttpContext.Current.User = objCustomPrincipal;
CustomIdentity ci = (CustomIdentity)objCustomPrincipal.Identity;
HttpContext.Current.Cache["CountryID"] = FatchMasterInfo.GetCountryID(ci.CultureId);
HttpContext.Current.Cache["WeatherLocationID"] = FatchMasterInfo.GetWeatherLocationId(ci.UserId);
Thread.CurrentPrincipal = objCustomPrincipal;
}
}
To solve this problem when i try tochange code as follows
HttpContext.Current.Session.Add("test", FatchMasterInfo.GetWeatherLocationId(ci.UserId);); in place of cache i found foolowing error
"Object refrence not set to the instance of object"
I don't know whether we can store session variable inside Application_OnPostAuthenticate() event or not?
You could try doing this a bit later in the request, such as in the PreRequestHandlerExecute event:
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
IPrincipal objIPrincipal = HttpContext.Current.User;
if ((objIPrincipal.Identity.IsAuthenticated) && (objIPrincipal.Identity.AuthenticationType == "Forms"))
{
HttpSessionState session = HttpContext.Current.Session;
CustomPrincipal objCustomPrincipal = new CustomPrincipal();
if (session[objIPrincipal.Identity.Name] == null)
{
// get data from database or wherever
objCustomPrincipal = objCustomPrincipal.GetCustomPrincipalObject(objIPrincipal.Identity.Name);
CustomIdentity ci = (CustomIdentity)objCustomPrincipal.Identity;
Object countryID = FatchMasterInfo.GetCountryID(ci.CultureId);
Object weatherLocationID = FatchMasterInfo.GetWeatherLocationId(ci.UserId);
// save in session (not cache as cache is application-wide, not per-user):
session.Add(objIPrincipal.Identity.Name, objCustomPrincipal);
session.Add(objIPrincipal.Identity.Name + "_CountryID", countryID);
session.Add(objIPrincipal.Identity.Name + "_WeatherLocationID", weatherLocationID);
}
else
{
// already have custom principal object in session
objCustomPrincipal = (CustomPrincipal)session[objIPrincipal.Identity.Name];
}
// set the custom principal object to context/thread
HttpContext.Current.User = objCustomPrincipal;
Thread.CurrentPrincipal = objCustomPrincipal;
}
}
You probably don't want to access the session in any event that happens in every request. Some requests don't even have session (for instance, a lot of web service calls, or calls to WebResource.axd that load static resources).
Before adding value to cache object, check if it already exists in the cache.
You might not have session state enabled. Does it work anywhere else (like in a web form's display)?
Look for a <sessionState> element under your system.web element in web.config make sure it's turned on (set it to InProc unless you have a web farm).

Resources