OnLoggedIn event on Login page ASP.NET - asp.net

I want to redirect people according to their role in the asp.net membership provider. I have some code in 'OnLoggedIn' event on the login page. Here is what I tried so far, and nothing doesn't work:
The code below returns false on the .IsAuthenticated step, it says the user is not authenticated. On which step at the login page the user is authenticated, I thought the 'OnLoggedIn' event is the right place to do this.
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.Identity is FormsIdentity)
{
}
}
}
2nd thing I tried was to get all the roles for the user, but it doesn't return anything, returns empty array of strings, and I checked the database that the role is assigned to that specific user. Here is how I am trying:
string[] userRole = Roles.GetRolesForUser(LoginUser.UserName);
So, my question is how I can get the role on the login page, do I need to check that in some other event or on some other way.
Thanks for your help in advance, Laziale

The first situation won't work because it returns the value of the Request as it came in. Logging in with FormsAuthentication basically just sets a cookie in the Response so that the next Request gets the right User.
The second situation should work though, assuming that LoginUser is the name of your login control.

if you have some predefined set of rules like (SuperAdmin,Admin,User,....) than
you can use a switch case
and according to the authentication level
you can classify/redirect the user accordingly with respective URL

Greg is totally correct. So the question is why the roles are not returned? There could be several reasons depending on how you created the roles on your rolesprovider settings in web.config.
So make sure you roles provider is pointing to the same database you are see the roles.
Also check you are not using different role provider to create roles but accessing it via different one. This can happen if you have more than one roles provider in web.config.
Also check if it isn't the applicationName issue.
If that doesn't help post your web.config roles setting as well as info on how you are creating roles.

Related

How to force the re-login to all users when roles are changed using Symfony2 and FOSUserBundle?

I have a question about how can I force a re-login for all users when I execute a process that reloads all user roles.
Is possible do that? I'm using FOSUserBundle as user provider.
Thank you!
I never used FosUserBundle but one simple way to do this is in your User Class implementing the EquatableInterface and inserting in the isEqualTo method something like:
# this comparison is ONLY indicative
if ($this->roles !== $user->getRoles()) {
return false;
}
PS: At any request Symfony checks that assigned roles are not changed (but you can add also other fields to check like Email, Username, etc...), otherwise the user is automatically disconnected (but without printing a friendly message to the user)

Asp.net mvc Authentication filter overide default reditect

In my MVC 5 application I have applied some Role filters such as:
[Authorize(Roles = "ManageRoles")]
Now if a user does not have permission to access this role, it redirects me to the login page. This is incorrect in my application as I want to rather display an error message saying that you donot have permission to access.
Where do I change what happens if a user is not authorised to access a filter?
Do I have to implement custom filters? I would like to try and use the redirectTo action if possible so that I can have different error pages in different situations.
Use Custom Authorize Attribure - Ben Scheirman or Ben Cull's answer in this thread.
Also Check Mark's response to similar question, where he used HandleUnauthorizedRequest to redirect unauthorized users.
In the both the above approaches, you can redirect to any Route or Action of your interest and use HttpContent.Items[] or TempData to hold the specific error messages or values to be display on the destination page.
MVC5 has actually started to address this issue. They now include Authentication Filters in addition to Authorization Filters. These are pretty lightly documented, but my gut feeling is that this a first stab at separating authentication from authorization (up until now, ASP.NET has confused the two)
What i'm thinking is that Authentication filters will be used to control whether a user is logged in or not, and Authorization filters will be used to control what you have access to. However, it seems that this isn't yet fully realized.
In your Login view, you can add logic for:
Checking if the request is not authenticated
1.1. Display login form
Checking if the user is authenticated but not in the required role
2.1. Display error message
Since you'll be automatically redirected to the login page by your Web.config settings, you can take advantage of this mechanism.
if (!Request.IsAuthenticated)
{
//render login form
}
else
{
<p>Error: you do not have the necessary credentials to access this resource.</p>
}
Another option would be to create your own AuthorizationAttribute. This question is similar to yours. You might find it useful.

ASP.NET MVC authenticates and authorizes non-existent users

