I had a Posting on a blog about Sessions AND Cookies. Here are details
Sessions
Sessions are More Secure
Sessions are on the server
Cookies
Cookies are On client side
Less Secure
Once it is disable on browser the difficult to use.
On the basis of above argument i used sessions in Login system to keep UserId,UserName & roleName
Now on the the basis of roleName i will decide either this is Admin to enter to administrator section or not.
I have used this Code in Model in MVC
public bool LoginMe()
{
Int64 Error;
//create db
Database db = DatabaseFactory.CreateDatabase("DBContext");
DbCommand dbCommand = db.GetStoredProcCommand("ValidateUser");
db.AddInParameter(dbCommand, "#Username", DbType.String, this.UserName);
db.AddInParameter(dbCommand, "#Password", DbType.String, EncryptPassword(this.Password));
db.AddOutParameter(dbCommand, "#Error", DbType.Int64, 10);
DataSet dsResult = db.ExecuteDataSet(dbCommand);
Error = Convert.ToInt64(db.GetParameterValue(dbCommand, "#Error"));
if (Error == 1100)
{
try
{
var query = (from o in dsResult.Tables[0].AsEnumerable()
select new AllUser
{
UserId = o.Field<int>("UserId"),
UserName = o.Field<string>("UserName"),
roleName = o.Field<string>("roleName"),
}).Single(); // this will raise an exception if there isn't just one record returned
Session["UserId"] = query.UserId;
Session["UserName"] = query.UserName;
Session["roleName"] = query.roleName;
return true;
}
catch {
// do nothing and let method return false as something has gone wrong.
// add logging here if you are using it to show there has been a problem
}
}
return false;
}
I used it in View like #Session["UserId"]
Now an expert comment on this like
If you aren't using https and securing the session cookie then this might make it easy to hack your site, although that's the same for any session based site (nearly all of them)
It might be nice to add some check so that if you remove a user's rights, the session variables are deleted the next time that user requests something from the server,
otherwise they could carry on using the site even though their account it banned.You'd have to decide if this is likely and then how you want to do this (using an authorization filter maybe.)
Above comments confused me.Can any body make it clear?What is the best way to keep these information?
Session state uses client tickets to identify the server-side session, it may be susceptible to session ID spoofing and injection attacks.
So, to hack session values one would require hacking the remote-server.
And yes, for highly secure application(such as online banking) use https.
http://msdn.microsoft.com/en-us/magazine/cc163730.aspx#S9
Secure sockets layer (SSL) should be used to prevent network-level sniffing of session IDs, authentication tickets, application cookies, and other request/response information.
Can session value be hacked?
Use HTTPS if you application handles sensitive information(credit-card number,account num,passwords).
Store the User object (model with userId,username,role) in the session than separate attributes
Set setHttpOnly attribute for SESSION_ID.
It might be costly to refresh the User object stored in session before invoking every operation to reflect the current rights stored in database.
Related
I've a oauth2 resource server which uses the JwtBearerMiddleware to validate the access tokens. Now I wan't that the access token is invalid if the security stamp has changed. As it looks like this middleware doesn't validate the security stamp by itself.
I've found the SecurityStampValidator class which only seems to validate cookie authentication.
Where and how do I have to validate the security stamp from my json web token?
My current way to do it is to register an eventhandler for the OnTokenValidated event when I register the JwtBearerMiddleware. In this eventhandler I simply query the database for the security claim and compare it with the one in the token. When the security stamp isn't the same I just set the Ticket and SecurityToken of the context to null and skip to the next middleware which eventually will throw an 401 http status code if authentication is required.
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
...
Events = new JwtBearerEvents
{
OnTokenValidated = async (ctx) =>
{
var securityStampClaim = ctx.Ticket.Principal.Claims.FirstOrDefault(claim => claim.Type == "AspNet.Identity.SecurityStamp");
var subjectClaim = ctx.Ticket.Principal.Claims.FirstOrDefault(claim => claim.Type == OpenIdConnectConstants.Claims.Subject);
if (securityStampClaim == null || subjectClaim == null)
return;
var user = await userStore.FindByIdAsync(subjectClaim.Value, ctx.HttpContext.RequestAborted);
if (user?.SecurityStamp == securityStampClaim.Value)
return;
ctx.SecurityToken = null;
ctx.Ticket = null;
ctx.SkipToNextMiddleware();
}
}
});
Is this how it should be done?
Is this how it should be done?
Technically, yes (you could even use SignInManager.ValidateSecurityStampAsync(principal) to simplify your code a bit).
That said, you should strongly consider avoiding storing the security stamps in your JWT tokens because they are not just "opaque" strings used to determine whether a token or a cookie should be considered as revoked, they are also used as the sole source of entropy by ASP.NET Core Identity to generate 2FA tokens: if you store them as-is in a JWT, they can be easily extracted by a malicious third-party client application and used to predict valid 2FA codes for the logged in user.
This is a known issue, but AFAIK, there's no plan to fix it: https://github.com/aspnet/Identity/issues/626.
If you want to store the security stamps in your access tokens, consider using OpenIddict's default (encrypted) format, which is exactly the same as the one used by ASP.NET Core for its encrypted authentication cookies.
I've been reading a lot about session fixation attacks and the most popular solutions I've come across are changing the SessionID when user logs in and creating an additional cookie using a GUID to verify the user "belongs" to the SessionID.
My question is this: Isn't it enough to just delete the SessionID cookie (ASP.NET_SessionID) to ensure a new SessionID is generated?
In MVC 5, when the user logs in an additional encrypted user claims cookies is created (AspNet.ApplicationCookie) which Identity uses to authenticate the user upon each request. The additional "GUID cookie" seems unnecessary.
I’m originally a .NET desktop application developer writing my first MVC app and the learning curve has been a bit steep… although refreshingly enjoyable.
Thanks for any help.
Let me try to explain the issue and the solution by using comparisons between desktop and web apps (both in .Net)
When you start your desktop app, the first thing the app shows is a login screen, after which your access to the UI is granted. Now, each time the app's exe is started, it writes the "RunID" to a text file and shows the login screen. The RunID is how the rest of your usage of the app is going to be tracked/correlated.
Assume for a second that the file was on C:\RunID.txt.
An attacker (hacker) can start the exe (without logging in) on Machine1 and copy the contents of C:\RunID.txt to Machine2. Now as soon as you log in on Machine1, the RunID token from Machine1 will also work on Machine2, this is called session fixation.
The ideal way to fix it is to ABANDON the pre-authentication token, and issue a NEW Post-Authentication token. So, you would get a new Token after authentication (or in your case, an additional GUID) which will NOT EXIST on Machine2 and hence provide a level of security in addition to the RunID random token (Session ID)
Let me know if you'd like further explaination, but that is why even in MVC, you should abandon the previous session and create a new session post-auth to avoid session fixation, as a compensating control, you can add a GUID cookie too correspond with the Session ID cookie.
You can do this to avoid that situation:
SessionIDManager Manager = new SessionIDManager();
string NewID = Manager.CreateSessionID(Context);
string OldID = Context.Session.SessionID;
bool redirected = false;
bool IsAdded = false;
Manager.SaveSessionID(Context, NewID, out redirected, out IsAdded);
Response.Write("Old SessionId Is : " + OldID);
if (IsAdded)
{
Response.Write("<br/> New Session ID Is : " + NewID);
}
else
{
Response.Write("<br/> Session Id did not saved : ");
}
Support link:
Link
I have an ASP.NET MVC application that consumes various operations of a Web API. It uses ACS for security and so users have to log on first with their Microsoft account before they can do anything.
One of these web API operations is getting the list of permissions for the currently logged on user. This call is done for every page request, as we need this information to correctly display, disable or hide UI elements. This works fine.
As permissions don't change often, I would like to cache them so that the call to the web API is only done the first time.
Normally session is the way to keep user-specific data in memory, but I want to remain stateless/sessionless.
Would it be technically OK to use the application cache, in which I store the permissions with a key that includes the user's unique identification? Are there any risks/disadvantages of doing it like this?
[I also would like to keep the option open to later replace it with (Azure) distributed caching later, if needed, but for now the solution should be a simple built in one which is free :)]
EDIT: the cache is meant to live as long as the user is working, so it's mostly short-term cache.
Application cache seems not to be not a good option. First of all, your application process may be restarted and then all the data will be lost. On other hand, if the application is running for a long time and you have a significant number of users, it will cause significant growth process of memory size.
I'd suggest you to use encrypted cookie. Upon successful login you set the cookie with his id / permission and upon logout remove it. This way you make user login really persistent and independent on session / server state and also free your server from unnecessary storage. Encryption protects against the possibility to abuse the cookie by its reverse engineering and receive another user's permissions.
See the sample code below:
// on login successful
string EncryptedUserId = EncriptCookie(UserId, Permissions);
HttpCookie LoginCookie = new HttpCookie("yoursitename");
LoginCookie.Values.Add("userinfo", EncryptedUserId);
LoginCookie.Expires = DateTime.Now.AddYears(10);
HttpContext.Current.Response.AppendCookie(LoginCookie);
public static void Logout()
{
HttpCookie LoginCookie = new HttpCookie("yoursitename");
LoginCookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.AppendCookie(LoginCookie);
}
private static string EncriptCookie(int UserId, string Permissions)
{
string CookieString = UserId.ToString() + "#" + Permissions);
DESCryptoServiceProvider Crypt = new DESCryptoServiceProvider();
Crypt.Key = ASCIIEncoding.ASCII.GetBytes("MYSECRET");
Crypt.IV = ASCIIEncoding.ASCII.GetBytes("MYSECRET");
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, Crypt.CreateEncryptor(), CryptoStreamMode.Write);
byte[] EncBytes = ASCIIEncoding.ASCII.GetBytes(CookieString);
cs.Write(EncBytes, 0, EncBytes.Length);
cs.FlushFinalBlock();
string EncryptedCookie = Convert.ToBase64String(ms.ToArray());
return EncryptedCookie;
}
My current services are using MVC to render forms, WebApi to move my viewModels back and forth and signalR for push notifications etc.
If the users are browsing the website they will be using forms auth, but we're introducing some mobile apps and I would like to be able to consume webapi and signalr from the mobile apps using basic auth, without having to maintain two separate sets of controllers.
I have two IPrincipals, a SessionPrincipal and a BasicPrincipal (where Session Principal inherits BasicPrincipal and has some additional contextual data). The idea is that some controllers will require to be on the website (SessionPrincipal), but everything else can be accessed by both web and mobile users (Basic Principal). Some won't require any authorisation at all, so can't just deny the request.
My current approach does the following steps to achieve this (some code omitted for brevity)
Global.asax Application_AuthenticateRequest
var cultureCookie = Request.Cookies["Culture"];
// Set culture ...
var authHeader = Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic"))
{
//Check Username / Password. If okay...
HttpContext.Current.User = new BasicAuthPrincipal(user);
}
else
{
var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
// Try and resolve Session from encrypted forms auth data. If okay...
HttpContext.Current.User = new SessionAuthPrincipal(Id, User, Agent);
}
}
Individual Authorize Filters (SessionMVC, SessionApi, BasicApi) that basically boil down to:
return HttpContext.Current.User as SessionPrincipal != null;
// Or
return HttpContext.Current.User as BasicPrincipal != null;
So if they were successfully set in global.asax then proceed to the controller.
Now, I have a working implementation of this, so why am I asking for help?
I'm not sure of certain fringe scenarios that may upset this. Am I asking for trouble for implementing it this way?
I read about HttpContext not being thread safe, but Application_AuthenticateRequest should run before everything else and no further changes are made to that data so I think it should be okay.
i want to add 3 serial key to client system using httpcookie when he visited my website
my website off course in asp.net MVC
but
serial key is different different not same.
when i add a 4th cookie then 1 key is automatically deleted.
how i can do this.
when user want to see then he can see recent 3 key.
Are you know how to add this cookie to client system by asp.net mvc website.
how i can add key1 , key 2 , key3 to client system.
Here's how you can do that.
Writing the serial-keys.
//create a cookie
HttpCookie SerialKeys = new HttpCookie("SerialKeys");
//Add serial-key-values in the cookie
SerialKeys.Values.Add("key1", "your-first-serialkey");
SerialKeys.Values.Add("key2", "your-second-serialkey");
SerialKeys.Values.Add("key3", "your-third-serialkey");
SerialKeys.Values.Add("key4", "your-fourth-serialkey");
//set cookie expiry date-time. Made it to last for next 12 hours.
SerialKeys.Expires = DateTime.Now.AddHours(12);
//Most important, write the cookie to client.
Response.Cookies.Add(SerialKeys);
Reading the serial-key cookie.
//Assuming user comes back after several hours. several < 12.
//Read the cookie from Request.
HttpCookie SerialKeys = Request.Cookies["SerialKeys"];
if (SerialKeys == null)
{
//No cookie found or cookie expired.
//Handle the situation here, Redirect the user or simply return;
}
//ok - cookie is found.
//Gracefully check if the cookie has the key-value as expected.
if (!string.IsNullOrEmpty(SerialKeys.Values["key1"]))
{
string serialKey = SerialKeys.Values["key1"].ToString();
//Yes key1 is found. Mission accomplished.
}
if (!string.IsNullOrEmpty(SerialKeys.Values["key2"]))
{
string serialKey = SerialKeys.Values["key2"].ToString();
//Yes key2 is found. Mission accomplished.
}
You can add cookies to the user when a user starts a session. This can be done by handling the session start even in the global.asax file of your application the adding in the logic code for creating these keys.
void Session_OnStart() {
HttpCookie key1 = new HttpCookie("key1","123");
Request.Cookies.Add(key1);
}
Then for the 4th cookie thing your were talking about you can create your code logic by referencing the users cookies by using Response.Cookies["cookie"] or remove one using Request.Cookies.Remove("cookie");
All browser limit in one way or another the amount of cookies a certain website can store. If for example your browser accepts n cookies, the when you send the n+1 the browser will delete your oldest one. It seems to me that this is what is going on.
A possible solution is to use one cookie with various subvalues instead of a single one. That way you can have in one cookie as many values as you want (subjected always to the cookie maximum size limit which is 4086 bytes).
The code to do that would be something like:
//This code creates the cookie, ads some subvalues to it and then adds it to the request so its sent to the browser
HttpCookie cookie = new HttpCookie();
cookie.Name = "MyKeys";
cookie.Values.Add("Key1", "ValueKey1");
cookie.Values.Add("Key2", "ValueKey2");
cookie.Values.Add("Key3", "ValueKey3");
//etc...
Request.Cookies.Add(cookie);
//This code reads the data from the cookie.
HttpCookie rcookie = Response.Cookies.Get("MyKeys");
string value1, value2, value3;
//We verify it the variable is null because the cookie might not exist in the users browser. If so, this variable would be null
if (rcookie != null)
{
value1 = rcookie.Values.Get("Key1");
value2 = rcookie.Values.Get("Key2");
value3 = rcookie.Values.Get("Key3");
}