Adding users to roles fails - c#

I have been working on a website for some time now.
I am using the membership, role and profile providers which are working correctly.
I have a standard createuserwizard control where a user can register. When a user registers, I want to add him to a certain role like this:
Roles.AddUserToRole(Profile.UserName, "Member");
I do this through the userCreated event trigger.
There's also a adminpage where an admin should be able to change the role of a user, I did that like this:
DropdownList ddl = ((DropDownList)sender);
String usr = ddl.enter code here
if (Roles.IsUserInRole(usr, "Member")) {
Roles.RemoveUserFromRole(usr, "Member");
}
if (Roles.IsUserInRole(usr, "Visitor")) {
...
switch (ddl.selectedIndex)
case 0:
Roles.AddUserToRole(usr, "Admin");
case 1:
...
This doesn't work either. If I go to the database itself, the user wasn't added to the aspnet_UserInRoles.
Extra details:
When I create a user, he can see the adminpages, which is not intended. Security trimming is working correctly, when I add the user manually to the aspnet_UsersInRoles table I can't reach the memberpages anymore as intended.
The newly created user isn't added to any role, although he can see all pages he shouldn't be able to see. This is freaking me out!

Alright, I fixed the issue that it wouldn't assign the role after registering.
You'd think that userCreated is called after the user has been logged in, but it isn't.
Profile.UserName results in an empty string!
I'm still having problems with the adminpage though... I get the username value from the tooltip of the dropdownlist. By hovering over the ddl I can visually verify that the username is indeed in the tooltip attribute.
Assuming that the same problem exists here -> the usr (username) string is empty. Why can't I get the value?

Related

MVC 5 - Roles - IsUserInRole and Adding user to role

In MVC4 i used Roles.IsUserInRole to check if a given user is in some role. However, with MVC5 i can't do it anymore...
At first, it asked me to enable RoleManager at the web.config but then i discovered that microsoft moved away from Web.Security to Microsoft.AspNet.Identity.
My question now is, with Microsoft.AspNet.Identity how do i do an action similar to Roles.IsUserInRole?
And/or create a relation between the Role and the User.
By the way, i'm still trying to understand the new authentication methods (ClaimsIdentity?).
You should read http://typecastexception.com/post/2014/04/20/ASPNET-MVC-and-Identity-20-Understanding-the-Basics.aspx for the basics of Identity 2.0!
There's also a complete demo project to get you started:
https://github.com/TypecastException/AspNet-Identity-2-With-Integer-Keys
If you take this as the basis for your Identity foundation you'll end up with something like this:
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
const string name = "YourUsername"
const string roleName = "Admin";
var user = userManager.FindByName(name);
//check for user roles
var rolesForUser = userManager.GetRoles(user.Id);
//if user is not in role, add him to it
if (!rolesForUser.Contains(role.Name))
{
userManager.AddToRole(user.Id, role.Name);
}
The post above was really helpful (Thanks Serv, would vote up if my reputation allowed me to). It helped me solve an issue I was having with a few minor changes to fit what I was trying to achieve. My particular problem was that I wanted to check in an MVC view if the current user was in a given role group. I also found that Roles.IsUserInRole was no longer working.
If you are doing this in a view, but using ASP.NET identity 2.0 instead of the simple membership provider offered by previous MVC versions, the following might be helpful as a 1-line solution:
bool isAdmin = HttpContext.Current.User.IsInRole("Admin");
You may then combine it with HTML to selectively show menu items (which is what I've been using it for) with something like this:
#if (isAdmin)
{
<li>#Html.ActionLink("Users", "List", "Account")</li>
}
This allows me to prevent access to the user management hyperlinks where the user is not a member of the 'Admin' role.

other user's profile not populating

I've got a weird issue going on. I'm calling the profile for another user (not the currently authenticated user) and trying to access a value.
var profile = System.Web.Profile.ProfileBase.Create(username, true);
if (profile.PropertyValues["x"] != null)
ddlList.SelectedValue = profile.PropertyValues["x"].PropertyValue.ToString();
The value 'x' does exist for the user, but it's returning null. If I step through the code, and actually view the profile values before the if statement, then it works as expected. So I have to explicitly step through the code and view the value for the app to actually acknowledge it.

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

Set proxy user in a GenericPrincipal, while keeping the old identity, using MVC

I have a site where I allow some users to proxy in as an other user. When they do, they should see the entire site as if they where the user they proxy in as. I do this by changing the current user object
internal static void SetProxyUser(int userID)
{
HttpContext.Current.User = GetGenericPrincipal(userID);
}
This code works fine for me.
On the site, to proxy in, the user selects a value in a dropdown that I render in my _layout file as such, so that it appears on all pages.
#Html.Action("SetProxyUsers", "Home")
The SetProxyUsers view looks like this:
#using (#Html.BeginForm("SetProxyUsers", "Home")) {
#Html.DropDownList("ddlProxyUser", (SelectList)ViewBag.ProxyUsers_SelectList, new { onchange = "this.form.submit();" })
}
The controller actions for this looks like this
[HttpGet]
public ActionResult SetProxyUsers()
{
ViewBag.ProxyUsers_SelectList = GetAvailableProxyUsers(originalUserID);
return PartialView();
}
[HttpPost]
public ActionResult SetProxyUsers(FormCollection formCollection)
{
int id = int.Parse(formCollection["ddlProxyUser"]);
RolesHelper.SetProxyUser(id);
ViewBag.ProxyUsers_SelectList = GetAvailableProxyUsers(originalUserID);
return Redirect(Request.UrlReferrer.ToString());
}
All this works (except for the originalUserID variable, which I put in here to symbolize what I want done next.
My problem is that the values in the dropdown list are based on the logged in user. So, when I change user using the proxy, I also change the values in the proxy dropdown list (to either disappear if the "new" user isn't allowed to proxy, or to show the "new" user's list of available proxy users).
I need to have this selectlist stay unchanged. How do I go about storing the id of the original user? I could store it in a session variable, but I don't want to mess with potential time out issues, so that's a last resort.
Please help, and let me know if there is anything unclear with the question.
Update
I didn't realize that the HttpContext is set for each post. I haven't really worked with this kind of stuff before and for some reason assumed I was setting the values for the entire session (stupid, I know). However, I'm using windows authentication. How can I change the user on a more permanent basis (as long as the browser is open)? I assume I can't use FormAuthentication cookies since I'm using windows as my authentication mode, right?
Instead of faking the authentication, why not make it real? On a site that I work on we let admins impersonate other users by setting the authentication cookie for the user to be impersonated. Then the original user id is stored in session so if they ever log out from the impersonated users account, they are actually automatically logged back in to their original account.
Edit:
Here's a code sample of how I do impersonation:
[Authorize] //I use a custom authorize attribute; just make sure this is secured to only certain users.
public ActionResult Impersonate(string email) {
var user = YourMembershipProvider.GetUser(email);
if (user != null) {
//Store the currently logged in username in session so they can be logged back in if they log out from impersonating the user.
UserService.SetImpersonateCache(WebsiteUser.Email, user.Email);
FormsAuthentication.SetAuthCookie(user.Email, false);
}
return new RedirectResult("~/");
}
Simple as that! It's been working great. The only tricky piece is storing the session data (which certainly isn't required, it was just a nice feature to offer to my users so they wouldn't have to log back in as themselves all the time). The session key that I am using is:
string.Format("Impersonation.{0}", username)
Where username is the name of the user being impersonated (the value for that session key is the username of the original/admin user). This is important because then when the log out occurs I can say, "Hey, are there any impersonation keys for you? Because if so, I am going to log you in as that user stored in session. If not, I'll just log you out".
Here's an example of the LogOff method:
[Authorize]
public ActionResult LogOff() {
//Get from session the name of the original user that was logged in and started impersonating the current user.
var originalLoggedInUser = UserService.GetImpersonateCache(WebsiteUser.Email);
if (string.IsNullOrEmpty(originalLoggedInUser)) {
FormsAuthentication.SignOut();
} else {
FormsAuthentication.SetAuthCookie(originalLoggedInUser, false);
}
return RedirectToAction("Index", "Home");
}
I used the mvc example in the comments on this article http://www.codeproject.com/Articles/43724/ASP-NET-Forms-authentication-user-impersonation to
It uses FormsAuthentication.SetAuthCookie() to just change the current authorized cookie and also store the impersonated user identity in a cookie. This way it can easily re-authenticate you back to your original user.
I got it working very quickly. Use it to allow admin to login as anyone else.

How can I set up ASP.NET login to allow the UserName or UserId to be retrieved later on in the session?

I'm trying to create a login system for my website, I've created a custom login.ascx and when the user clicks [ Login ] a div pops up with the contents of login.ascx.
Then after the user enters their credentials, they click on the Login button. They get validated and logged in using this code in the login click function:
if( Membership.ValidateUser( userName.Text, password.Text ) )
{
//Here is where I'm not sure what to do
}
else
{
LoginError.Visible = true;
}
So in the section where I'm not sure what to do, I would like the user to get logged in (Not sure if that means creating an authentication ticket or whatnot). What does is the next step to actually log the user in, I don't want them to get redirected anywhere since they are on the correct page already.
I would also like to be able to retrieve their user name or user id later on for use in my web services. So, for this should I do a Session.Add to create a new session value or is there some other way of storing the data that is preferred?
For authenticating the user,
FormsAuthenatication.SetAuthCookie(username, false/*true if you want to remember the user's login*/);
This logs the user in. You can later use
Page.User.Identity.Name
to retrieve username of the current user and
Page.User.Identity.IsAuthenticated
to check if the user is logged in.
There's no need to store it in Session. Just use:
FormsAuthentication.SetAuthCookie
to send an authentication ticket to the client. Then use HttpContext.Current.User.Identity to retrieve it later.
I find using the membership provider is useful, I would recommend it
Scott Guthrie posted great blog on this
http://weblogs.asp.net/scottgu/archive/2006/05/07/ASP.NET-2.0-Membership-and-Roles-Tutorial-Series.aspx

Categories