ASP.NET MVC Remember me - asp.net

I've got a project based in ASP.NET MVC 4 that simple authentication.
I'm trying to get my site to automatically log the user in when they check the remember me checkbox. However I'm having problems getting this working. After closing down the browser and reopening it the user is never logged in.
After checking (http://forums.asp.net/t/1654606.aspx#4310292) I've added a machine key in, generated by IIS. I've set automatically generate at runtime and generate a unique key for each application have both been disabled and I've Generated Keys). Unfortunately this hasn't worked.
Looking at "Remember me" with ASP.NET MVC Authentication is not working, I've added in the line FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe) but that didn't work either so I've now commented it out.
I tried the answer given on ASP.NET MVC RememberMe but that doesn't seem to work either.
Am I missing something obvious?
//FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (model.RememberMe)
{
//int timeout = model.RememberMe ? 525600 : 2; // Timeout in minutes,525600 = 365 days
int timeout = 525600;
var ticket = new FormsAuthenticationTicket(model.UserName, model.RememberMe, timeout);
string encrypted = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
cookie.Expires = System.DateTime.Now.AddMinutes(timeout);//My Line
Response.Cookies.Add(cookie);
}

this is how i do it
public class MyAuthentication
{
public static HttpCookie GetAuthenticationCookie(LoginModel model, bool persistLogin)
{
// userData storing data in ticktet and then cookie
JavaScriptSerializer js = new JavaScriptSerializer();
var userData = js.Serialize(model);
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
"akash",
DateTime.Now,
DateTime.Now.AddHours(1),
persistLogin,
userData);
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie cookie= new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.Expires = authTicket.Expiration; //must do it for cookie expiration
return cookie;
}
internal static bool Login(string UserName, string Password)
{
//UserName="akash" Password="akash"
//check can be done by DB
if (UserName== "akash" && Password == "akash")
return true;
else
return false;
}
}
and then
[HttpGet]
[AllowAnonymous]
public ActionResult Login()
{
//ViewBag.Message = "Your contact page.";
HttpCookie cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
// var ek = cookie.Value;
try
{
//some times no cookie in browser
JavaScriptSerializer js = new JavaScriptSerializer();
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
//string data = ticket.UserData;
LoginModel model = js.Deserialize<LoginModel>(ticket.UserData);
if (MyAuthentication.Login(model.UserName, model.Password) == true)
{
RedirectToAction("Index", "Home");
}
}
catch
{
}
return View();
you can check it on Global.asax or authorization filter.
make sure you have web.config has
<authentication mode="Forms">
<forms defaultUrl="/Home/Login" loginUrl="/home/Login" timeout="2880">
</forms>
</authentication>
and [Authorize] attribute before all controller.

builder.Services.AddControllersWithViews();
var constr = builder.Configuration["ConnectionStrings:Default"];
builder.Services.AddDbContext<AppDbContext>(opt =>
{
opt.UseSqlServer(constr);
});
builder.Services.AddIdentity<AppUser, IdentityRole>(opt =>
{
opt.Password.RequiredLength = 8;
opt.Password.RequireDigit= true;
opt.Password.RequireLowercase= true;
opt.Password.RequireUppercase= true;
opt.Password.RequireNonAlphanumeric= true;
opt.User.RequireUniqueEmail= true;
opt.Lockout.MaxFailedAccessAttempts= 5;
opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(10);
opt.Lockout.AllowedForNewUsers= true;
}).AddEntityFrameworkStores<AppDbContext
().AddDefaultTokenProviders();
builder.Services.AddSession(opt =>
{
opt.IdleTimeout = TimeSpan.FromSeconds(15);
});
builder.Services.ConfigureApplicationCookie(opt =>
{
opt.LoginPath = "/Auth/Login";
});
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();

Related

Force logout from asp.net application when the same url is pasted in another tab

i am new to this authentication mechanism and still learning.What i am trying to achieve is that..when the user tries to use multiple instances of the application like say for by opening different tabs,the application should automatically logoff.
My login Code
public static bool SignIn(int officeId, string userName, string password, bool remember, System.Web.UI.Page page)
{
int userId = BusinessLayer.Office.Users.GetUserId(userName);
bool active = BusinessLayer.Office.Users.IsUserActive(userId);
if(!active)
{
return false;
}
if (page != null)
{
try
{
string remoteAddress = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
string remoteUser = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_USER"];
DateTime? serverDate = BusinessLayer.Core.DateConversion.GetCurrentServerDate();
string pass = BusinessLayer.Security.Password.GetHash(password, userName);
long logOnId = Everest.Net.DatabaseLayer.Security.User.SignIn(officeId, userName,
BusinessLayer.Security.Password.GetHash(password, userName),
page.Request.UserAgent, remoteAddress, remoteUser);
// var isActive = BusinessLayer.Office.Users.GetUserId(userName);
if (logOnId > 0)
{
if (IsBoDStarted(Conversion.TryCastDate(serverDate)))
{
var isSessionSet = SetSession(page, userName);
if (isSessionSet)
{
var ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now,
DateTime.Now.AddHours(12), remember, String.Empty, FormsAuthentication.FormsCookiePath);
string encryptedCookie = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedCookie);
cookie.Expires = DateTime.Now.AddHours(12);
page.Response.Cookies.Add(cookie);
System.Web.Security.FormsAuthentication.RedirectFromLoginPage(userName, true, "Everest.Net");
return true;
}
}
else
{
var ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now,
DateTime.Now.AddHours(12), remember, String.Empty, FormsAuthentication.FormsCookiePath);
string encryptedCookie = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedCookie);
cookie.Expires = DateTime.Now.AddHours(12);
page.Response.Cookies.Add(cookie);
page.Response.Redirect("~/Utilities/BodOperation.aspx");
return true;
}
}
}
catch (DbException)
{
//Swallow the exception
return false;
}
}
if (page != null)
{
page.Session.Clear();
}
return false;
}
Any ideas by you experts around here would be helpful.I did searched about this in SO and in here.Couldnt get the grasp of it.Any help appreciated.
My webconfig
<authentication mode="Forms">
<forms loginUrl="~/SignIn.aspx" timeout="6" slidingExpiration="true" defaultUrl="~/Index.aspx" />
</authentication>
In my above webconfig since the timeout is set to 6minutes, this doesnot works too.
Help Please.