I'm using the DropCreateDatabaseAlways Initializer so my database gets destroyed every time I start the application (at least I hope so). The funny thing is I still see myself as logged in. I get pass the Authorize attribute and can do dangerous stuff. This is probably because of leftover cookies from previous testing.
Registration/login part of my app is the MVC 4 Internet Application template untouched. Shouldn't ASP.NET check the cookie values against users saved in the DB? WebSecurity.IsAuthenticated returns true and WebSecurity.CurrentUserName returns the name.
The only thing working as expected is WebSecurity.CurrentUserId which returns -1. I'm a newbie so I can only guess this is because UserId isn't stored in the cookie and must be retrieved from the database.
Am I right? If so, does it mean I should always use WebSecurity.CurrentUserId to determine whether a user is logged in? WebSecurity.IsAuthenticated and User.Identity.IsAuthenticated seem pretty useless in that case. I can delete a user's account and he or she remains unaffected. What should be done differently if I am wrong?
If you want to realiably check whether a user has not been deleted, you just have to consult the database.
Note that users and administrators work concurrently. This means that a user can be deleted just a second after he has been authenticated. A cookie can be then even one or two seconds old (!) and the user could probably have been just deleted.
In a most pessimistic scenario, a user types a valid username and password and is succesfully logged in and get the "sorry, your account has been deleted" just one request later (because the account has really just been deleted).
There will be a small window where if a user is deleted and they are still logged in that they can still access the site. Since most actions require a validate user id, you can simply throw an excpetion and log the user out.
Normally the database does not get blown away on each build, so I'm guessing this is not a use case SimpleMembership was coded for. You can of course check for this. I'll make another assumption that you are not closing your browser when you rebuild the site and deploy the new database. In a real world scenario these things just don't happen. The database is never blown away and the user id is never lost.
Generally once you've logged in the user, the user is not authenticated anytime after that (unless they have logged out, or the session has expired). That's the point of login. The authentication cookie is an indication that the authentication happened and was successful. The assumption going forward is the user has access to your site and is not reauthenticated.
As long as the authentication session remains open (i.e. browser now closed), the session cookie remains active and MVC assumes that the user is still valid.
Remove the cookie by using FormsAuthentication.LogOff() if the user is authenticated (User.Identity.IsAuthenticated == true) and there's no valid user in UserTable (WebSecurity.CurrentUserId == -1).
I had the same issue, but solved it by specifying the required role(s) in the Authorize attribute. As soon as you do this, it start getting to the database and fails with the "user does not exist" error, which is what you want.
[Authorize(Roles = "Customer")]
public class DashboardController : Controller
In normal case adding Session.Abandon(); to to your LogOff action in AccountController would do the job of clearing session:
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
Session.Abandon();
return RedirectToAction("Index", "Home");
}
So I think you can try adding Session.Abandon(); in init code, where you use DropCreateDatabaseAlways to clear session each time.
The ticket issuing time is usually encrypted within the authentication cookie then you can use it to require re-authentication to sensitive areas (inbox/billing etc.) if more than X time passed since login.
If you insist on invalidating all current auth tickets upon application changes (i.e database/configuration) you can change this settings in your web.config:
<machineKey validationKey="..." decryptionKey="" />

MVC Forms Authentication with custom database

I'm trying to get forms authentication working for an mvc site. I have a custom database with a users table, and I would like to do my own password validation.
I am logging in my user like this:
if (PasswordHasher.Hash(password) == dataUser.Password)
{
FormsAuthentication.SetAuthCookie(email, true);
return true;
}
The problem is, when the session expires obviously the user has to login again.
I am thinking I should be storing this Auth cookie in my users table?
Update: I'm obviously in desperate need of more education in this area. I just noticed that the user stays authenticated even after an iisreset.
I guess what I'm asking is how can I get persistent and non persistent authentication working properly. I want a user to not have to login again if they click "remember", and if they don't then their authentication should expire when the forms authentication is set to expire.
Turns out I forgot to put my variable in the second argument of the SetAuthCookie method. It was always sending true for the "persistent" argument. FML.
I'd recommend implementing a custom Membership Provider so you can leverage the existing controls or patterns that are out there for the existing membership providers.

ASP.NET Problem Caching Roles In Cookie

I'm using ASP.NET Roles with a special role "Must Change Password". If a user has not changed their password for more than 90 days, they are automatically added to this role. This happens during the user login process. Authorization rules then deny that role access to all of the application except the "change password" page.
Generally this works great, but there is a problem when the role cache cookie is used to cache roles. What happens is during the login process, the password last changed date is checked, and if > 90 days, the user is added to the "Must Change Password" role. In the same page request, I subsequently call Roles.IsUserInRole("Must Change Password") to decide whether to redirect the user to the Change Password page or not. This is where it falls down - it seems that with the role cache cookie enabled, Roles.IsUserInRole("Must Change Password") doesn't realise that I have changed role mappings for this user, and returns false. However, on the next page request, Roles.IsUserInRole("Must Change Password") returns true.
This behaviour is fixed by setting cacheRolesInCookie="false", but that seems a high price to pay. Is there another way to fix this problem?
Another , IMHO more elegant, solution is to cast HttpContext.User to RolePrincipal and call SetDirty method after adding a new role to the user (read more on RolePrincipal.SetDirty).
The next call of IsInRole or GetRolesForUser methods should trigger request to your default RoleProvider.
Since you said that the problem exists in the same request, how about also setting an item in the HttpContext.Current.Items collection to indicate that the user must change their password, and check both the cookie and the HttpContext.Current.Items collection later on in the code?
Actually, I've found the problem - it is not a problem with caching roles in cookies, but rather a problem with Roles.IsUserInRole(). If I use the overload Roles.IsUserInRole(username, role) then it works fine, with or without roles cached in a cookie.

Resources