ASP.net MVC - Get currently logged user role in view - c#

I know that there are a lot of topics about this issue but I already tried several solutions and cannot make it work.
So, I am trying to verify the currently logged user role in my view. As referred in the major part of topics about this in StackOverflow, I just have to do:
#User.IsInRole("Admin")
Unfortunately this always returns false even with the "Role" column, in the AspNetUsers table, of the current logged user is populated with "Admin".
I also tried below approach but it says that "UserManager does not exist in current context".
<p>#UserManager.GetRoles(userId)</p>
One of my suspects is that I am not correctly setting the role for the user upon registration. My AspNetRoles table is correctly populated but AspNetUserRoles table is empty.
How can I troubleshoot this to find what is wrong with my application so I can use #User.IsInRole(...) instruction?
Thanks in advance for any help.

This worked perfectly fine for me.
Just make sure you've seeded the roles in the database and also the registered user is assigned a role and this should work fine.
{
<a asp-action="StudentDashboard" asp-controller="Home">Dashboard</a>
}
else
if (User.IsInRole("College"))
{
<a asp-action="CollegeDashboard" asp-controller="Home">Dashboard</a>
}
else
if (User.IsInRole("Manager"))
{
<a asp-action="AdminDashboard" asp-controller="Home">Dashboard</a>
}
else
if (User.IsInRole("Admin"))
{
<a asp-action="AdminDashboard" asp-controller="Home">Dashboard</a>
}```

i think you did not write or you write but in the wrong way this below code on global.asax :
protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs e)
{
if (FormsAuthentication.CookiesSupported == true)
{
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
try
{
//let us take out the username now
string Email = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
string roles = string.Empty;
using (DatabaseContext entities = new DatabaseContext())
{
var user = entities.TblUsers.Where(u => u.Email == Email).FirstOrDefault().IDRole;
//here
roles = entities.TblRoles.Where(x => x.IDRole == user).FirstOrDefault().RoleName;
}
//let us extract the roles from our own custom cookie
// and here
//Let us set the Pricipal with our user specific details
e.User = new System.Security.Principal.GenericPrincipal(
new System.Security.Principal.GenericIdentity(Email, "Forms"), roles.Split(';'));
}
catch
{
//somehting went wrong
}
}
}
}

Have you tried adding below at the top of the view page:
#using Microsoft.AspNet.Identity
Alternatively:
#if(Roles.IsUserInRole(User.Identity.GetUserName(), "Admin"))

Related

Role user and admin not work

I have i little problem in my roles, if i made login need show my name in bar menu, this work fine if i not use roles, but when i try use my roles check not work anymore. sorry my bad english
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
protected void Application_AuthenticateRequest()
{
// Check if user is logged in
if (User == null) { return; }
// Get username
string username = Context.User.Identity.Name;
// Declare array of roles
string[] roles = null;
using (Db db = new Db())
{
// Populate roles
UsuarioDTO dto = db.Usuario.FirstOrDefault(x => x.Login == username);
roles = db.RegraUsuario.Where(x => x.UsuarioId == dto.Id).Select(x => x.Regra.Nome).ToArray();
}
// Build IPrincipal object
IIdentity userIdentity = new GenericIdentity(username);
IPrincipal newUserObj = new GenericPrincipal(userIdentity, roles);
// Update Context.User
Context.User = newUserObj;
}
And in my Loyout.html
<ul class="nav navbar-nav">
#Html.Action("PaginaMenupartial", "Paginas")
#if(Request.IsAuthenticated)
{
//if user is loged show logout
<li>Sair</li>
}
else
{
if (ViewBag.Tile == "Login")
{
<li class="active">Entrar</li>
}
else
{ //if user is not loged show login
<li>Entrar</li>
}
}
// in this line below is my problem
#if (Request.IsAuthenticated && User.IsInRole("User"))
{
<li>#Html.Action("UsuarioNavPartial","Conta", new { area=""})</li>
}
</ul>
enter image description here
if i remove and leave only #if (Request.IsAuthenticated ) then work.
enter image description here
But i add #if (Request.IsAuthenticated && User.IsInRole("User")) not work, i check in all code and seems fine, some one can help me?
Make sure that the exact role is assigned to this specific user in the Database.
It has to be written exactly the same way.
I would also like to suggest, that you might want to use ENUMs or CONSTANTS as role names / symbols.
This way, a typo will not break a specific page (in case there is a typo again).
That wil ensure, that the role name is accessible and the same across the entire project.
I am assuming, that you will want to change roles later on or add / update.
This will also help with future development.

Return user details after they have logged in

the code below works ok, just one issue, the code confirms if user logged in is Admin or not i.e. the code checks if the user name is within the AspNetUser table and returns a Boolean true or false.
But I also need the user GarageID to be returned, the GarageID field is held within the AspNetUser table any ideas how to do this?
private bool IsUserAdmin()
{
System.Security.Principal.WindowsIdentity identity = Context.Request.LogonUserIdentity;
//Debug.WriteLine(identity.Name);
string loginName = identity.Name;
//Debug.WriteLine(loginName);
TyrescannerWebApp.IdentityModel.tyrescannerdatabaseEntities dbcontext = new TyrescannerWebApp.IdentityModel.tyrescannerdatabaseEntities();
return content.AdminUsers.Any(a => a.LoginName == loginName);
}
You should use the role provider to determine if the user is in the current role.
if (System.Web.Security.Roles.IsUserInRole(loginName, "Admin"))
{
//Do something
}
else
{
//Display unauthorized message
}

Users able to see others' details. FirstOrDefault returning the wrong record? Or caching issue? Help! :)

Users of my site have experienced some strange behaviour yesterday (first time I've seen this issue), and unfortunately I don't have much in the way of error logs to try to figure out what's going on. The site had a higher-than-normal number of people online at once, albeit not a large number in the grand scheme of things (maybe 50 to 100 users all trying to perform similar functions). I can't recreate the issue in my development environment, haven't seen it before, and don't really know why it is happening.
The crux of the problem is that users can register or log on successfully, but a small number of them could see other users' data.
The site is ASP.NET MVC 3.
Users are logging on and I set an authentication cookie - here's the LogOn action:
[HttpPost]
public ActionResult LogOn(AccountLogOnViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (!Membership.ValidateUser(model.UserName, model.Password))
{
ModelState.AddModelError("login-message", "Incorrect username or password");
}
}
if (ModelState.IsValid)
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
Session.Remove("MenuItems");
return Redirect(returnUrl ?? Url.Action("Index", "Home"));
}
else
{
model.ReturnUrl = returnUrl;
return View(model);
}
}
AccountLogOnViewModel is a simple object with two string properties, UserName and Password.
From what I can gather, this is fine - if you log in as NickW then doing something like User.Identity.Name correctly gives you "NickW" (when users were seeing other users' data, they reported that that "Welcome, NickW" text on screen was showing them the correct value - this is written out using User.Identity.Name)
The site also uses a custom membership provider. It overrides the ValidateLogin method, and the GetUser method. ValidateLogin appears to be working just fine so I'm not concerned about it.
The overridden GetUser method is as follows:
public override MembershipUser GetUser(string username, bool userIsOnline)
{
User user = _userRepository.Users.FirstOrDefault(u => u.UserName == username);
MembershipUser membershipUser = null;
if (user == null)
return membershipUser;
membershipUser = new MembershipUser(this.Name,
user.UserName,
user.Id,
user.Email,
null,
user.Comments,
user.IsActivated,
user.IsLockedOut,
user.CreatedDate,
user.LastLoginDate,
user.LastLoginDate,
user.LastModifiedDate,
Convert.ToDateTime(user.LastLockedOutDate));
return membershipUser;
}
So I'm attempting to retrieve a User object from my database, and using that to create a new MembershipUser object. My database User table has additional columns on top of those required by the membership provider - e.g. name, address, phone number etc.
At various points in the rest of the website (for example if you go to the Profile page), I retrieve a user object from the database and use it to populate the screen. The line I use to retrieve the User object is:
User user = userRepository.Users.FirstOrDefault(u => u.UserName == Membership.GetUser().UserName);
Here is a cut down version of the userRepository (i.e. just removing unrelated code).
public class SqlUserRepository : IUserRepository
{
private Table<User> usersTable;
private string _connectionString;
public SqlUserRepository(string connectionString)
{
_connectionString = connectionString;
usersTable = (new DataContext(connectionString)).GetTable<User>();
}
public IQueryable<User> Users
{
get { return usersTable; }
}
public void CreateUser(AccountRegisterViewModel user)
{
User newUser = new User();
newUser.UserName = user.UserName;
newUser.Salutation = user.Salutation;
newUser.PhoneNumber = user.PhoneNumber;
newUser.SecondaryPhoneNumber = user.SecondaryPhoneNumber;
newUser.FirstName = user.FirstName;
newUser.LastName = user.LastName;
newUser.PasswordSalt = CreateSalt();
newUser.Password = CreatePasswordHash(user.Password, newUser.PasswordSalt);
newUser.Email = user.Email;
newUser.CreatedDate = DateTime.UtcNow;
newUser.Comments = "Created from web registration";
newUser.LastModifiedDate = DateTime.UtcNow;
newUser.LastLoginDate = DateTime.UtcNow;
newUser.IsActivated = true;
newUser.IsLockedOut = false;
newUser.MayContact = user.MayContact;
usersTable.InsertOnSubmit(newUser);
usersTable.Context.SubmitChanges();
}
}
So it appears to me as if the auth cookie I'm setting is fine, but either:
When I first go in to the membership provider's GetUser() method, it retrieves the wrong record from the database and therefore sets up a MembershipUser object with the wrong username; subsequently when I look in the database for "this" user I'm actually looking for the wrong username.
Or: Intermittently when I do userRepository.FirstOrDefault(x => x.UserName == Membership.GetUser().Name) it retrieves the wrong record.
Or: something else is going wrong that I haven't thought of.
As I say, this seems to be a problem when the site was under load, so I'm wondering if it's some sort of caching issue somewhere? But I really don't know.
One thought I had was to change the way I retrieve the user in case the problem lies with the membership provider, and use this instead:
userRepository.FirstOrDefault(x => x.UserName == User.Identity.Name)
// or HttpContext.Current.User.Identity.Name if not within a controller
But really I'm not even sure what's going on so have no idea whether this will resolve the issue. Could it be a caching problem somewhere? It appears (but I can't be 100% certain) that when user A could see user B's details, it was always the case that user B was also active in the system (or had been within the previous 20 minutes).
I know it's a long shot, but does anyone have any idea how this could happen? Obviously it's a major concern and needs to be fixed urgently, but without knowing why it's happening I can't fix it!
Thanks in advance for any help,
Nick
Some things to consider:
Instead of using FirstOrDefault, use SingleOrDefault. FirstOrDefault assumes there will be more than 1 record of data matching your query. Since you are querying by username, there should only be 1 matching row, correct? In that case, use SingleOrDefault instead. When there are multiple rows that match the query, SingleOrDefault will throw an exception.
To get the username, instead of invoking Membership.GetUser().UserName, use User.Identity.Name. The User property on an MVC controller references an IPrincipal that should match the user's forms authentication cookie value. Since you have a custom membership provider, this should help eliminate its methods as a source of the problem.
There could be a caching issue if you have caching set up for the MVC project. Do you use the OutputCacheAttribute ([OutputCache]) on any controllers or action methods? Do you have it set up as a global filter in the global.asax file? Or do you think there may be some kind of SQL-based caching going on?
Looking at your overridden GetUser method, I see it should take 2 parameters: string username and bool isOnline. However, when you invoke it with Membership.GetUser().UserName, you are passing no parameters. Do you have another overridden overload of this method that also takes no parameters? What does it look like? Does it use System.Threading.CurrentPrincipal.Identity.Name to sniff out the current username when none is passed?

Login Form trouble

I wrote the following code to log in to my application using C# and LINQ. It connected to a SQL service oriented database that I have created in Visual Studio. The problem that I am having is one that I do not understand and am hoping that someone can help me about here. I have created two message boxed to try to see the output of my code buy I am not getting anything from it.
If anyone could help that would be great!
public bool UserLogin(string User, string Pass)
{
var Database = new ExampleDataSet();
var query = from Employee in Database.Employee
where (Employee.EmployeeID.ToString() == Employee.ToLower() && Employee.Password == Pass)
select Employee;
if (query.Count() != 0)
{
return true;
MessageBox.Show("You are logged in");
}
return false;
MessageBox.Show("You are not logged in");
}
private void cmdLogin_Click(object sender, EventArgs e)
{
string User = (txtUser.Text);
string Pass = (txtPass.Text);
UserLogin(User, Pass);
}
From the code you wrote, it seems that the problem is that you compare the string representation of an Employee with its EmployeeId property Employee.EmployeeID.ToString() == Employee.ToLower(). This line will always return false unless you override ToString() method of Employee class to return the property EmployeeId (which I presume you didn't).
Try this instead (assuming that parameter User contains the name of the user):
using(var dataSet = new ExampleDataSet())
{
var loggedIn = dataSet.Employee.Any(e=>e.UserName == User && e.Password == Pass);
var message = loggedIn ? "You are logged in" : "You are not logged in";
MessageBox.Show(message);
return loggedIn;
}
When you return, the function execution will stop, because it's done and will return the value to what it was called from. So anything after your return won't happen. Try putting MessageBox.Show before return:
MessageBox.Show("You are logged in");
return true;
And the same for the false version.
The Message boxes wont show as they are after the return statements - move your message boxes to before the returns to see them.
I have made changes in your code....Your if-else part is not valid......You are comparign employee.ID with employee itself..Try out with following code.....
public bool UserLogin(string User, string Pass)
{
var Database = new ExampleDataSet();
var query = from Employee in Database.Employee
where (Employee.EmployeeID.ToString().ToLower().Equals(User.ToLower())&& Employee.Password.ToString().ToLower().Equals(Pass.ToLower())
select Employee;
if (query.Count() != 0)
{
MessageBox.Show("You are logged in");
return true;
}
else
{
MessageBox.Show("You are not logged in");
return false;
}
}
private void cmdLogin_Click(object sender, EventArgs e)
{
string User = (txtUser.Text);
string Pass = (txtPass.Text);
UserLogin(User, Pass);
}
If you mean user = employeeId
Employee.EmployeeID.ToString() == user.ToLower()
if not :
Employee.EmployeeName.ToLower() == user.ToLower()
About the message box, you should know any statement after return will not be executed
Writing your own user authentication is not recommended. It is very difficult to do it right, and in most cases you can use one that is already provided by Windows or the dot net framework.
For example, your application should not store the users passwords in plain text. If your application or database is compromised, the attacker will not only gain full access to your application, but a list of passwords which it is likely the users have also used elsewhere.
If you need to store the users credentials, they should first be salted, and then hashed with a secure hashing algorithm. This prevents anyone who gains access to the database from learning users passwords.
To verify the password, you look up the salt in the database, append the password to it, hash the result, and then compare that with the stored value. If they are the same, then the user entered the correct password.
If you are writing an application that will be used in a windows domain, you can use Active Directory groups to control access to your application. On the simplest level, you can store your application in a folder which is only accessible by the authorised users.
You can also use groups to control access to the database the application connects to. If you are using SQL server, each group should be placed in a SQL database role, which is in turn granted the necessary permissions for that role.
From within the application, you can look up the users group membership, and use it to determine which forms / menu options to show, or exit the application if they are not authorised.
If you are writing an ASP.Net application, consider using MemberShip and Roles which are built in to the framework.

How to check what the current users role is

How do I check in C# what the current users role is, and print it to the screen.
Thanks!
You can use Roles.GetRolesForUser() method to get all the rols user belong to . use it like this;
string[] rolesuserbelongto = Roles.GetRolesForUser();
you will have all roles in string array.
you can even pass a UserName as a parameter to get the roles for that particular User like this:
string[] rolesuserbelongto = Roles.GetRolesForUser("Shekhar_Pro");
The most general method is to get an IPrinciple and then call IsInRole() on it. How you get the Principle denpends on your runtime environment. This example works well for apps running under the user's account.
Example:
static void PrintIsInAdministrators()
{
// There are many ways to get a principle... this is one.
System.Security.Principal.IPrincipal principle = System.Threading.Thread.CurrentPrincipal;
bool isInRole = principle.IsInRole("MyDomain\\MyRole");
Console.WriteLine("I {0} an Admin", isInRole ? "am" : "am not");
}
Roles.GetRolesForUser(); gave me the error The Role Manager feature has not been enabled.
If you are using ASP.NET Identity UserManager you can get it like this:
var userManager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roles = userManager.GetRoles(User.Identity.GetUserId());
If you have changed key for user from Guid to Int for example use this code:
var roles = userManager.GetRoles(User.Identity.GetUserId<int>());
string[] userroles = Roles.GetRolesForUser(Page.User.Identity.Name);
foreach(var role in userroles)
{
Response.Write(role);
}
This is what you are looking for:
#if (Request.IsAuthenticated)
{
if (User.IsInRole("Admin"))
{
<h1> I only show this text to admin users </h1>
}
}
Note: You can check the roles defined in your AccountController.cs file, if you have one implemented.
You can use user manager for that purpose:
var userRoles = await _userManager.GetRolesAsync(user);
Not entirely sure of you question.
You can do:
this.User.IsInRole();
//loop and check whether the user is in your role.
this would correspond to a page class, so you can write the above code only inside a page and this.User returns an IPrincipal.

Categories