Authentication changes in .NET 4.5.1

I have some knowledge on .NET 4.5, but totally new to 4.5.1. As I read, they have a couple of changes so that apps work with Identity, which is nice for scale web apps.
That being said, I need to work on a web app with a basic user/password login system and I'm wondering if this template Individual User Accounts can work, or if I have to go with No Authentication? Please explain your answer.
basic user/password login system
Individual User Accounts will configure ASP.Net Identity for you. In addition, it will also create basic login, logout and other extra templates too. Click on Learn more for more information.
However, if you just need simple FormAuthentication, you want to select No Authentication.
The following is the example of simple FormAuthentication.
Sign-In method
public void SignIn(string username, bool createPersistentCookie)
{
var now = DateTime.UtcNow.ToLocalTime();
TimeSpan expirationTimeSpan = FormsAuthentication.Timeout;
var ticket = new FormsAuthenticationTicket(
1 /*version*/,
username,
now,
now.Add(expirationTimeSpan),
createPersistentCookie,
"" /*userData*/,
FormsAuthentication.FormsCookiePath);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (ticket.IsPersistent)
{
cookie.Expires = ticket.Expiration;
}
if (FormsAuthentication.CookieDomain != null)
{
cookie.Domain = FormsAuthentication.CookieDomain;
}
Response.Cookies.Add(cookie);
}
Global.asax.cs
You need this in order to retrieve the username from cookie, and save it in IPrincipal Object.
public class Global : HttpApplication
{
private void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie decryptedCookie =
Context.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket =
FormsAuthentication.Decrypt(decryptedCookie.Value);
var identity = new GenericIdentity(ticket.Name);
var principal = new GenericPrincipal(identity, null);
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = HttpContext.Current.User;
}
}
web.config
Make sure you have authentication tag in web.config.
For example,
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" />
</authentication>
Usage
public ActionResult Index()
{
var username = User.Identity.Name;
return View();
}

How Authenticate by WebMethod

I Passed userName and Pass to webmethod in .aspx page by Ajax in Json Format,
now i want authenticate users and redirect user to same page and update LoginView with LogedIn State;
How Can i do it?
here's my WebMethod
[WebMethod]
// [ [System.Web.Script.Services.ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet=false)]
public static void login(object myData)
{
JavaScriptSerializer js = new JavaScriptSerializer();
List<nameVal> myfrm = js.Deserialize<List<nameVal>>(myData.ToString());
// MembershipUser u = Membership.GetUser(myfrm.SingleOrDefault(rs=>rs.name=="userName").value);
if ( Membership.ValidateUser(myfrm[0].value,myfrm[1].value))
{
FormsAuthentication.Authenticate(myfrm[0].value, myfrm[1].value);
//FormsAuthentication.RedirectFromLoginPage(myfrm[0].value, false);
FormsAuthenticationTicket tkt;
string cookiestr;
HttpCookie ck;
tkt = new FormsAuthenticationTicket(1, myfrm[0].value, DateTime.Now,
DateTime.Now.AddMinutes(30), true, "my custom data");
cookiestr = FormsAuthentication.Encrypt(tkt);
ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
ck.Path = FormsAuthentication.FormsCookiePath;
// ******* now i must somthing like this: --> Response.Cookies.Add(ck);
// but im in static method don't have respons request objects
// i want respons in json form and proccess the json
// return "Success";
}
else
{
//return "Faild";
}
}
so tanks
You can do the following:
FormsAuthentication.SetAuthCookie(myfrm[0].value, createPersistentCookie: false);
return FormsAuthentication.GetRedirectUrl(user.Name, false);
and then in your javascript:
var onSuccess = function (result) {
if (result === null) {
// login failed
return;
}
window.location.href = result;
};
PageMethods.login(myData, onSuccess);
This unfortunately still has a "silent" ThreadAbortException that I can't seem to get rid of, but it doesn't seem to cause any problems. I think it's probably unavoidable and benign.

