Auto login from credentials based in the URL - c#

c#, .net4, webforms
I'm building if someone forgets a password. A system admin can send a link to the customers email, they can click it, it logs in, and forces them to update their profile. I have everything working and verifying. Now I don't understand (still reading) on how to make
HttpContext.Current.User.Identity.IsAuthenticated == true; after my method returns true that the person is verified and allow the information from the url log that person in. I know I'm missing something, or not understanding how it works.
Either way, thanks for the help

If someone needs this
if (verifiedUser != "0")
{
//if user is verified
FormsAuthentication.SetAuthCookie(verifiedUser, true);
var LoginType = HttpContext.Current.User.Identity.AuthenticationType;
if (!User.Identity.IsAuthenticated)
{
Response.Redirect(Request.RawUrl);
}
}
Works for my issue.

Related

Can't login to my mvc site after publishing it to a Web hosting service

I have a asp.net MVC website that I've recently published on a web hosting service. Almost everything works great, the information that I get from my msSQL db is shown on the pages etc etc. But there's one problem. When I try to log in to my website, it won't work. Before I explain any further, you'll have to take a look at the following code which is how I authenticate a user login:
public ActionResult Login()
{
return View();
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
if (Repository.AuthenticateLogin(model.Username, model.Password.GetHashCode().ToString()))
{
FormsAuthentication.SetAuthCookie(model.Username, false);
return RedirectToAction("Index", "Home");
}
else
{
TempData["WrongLogin"] = "The username or password you've entered is wrong. Please try again!";
return View(model);
}
}
else
{
return View(model);
}
}
And the method "AuthenticateLogin(string username, string password) that is used in the if-statement above looks like this:
public static bool AuthenticateLogin(string username, string password)
{
using (var context = new SHultEntities())
{
return (from u in context.User
where u.Username == username && u.Password == password
select u).Any();
}
}
Now, as you can see, to authenticate a user, I am checking the entered username and password against any user in the database's user-table. If there is a match, the method returns "true", or else it returns "false". Yeah, you get it.
Well, the problem is, when I try to log in on my site I get the TempData["WrongLogin"] text, which means my AuthenticateLogin method must've returned false, which means that there must not have been any matches. But when I try this on my local project on my computer, with the same username and password, the AuthenticateLogin returns true.
If the problem was the connection to the database, the headers and contents that I retrieve from my database would not appear on the site. But it does. Also, when I update something from my local project and then go on my website, the updated information appears. So, the only problem is that I can't log in.
This is driving me crazy and I would really appreciate some help.
EDIT: Could be worth mentioning that I have to log in to my website to edit any content/information. That's why I mentioned that I can log in and change from my local project, and then the changes appear on the website.
FOUND PROBLEM: I tried creating a user with a non-hashed password and deleted the .GetHashCode.ToString() from the AuthenticateLogin on the password. Then i re-published. It works. The problem is the hashing.
How can I solve this? I need hashed passwords in the db...
How did you seed the username and password in your database? If the implementation of password.GetHashCode() is machine specific (i.e. relies on a machine specific salt) then this could be why it cannot match against any users. On the other hand if the users were created via the remote (hosted) environment, this should not be a problem.
The problem was caused by my hashing. Apprenatly, two strings that looks exactly the same can produce different values when hashed, with standard framework implementation of .GetHashCode(), on different machines (even though the machines are using the same version of the framework).
For more information, click here!
I Solved my problem by using a customized Hashing-class.

Web Security not working in Chrome and Firefox

I am currently using Web Security. User can log in using this code
if (WebSecurity.Login(loginRequest.EmailAddress, loginRequest.Password))
{
FormsAuthentication.SetAuthCookie(loginRequest.EmailAddress, false);
var userDetails = new string[2];
userDetails[0] = loginRequest.EmailAddress;
var currentUSerRole = Roles.GetRolesForUser(loginRequest.EmailAddress);
userDetails[1] = currentUSerRole[0].ToString();
return response = Request.CreateResponse(HttpStatusCode.Accepted, userDetails);
}
The login code works, but IsAuthentcated always returns false and CurrentUsername always return -1 and all Websecurity methods are not worked well when I run my application on Chrome and Firefox browsers. But it's working good on IE Browser.
What did I missed? Is it any cors issue? or anything else? I found a lot of answers from Google, but they haven't helped me.
Any One Help Me
As per My knowledge
FormsAuthentication.SetAuthCookie(string, bool); can be used to login/logout a particular user with the string a username and bool value as true/false for log in/out.
FormsAuthentication.SetAuthCookie("user", true); will log in the user and the WebSecurity will have its userID.
FormsAuthentication.SetAuthCookie("admin", false); will log out admin and will remove its userID from WebSecurity.
so you should try FormsAuthentication.SetAuthCookie("user", true);

How can I get the Role for a user after Login?

Here is my sample code for logging in:
if (WebSecurity.Login(playerModel.WorkerID, playerModel.Password))
{
if (Roles.IsUserInRole(User.Identity.Name, "Administrator"))
{
// display the admin panel
ViewBag.Message = "Admin Panel";
return View("Index");
}
else
{
ViewBag.ButtonText = "Log In";
ViewBag.Message = "You are not an Admin user";
return View();
}
}
For some reason, the first time I log in, the user is not in "Administrator" even though they are in the correct Role in the table. I have also tried using this:
Roles.GetRolesForUser();
That returns an empty array. I'm assuming there is a limitation to do with the user logging in, a post-back occurring and then being able to check the role. But I'm hoping there is a workaround (or I have something wrong).
After a post-back both the Roles.IsUserInRole and Roles.GetRolesForUSer methods work correctly.
you could try using
HttpContext.Current.User.IsInRole("role")
I'm not 100% sure on when the Roles security class gets updated after a login - but I bets its not until the forward page gets called and a whole new request is generated.
The solution was to redirect to another page and check there. The issue is that the cookie isn't read back in with the role information until you have another postback (read the cookie you just wrote).

