AuthorizeAttribute not recognizing AuthCookie in ASP.NET - c#

Upon successful Login I have this line
FormsAuthentication.SetAuthCookie(a.username, true);
Then I have several pages which require login to be accessed, so I added the [Authorize] attribute to them like so
[Authorize]
public ActionResult Upload()
{
return View();
}
However, after logging in, such functions still return a 401 - Unauthorized error page just as if the user had not logged in. The error page states:
Logon Method Anonymous
Logon User Anonymous
Furthermore, in my project Anonymous Authentication is enabled and Windows Authentication is disabled.
I am looking for a solution where funcitons like Upload() are always available to any logged in user.

What you can do and what I've done is to write your own cookie this way:
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(1, //version number of ticket
userName, // UserName
DateTime.Now, //cookie creation time
DateTime.Now.AddHours(24), //Expiration time . cookie valid for 1 day
true, //Persistent
userData); // other data to store in ticket
// set Cookie
Response.SetCookie(
new HttpCookie(
FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(authTicket)) //// encrypt ticket
{
Expires = DateTime.Now.AddHours(24),
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL
});

"Forms authentication needs to be enabled, look in your web.config if you have in system.web" – glacasa

Related

How to Invalidate AspNetCore.Identity.Application Cookie after user log out

I am having trouble invalidating .AspNetCore.Identity.Application cookie in ASP.NET Core Identity once the user log out.
Once user clicks on log out below code will execute.
public async Task<IActionResult> Logout(LogoutInputModel model)
{
// build a model so the logged out page knows what to display
LoggedOutViewModel loggedOutViewModel = await BuildLoggedOutViewModelAsync(model.LogoutId);
_logger.LogInformation($"loggedOutViewModel : {JsonConvert.SerializeObject(loggedOutViewModel)}");
if (User?.Identity.IsAuthenticated == true)
{
// delete local authentication cookie
await _norskTakstSignInManager.SignOutAsync();
//clear cookies
var appCookies = Request.Cookies.Keys;
foreach (var cookie in appCookies)
{
Response.Cookies.Delete(cookie);
}
// raise the logout event
await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
}
// check if we need to trigger sign-out at an upstream identity provider
if (loggedOutViewModel.TriggerExternalSignout)
{
// build a return URL so the upstream provider will redirect back
// to us after the user has logged out. this allows us to then
// complete our single sign-out processing.
string url = Url.Action("Logout", new { logoutId = loggedOutViewModel.LogoutId });
// this triggers a redirect to the external provider for sign-out
return SignOut(new AuthenticationProperties { RedirectUri = url }, loggedOutViewModel.ExternalAuthenticationScheme);
}
return View("LoggedOut", loggedOutViewModel);
}
This successfully clears all the cookies in the browser, however, if I grab the value of the cookie named ".AspNetCore.Identity.Application" prior to signing out, then add it back in on to the browser, then i can log in to the application without entering user credentials.
I tested few flows setting up cookie expiration time in different ways but non of them seem to work correctly.
I want to know way to invalidate the cookie without just clearing to resolve this issue.Then user should not be able to enter cookie manually and log in to the system. Any help is hugly appreciated. Thank you.
That's by design... one thing you can do is try updating the user's security stamp after logout, using UserManager.UpdateSecurityStampAsync.
This way the cookie's security stamp won't match the one in the database and the cookie will no longer be valid (however, no other cookie issued to that user will, even if they haven't "signed out"... so if a user has several sessions opened, all of those cookies will stop being valid, not just the one you signed out).
Identity doesn't track specific user sessions (it just validates the cookie against the user, and if it matches, it matches). If you want to be able to selectively remove sessions, you'll have to track them yourself
For me the best security practice is save every login and logout in one record with an unique random ID as GUID, then save this "id session" into the claims, and check this everytime the user access, if the ID in the claim is correct to that session.

Store Id after authentication ASP net web forms

I would like to save the user ID after the forms authentication is made through email and password. I am currently using a session to do so;
However the session and the form authentication have different timeouts and because the session is a server type of variable when one user is logged in if I login with a different username on another machine the session simple changes its value and that is a major issue.
Besides Caching is there any other way to accomplish it?
You can store user ID in expanded authentication cookie. On authorization routine compose custom cookie and add it to response:
var ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(60), false, userId.ToString()));
HttpContext.Current.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket)) { HttpOnly = true });
You can decrypt that cookie for authenticated request and find out what was user ID:
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
int iserId = int.Parse(authTicket.UserData);

Combine server-side and client-side authentication with WebAPI