User is in role "admin" but [Authorize(Roles="admin")] won't authenticate

I found a great answer on SO describing how to set up custom user roles, and I've done the same in my project. So in my Login service I have:
public ActionResult Login() {
// password authentication stuff omitted here
var roles = GetRoles(user.Type); // returns a string e.g. "admin,user"
var authTicket = new FormsAuthenticationTicket(
1,
userName,
DateTime.Now,
DateTime.Now.AddMinutes(20), // expiry
false,
roles,
"/");
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(authTicket));
Response.Cookies.Add(cookie);
return new XmlResult(xmlDoc); // don't worry so much about this - returns XML as ActionResult
}
And in Global.asax.cs, I have (copied verbatim from the other answer):
protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null) {
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var roles = authTicket.UserData.Split(new Char[] { ',' });
var userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}
Then, in my ServicesController class, I have:
[Authorize(Roles = "admin")]
//[Authorize]
public ActionResult DoAdminStuff() {
...
}
I login as a user with the "admin" role, and that works. Then I call /services/doadminstuff - and I get access denied, even though when I put a breakpoint in Global.asax.cs, I can see that my roles do include "admin". If I comment out the first Authorize attribute (with roles) and just use a plain vanilla Authorize, then I can access the service.
I must be missing something critical here - but where to start looking?
I would recommend you use a custom authorize attribute instead of Application_AuthenticateRequest:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
string cookieName = FormsAuthentication.FormsCookieName;
if (!filterContext.HttpContext.User.Identity.IsAuthenticated ||
filterContext.HttpContext.Request.Cookies == null ||
filterContext.HttpContext.Request.Cookies[cookieName] == null
)
{
HandleUnauthorizedRequest(filterContext);
return;
}
var authCookie = filterContext.HttpContext.Request.Cookies[cookieName];
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(',');
var userIdentity = new GenericIdentity(authTicket.Name);
var userPrincipal = new GenericPrincipal(userIdentity, roles);
filterContext.HttpContext.User = userPrincipal;
base.OnAuthorization(filterContext);
}
}
and then:
[CustomAuthorize(Roles = "admin")]
public ActionResult DoAdminStuff()
{
...
}
Also a very important thing is to ensure that when you login an authentication cookie is emitted because you return an XML file. Use FireBug to inspect whether the authentication cookie is properly sent when you try to access the url /services/doadminstuff.
I would change principal assign at first:
Thread.CurrentPrincipal = userPrincipal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = userPrincipal;
}
as ASP.NET documentation stands.

Problem creating persistent authentication cookie: ASP.NET MVC

OK, here's my code to create an authentication cookie:
// get user's role
List<UserType> roles = rc.rolesRepository.GetUserRoles(rc.userLoginRepository.GetUserID(userName));
List<string> rolesList = (from r in roles
select r.ToString()).ToList();
string[] rolesArr = rolesList.ToArray();
// create encryption cookie
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
userName,
DateTime.Now,
DateTime.Now.AddDays(90),
createPersistentCookie,
String.Join(";",rolesArr) //user's roles
);
// add cookie to response stream
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
System.Web.HttpCookie authCookie = new System.Web.HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);
//FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
And here's my code in Global.asax to set the user roles into the user identity:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
{
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(new char[] { ';' });
if (Context.User != null)
{
Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
}
}
catch
{
return;
}
}
However, if "createPersistentCookie" is TRUE in the top example, no persistent cookie is created. If I uncomment the last line like so:
//System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
then the persistent cookie is created on my hard drive. BUT then in the Global.asax code, the UserData field in "authTicket" is blank, so I can't set up the roles properly!
So I have to use SetAuthCookie to create a persistent cookie, but then for some reason the UserData field disappears from the persistent cookie.
What is the answer to this??
To create a persistent cookie you need to set the Expires property:
if (authTicket.IsPersistent)
{
authCookie.Expires = authTicket.Expiration;
}

Resources