Membership.GetUser() C# .NET

I am trying to use either the UserName or (preferably) the user ID to determine what specific user is logged into my application. My intent, is to limit the amount of content that can be uploaded to my site based on the user. Whenever the user attempts to upload a document, I want to retrieve a count of all the documents they have currently uploaded. As a test run, I just added a label to my form to try and identify the user before writing a query:
// validate user. If they are not authenticated, do not let them upload files
if (!HttpContext.Current.User.Identity.IsAuthenticated || !HttpContext.Current.User.IsInRole("Administrator"))
{
uploadLabel.Visible = false;
user.Text = Membership.GetUser().UserName; // this line should output the username
mapUpload.Visible = false;
uploadButton.Visible = false;
}
I know the authentication logic works, because all other fields are not visible when logged in. Additionally, Membership.GetUser().UserName only has a value when the user IsAuthenticated; else, I get a null pointer exception. If the code is called, then Membership.GetUser().UserName appears to be setting the label to an empty text string.
Is there another way to get information for the current logged in user? As mentioned, my ultimate goal is be able to write a query with the information:
SELECT COUNT(DocumentID) FROM Documents WHERE UserID=#UserID
Thanks in advance for any assistance.
Bic
No need to use MembershipUser event to get currently logged in user we have another simple way to get currently logged in username you just define like this in your page
string userName = Page.User.Identity.Name;
Can't you replace
user.Text = Membership.GetUser().UserName;
with
user.Text= User.Identity.Name

Deleted User logged in even after deleting on the other broswer

var query = from p in AdminModelContext.Users
where p.UserName == model.UserName && p.Password == encryptPassword
&& p.IsDeleted == false
select p;
IList<Users> userList = query.ToList();
if (userList.Count() > 0)
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (CheckUrl(returnUrl))
{
return Redirect(returnUrl);
}
SetRoleForUser(userList[0].RolesId);
LoggerService.Info(string.Format("Login Successful for the user : {0}",
model.UserName));
return RedirectToAction("Index", "Home");
}
I am using the following code to Login through my website. The problem that I am facing is when I logged in with a user on a specific browser and at the same time login with a different user on a different browser, and then I delete the user(logged in on the other browser). Still I am able to navigate through the pages with the deleted user logged in.
I am not finding a fair solution to put authentication logic on every page. My website is in MVC model and using Form based authentication.
Please suggest how can I put the logged in user session validation and achieve this.
None of the answers so far actually acknowledge the question.
Lets look at the control flow:
User A enters log in page, supplies valid credentials
User A is issued Ticket A.
User B enters site, supplies valid credentials.
User B is issued Ticket B.
User B then revokes User A's access CREDENTIALS.
At this point nothing happens to Ticket A. Because the Ticket is independent on the credentials. When Ticket A expires they will then be required to present their credentials and it will fail login.
So what you've noticed that kicking a live user out of your site is actually pretty hard. As you've realized the ONLY solution is to have authentication logic on EVERY request. That unfortunately is really heavy.
In the login system I built I handled this aspect by creating 2 tickets, 1 ticket that's stored in the Forms Auth ticket as normal that has a big duration, and a ticket that's stored in HttpRuntime.Cache, I set the cache expiration to 15 minutes on this ticket.
On every page request I check to see whether a user has a ticket in the cache (based off their Forms Auth ticket information), at this point if they have no ticket I do a user data refresh and poll the user database. If the user has become suspended or deleted they will be logged out at then.
Using this method I know that my site can disable a user and within 15 minutes that user will be barred from the site. If I want them immediately barred I can just cycle the app config to clear the cache and FORCE it to happen.
Normally if you have the [Authorize] attribute defined for an Controller or an Action the Authentication is checked on every post back.
The build in MembershipProvider handles all that for you. But it seems you are using your own user Database. Then you have to implement your own MembershipProvider, IPrincipal and MembershipUser and have this added to your Web.config replacing the default one.
More you'll find here how to implement your own MembershipProvider: http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
My suggestion is to create an empty MVC project and have a look at the default authentication mechanism. And if your building a new Application with a new Database, try to use the default authentication.
Your validateUser function in your own MembershipProvider could look like this.
public override bool ValidateUser(string username, string password)
{
bool isValid = false;
bool isApproved = false;
string pwd = "";
using (AdminModelContext db = new AdminModelContext())
{
var user = db.Users.FirstOrDefault(u => u.UserName == username);
if (user != null)
{
pwd = user.Password;
isApproved = user.IsApproved;
if (CheckPassword(password, pwd))
{
if (isApproved)
{
isValid = true;
user.LastLoginDate = DateTime.Now;
user.LastActivityDate = DateTime.Now;
try
{
db.SubmitChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
else
{
UpdateFailureCount(username, "password");
}
}
}
return isValid;
}
I see the problem now. I dont know how this works in MVC, but by using Authenticate_Request, you can validate if the user is still valid. The business logic may also double check if the user is still valid. But as far as I know, there is no way of iterating all the open sessions and killing the requierd ones, even in that case, the authorization cookie should be double checked on Session_Start event.
Another options is adding a global invalidated_users list on the application, and then checking that user against the invalid list. This list should only contain users that are invalidated after the application has restarted.
Link for Reading All Users Session:
http://weblogs.asp.net/imranbaloch/archive/2010/04/05/reading-all-users-session.aspx

Categories