I have a legacy ASP.NET webforms application in which users login via a form that is processed server-side. If the entered username + password match to credentials in the database, I set some values in the sessions (e.g., the current user ID) and perform a Response.Redirect afterwards. I'm also creating a HttpCookie for a "automatically relog me next time I visit" functionality.
Currently, I'm also adding WebApi support into that web application. I've managed to implement token authentication which allows me to login on the client side.
How can I combine both authentication approaches? I want to the user to enter his credentials once, get authenticated on the server side and on the client side an redirect the users to another page after authenticating.
The following code will create a cookie to keep user logged in.
// login etc
if (chkRemember.Checked)
{
// calculate the total number of minutes in 20 days to use as the time out.
int timeout = (int)TimeSpan.FromDays(30).TotalMinutes;
// create an authentication ticket
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(txtUserName.Text, true, timeout);
// Encrypt the ticket
string encrptedTicked = FormsAuthentication.Encrypt(ticket);
// create the cookie for the ticket, and put the ticket inside
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrptedTicked);
// give cookie and ticket same expiration
cookie.Expires = ticket.Expiration;
// Attach cookie to current response. it will now to the client and then back to the webserver with every request
HttpContext.Current.Response.Cookies.Set(cookie);
// send the user to the originally requested page.
string requestedPage = FormsAuthentication.GetRedirectUrl(txtUserName.Text, false);
Response.Redirect(requestedPage, true);
}
else
{
// login without saving cookie to client
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, false);
}
You can use token based authentication in webapi using Angular JS. Visit following link
http://www.dotnetcurry.com/aspnet/1223/secure-aspnet-web-api-using-tokens-owin-angularjs

ASP.NET Web API Authorization with Postman

I have created an ASP.NET Web API and applied Authorize attribute to the API controller. Now, I want to test it using Postman but I am getting Authorization error.
Controller code is:
[Authorize]
[HttpPost]
public IHttpActionResult Attend([FromBody] int gigId)
{
var attendance = new Attdendance
{
GigId = gigId,
AttendeeId = User.Identity.GetUserId()
};
_context.Attdendances.Add(attendance);
_context.SaveChanges();
return Ok();
}
My request looks like this http://prntscr.com/c8wz0b
I am using this advance Postman rest client http://prntscr.com/c8xafd
How do I pass authorization in Postman?
EDIT 23/08/2016
I presume you are in cookie authentication with identity
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
This is the default configuration with identity in Visual Studio.
I can argue why it is not a good option for security but that's not the point.
You can go whit it in "postman" but it's tricky
this is how I do it :
Make a request over your login page :
Get the anti forgery token in the form :
Make a post request on login page with this post params in data form :
Now your postman get the authentication cookie and you can request web api with [authorize] tag
EDIT
For tool you have to add an authorization header.
Go in the Headers form
Add the HTTP header "authorization"
Click on the edit button et voilà ;)
screen shot
Previous answer deleted
For Postman Windows App 4.6.0:
Select your request from your request collection
Go to the "Authorization" tab
Choose an appropriate "Type", e.g. "Basic Auth"
Enter "Username" and "Password"
Click "Update Request"
In addition to the answer posted by Mathieu, I had to install interceptor extension for postman (https://www.getpostman.com/docs/interceptor_cookies, https://www.getpostman.com/docs/capture) to capture the cookies. After that it worked.

Some misunderstanding in authentication

I have some miss understanding in authentication using "User.Identity" and "FormsAuthentication.SetAuthCookie".
I have this action:
public ActionResult Login(string userName, string password)
{
if (Membership.ValidateUser(userName, password))
{
FormsAuthentication.SetAuthCookie(userName, true);
var isAuth = User.Identity.IsAuthenticated;
return View("Desktop");
}
return View("Login");
}
My question is why the value of the isAuth variable false after I set authentication ticket using this row(User.Identity.IsAuthenticated)?
By calling FormsAuthentication.SetAuthCookie you're simply dumping the authentication cookie to the HTTP response. At this stage the request is still considered as 'non-authenticated'.
Only the following requests (which will include the authentication cookie) will be considered as 'authenticated' and will have the User property set to the appropriate value.
If you want your HTTP request to immediately have the (just-authenticated) user set. Try this:
var user = new GenericPrincipal(new GenericIdentity(userName), null);
HttpContext.Current.User = Thread.CurrentPrincipal = currentUser;
MVC uses the standard ASP.Net pipeline. One part of the pipeline is authenticating the user. If a user is logged in after the pipeline has authenticated as anonymous, the only way to rerun the process is to redirect the user so the pipeline can authenticate the user. In your scenario, after you set the cookie, you'll need to do a redirect back to whatever action you want the user to go to.

Categories