Possible Duplicate:
Can I change the FormsAuthentication cookie name?
I have multiple MVC3 sites that create FormsAuthentication tickets and store them in cookies.
Login:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(15), true, String.Empty);
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
In Application_AuthenticateRequest:
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
Surely this will cause issues if multiple sites are saving to the same cookie?
Is there any harm in having a different cookie name for each app or is there another recommended way to do it?
It will only cause issues if those multiple sites are on the same domain.
You can set the cookie name in the web.config - see Can I change the FormsAuthentication cookie name?
Related
In the spring boot project, when the user logouts, we invalidate the cookie with this block of code:
//name = "Token"
//value = "expired"
//age = 0
private void setExpiredCookie(HttpServletResponse response, String name, String value, int age) {
Cookie cookie = new Cookie(name, value);
cookie.setSecure(true); //Send cookie to the server only over an encrypted HTTPS connection
cookie.setHttpOnly(true); //Preventing cross-site scripting attacks
cookie.setPath("/"); //Global cookie accessible every where
cookie.setMaxAge(age); //Deleting a cookie. I Passed the same other cookie properties when you used to set it
response.addCookie(cookie);
}
However, after logout, I tested my website with an application for catching the request and resending it through the repeater, with exact values, such as token and payload.
I resent a request, for example, to change the email address, and this request, despite logging out, is valid for 15 minutes (for the life of the original cookie).
What am I missing? Because I am properly deleting and protecting cookies.
You are just creating new cookie.
You should invalidate cookie with session id, which was given to you when you authenticated. Simply use this:
HttpSession session = httpServletRequest.getSession(false);
session.invalidate();
I have an old MVC system in use that a Whitehat company is complaining about after penetration testing.
The scenario is as follows:
User logs in with credentials.
User takes note of .ASPXAUTH and ASP.Net_SessionId cookies and their values
User logs off
User then uses F12 to add the cookies and their values
Navigate to a page that would normally not allow as user is not logged in, but it works OK when it should not
On logout I am deleting the cookies - that is not the problem.
The problem is that the 'values' remain within the server somehow and can be reused.
The code I use for logoff is as follows:
FormsAuthentication.SignOut();
// Drop all the information held in the session
Session.Clear();
Session.Abandon();
// clear authentication cookie
HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie1.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie1);
// clear session cookie
HttpCookie cookie2 = new HttpCookie("ASP.NET_SessionId", "");
cookie2.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie2);
return RedirectToAction("Index", "Home");
This question already has answers here:
Accessing Session Using ASP.NET Web API
(13 answers)
Closed 3 years ago.
In my Web api when a user login successfully I set session with some values like
HttpContext.Session.SetObject("CurrentUserID", user.Id);
HttpContext.Session.SetObject("CurrentUserRoles",user.Roles);
and just return token and some values to save in cookie
return Ok(new
{
Id = user.Id,
Username = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
Token = tokenString,
role = user.Roles
});
But when the client hit api action which has this line
List<string> userRolesList = HttpContext.Session.GetObject<List<string>>("CurrentUserRoles");
Then always get null value even I have added session inside Startup >Configure
like
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
and ConfigureService also
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds( 60 * 60);
options.Cookie.HttpOnly = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
but does work still... Please help.
HTTP is a stateless protocol. Sessions are fake state, enabled by both a server-side and client-side component. The client-side component is a cookie: specifically a Set-Cookie response header. In order for the session to be restored on the next request, the value of this Set-Cookie response header must be sent back via the Cookie request header with each request. A web browser (the client) will do all this automatically, including persisting the cookie locally. However, a thin client like HttpClient, Postman, etc. will not. You would need to independently persist the cookie from the response header and then attach it to each request via the Cookie header in order to maintain the session between requests.
That said, this is a major reason why APIs typically do not, and honestly should not make use of sessions. It's simply a pattern that doesn't make much sense in an API context, and only adds a potential point of failure, since clients must pay attention to the cookie headers, and take manual actions to handle the cookies.
I use the IdentityServer 3 with the ResourceOwner Flow.
It seems to work. I can see in fiddler the token is accessed and validated by my WebAPI.
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "http://server/IdentityServer/",
ValidationMode = ValidationMode.ValidationEndpoint,
RequiredScopes = new[] { "MyFramework" },
SigningCertificate = Certificate.Get(),
DelayLoadMetadata = true
});
If I configure:
ValidationMode = ValidationMode.ValidationEndpoint
There is an extra request.
With ValidationMode.Local there is not. (This is good because IdentityServer is embedded in the WebAPI).
But if I use ValidationMode.Local, there are TWO requests to the IdentityServer.
http://server/IdentityServer/.well-known/openid-configuration
http://server/IdentityServer/.well-known/jwks
Why is this reccessary? The IdentityServer is embedded and this information is accessible in-memory. Even if the setting is "ValidationMode.ValidationEndpoint" this two calls do not appear.
But back to my primary question:
How can I validate the ClaimsIdentity in my WebAPI?
I have an "AuthenticationHandler" (ASP.NET-DelegatingHandler) that handles the validation for my old basic-authentication.
I figured out I can use the HttpContext.Current.User to access the IPrincipal.
Now I check it is of the type "ClaimsIdentity" and the Identity.IsAuthenticated==true.
Is this a correct approach?
And how can I check the User-ID?
On the server-side the ID of the user is put in the "sub"-claim (aka 'Subject').
Do I have to access this specific property to check which user is logged in?
I could access it like this:
ClaimsIdentity.Claims.FirstOrDefault(c => c.Type.Equals("sub"));
BUT only with the setting "ValidationMode.ValidationEndpoint".
Then the AuthenticationType of the IPrincipal is "Bearer" and the 'sub'-claim is present.
With the setting "ValidationMode.Local" the AuthenticationType is "JWT" and the claim is not present.
Why does the ValidationMode changes the IPrincipal? Do I have to check this for different cases?
I am using forms authentication for an MVC website and I am having a problem adding Cookies, I am using an Encrypted Forms Authentication Ticket and adding it to the Cookies but when inspecting my cookies it is there (by name "AuthCookie") but the value is always null and the Expires date is always set to "01/01/0001 00:00"... here is my Login controller code:
[HttpPost]
public ActionResult Index(Login login, string returnUrl)
{
if (ModelState.IsValid)
try
{
User user = UserManager.Login(login.Username, login.Password);
string serialUser = Serialize.SerializeToString(user);
string ticket = FormsAuthentication.Encrypt(
new FormsAuthenticationTicket(1, login.Username, DateTime.Now, DateTime.Now.AddMinutes(20.0), login.RemeberMe, serialUser));
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, ticket) { Expires = DateTime.Now.AddMinutes(20) };
Response.Cookies.Add(cookie);
if (String.IsNullOrEmpty(returnUrl))
return RedirectToAction("Index", "Home");
else
return Redirect(returnUrl);
}
catch (LoginFailedException)
{
ModelState.AddModelError("", "Login failed: Invalid Username or Password.");
return View(login);
}
else
return View(login);
}
At first I assumed the encrypted string was not working due to the length but I have tested this by creating a simple test cooke and I am getting the same result.
Can anyone help
When you call Redirect() or RedirectToAction(), you're terminating the response so the cookies aren't sent to the client. Some solutions:
Use TempData to persist the information across the direct, writing the Cookie in the action you redirect to.
Take a look at the way Forms Authentication cookie information is written in the NerdDinner code on CodePlex.
As mentioned in the comments, you can persist role information in Session. The recommendation to store the role information in Session and retrieve from Roles if not found would work, but I'd start by using the membership system as-is and performance tuning later if you see that it's a problem, rather than assuming it will be.