I'm using roleclaims in my application that's all set up and working, but I want to do something like this
result = await User.HasRoleClaim("ClaimName")
where this result is a boolean true if any role the user is in has that claim and false if no role they are in does not have that claim.
Am I missing something because I can't see a response to this anywhere, not even on the Microsoft pages so I'm guessing it can't be done. That functionality doesn't seem to exist. Using rolemanager and/or usermanager I can get/set roles, claims and even roleclaims, but I can't find a way to get user.roleclaims (or similar).
I can construct my own methods to do this, but just wanted to ask/check if what I want to do is possible before I go off down a rabbit hole
Any help much appreciated, thanks.
So I have multiple websites running off one code base (asp.net standard MVC). I'm using the built in ASPNet.Identity methods for users to register/log in (using ApplicationSignInManager, ApplicationUserManager).
Currently, all websites are using a single database to store user information. This is causing a couple of issues:
When user A registers on website A, they are now able to log into website B with the same details. As far as they are aware, they did not register on website B. Not good!
If I constrain user A to only access website A, if that user then tried to register on website B, they get the 'email address already in use' error. Also not good!
I've tried separating the databases, one per site, to get around this issue but I don't know how to dynamically change the DBContext assigned to the ApplicationSignInManager and ApplicationUserManager in my controller.
For example, when a user comes to website A, I grab the connection string for website A and perform login/register actions. I need the domain name to work out which connection string to load, which I can't access until after startup.cs code has run, configuring my manager instances.
I figure other people must have done this. Ideally I need to dynamically change the DBContext AFTER Startup.cs has run. Failing that, I need a nice approach to storing multiple identical email addresses in the same DB
Thanks
If you have a flag somewhere which website the current context is for, i'd say easiest to achieve that is to do two things:
extend the IdentityUser with a Website property, something simple either just an int WebsiteId or a String.
extend the AccountController to use that property wherever needed, I think you'd need to modify "Register" and all "Login" functions to verify the website the account is for.
I managed to find a solution. It's not the most elegant but it solves the issue until I can figure out how to dynamically change the DB Context used during login/register
In IdentityConfig.cs I switched 'RequireUniqueEmail' to false:
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
Then when a user registers, I take the email address, make it unique to the website they registered on, and store it in the UserName field (I don't use the UserName for anything). When they log in, I make the same alteration to the entered email address before attempting login.
If this user registers on a different website, the username will be different even though the email is identical. Not perfect, but it works.
E.g.
string uniqueCode = "Website_Specific_String";
var user = new ApplicationUser { uniqueCode + model.Email, Email = model.Email};
var result = await UserManager.CreateAsync(user, model.Password);
and the login
var user = await UserManager.FindByNameAsync(uniqueCode + model.Email);
Still open to better ideas. Thanks
currently dealing with an interesting problem. I am building a website with three different user roles. When logged in, the MVC partial view shows navigation options for the users. I want to show different options depending on the user's role. In previous websites, I have used the following code to determine a role:
#if (Roles.IsUserInRole("intern"))
{
<li>#Html.ActionLink("Log Time", "Index", "Time")</li>
}
Unfortunately, when I attempted this in my current code, I got the message:
The Role Manager feature has not been enabled.
So apparently in the new MVC they disable the role manager by default and have a new way of doing it. No biggie. Searching the issue suggested that I enable the feature in web.config. I followed several instructions on how to do that (I promise I can google search) but it seems to mess with my SQL Server connection string, giving me errors that indicate it's trying to log in to a local db that doesn't exist rather than my Azure SQL Server. I've played around for a while and I don't know why this is the case.
Anyway, long story short, rather than work around and re-enable a vestigial Identity feature, how are you supposed to accomplish this in the new MVC? I can get the roles fine controller side with user manager, but I can't use that in a view. Similarly a Viewbag full of roles can't work because this is navigation on every page.
I appreciate all the help in advance, thanks everyone!
Just found the answer, I'll leave this up for other people dealing with this. The correct way to do this is:
#if (User.IsInRole("intern"))
This makes sense since MVC is moving away from Role based objects and towards User based objects.
I think it's not really a good idea to ask for the user's role all the time, too many requests are made.
It would be better to ask once and save it on a variable in Razor. Then just check that variable whenever you need it.
By the way, if the roles are different, you don't even want to ask if the user is in that role rather than another one. Rather get the list of roles in a list and check if the role indicated is in the list.
Example (I'm not sure it will compile, look a the idea):
#using Microsoft.AspNetCore.Identity
#using Microsoft.AspNetCore.Mvc.Localization
#inject UserManager<ApplicationUser> UserManager
#{
ApplicationUser currentUser = await UserManager.GetUserAsync(User);
var roles = await UserManager.GetRolesAsync(currentUser);
bool isIntern = roles.Contains("intern");
bool isExtern = roles.Contains("extern");
bool isFoo = roles.Contains("foo");
...
}
then, further on
#if (isIntern)
{
<li>#Html.ActionLink("Log Time", "Index", "Time")</li>
}
else if (isExtern)
{
...
}
You can control the role of the user as many times as you want without having to make other requests and it's all much more readable.
I am struggling a little bit to completely understand what is the correct way to implement a windows authentication and role based authorization scheme into an MVC4 application. When the user accesses the (intranet) website I currently have the following method check the user name against the against a database table
List<string> permissionList =
PermissionBo.GetUserPermissionsList(PermissionBo.ParseUserName(User.Identity.Name));
Permissions permissions = new Permissions(permissionList);
Then the following if state adds a role to a user object:
if (permissions.IsAdmin)
{
if(!Roles.RoleExists("UtilitiesToolAdmin"))
{
Roles.CreateRole("UtilitiesToolAdmin");
}
if(!Roles.IsUserInRole(User.Identity.Name, "UtilitiesToolAdmin"))
{
Roles.AddUsersToRole(new string[] { User.Identity.Name }, "UtilitiesToolAdmin");
}
}
I feel like this may be an incorrect way to go about implementing this, but I am not sure where I am going wrong. Is this sufficient to begin using the authorize attribute like so:
[Authorize(Roles="UtilitiesToolAdmin")]
public static void Foo()
{
return "Bar"
}
If not what am I missing?
If all you are doing is simple role checking, a custom Role Provider might be a bit of an overkill (Role Providers also provide facilities for managing the roles themselves). What you will end up with is a class full of
throw new NotImplementedException();
Instead, consider creating a custom user principal. The IPrincipal interface defines an IsInRole method that returns a bool. This is where you would put your custom role checks. The advantage of the custom user principal is that now all of the built in ASP.NET role-checking goodies should "just work" as long as you replace the default user principal object with your custom one early enough in the lifecycle.
This SO answer has one of the best examples I've seen of using a custom user principal with an MVC application.
In a forms model, I used to get the current logged-in user by:
Page.CurrentUser
How do I get the current user inside a controller class in ASP.NET MVC?
If you need to get the user from within the controller, use the User property of Controller. If you need it from the view, I would populate what you specifically need in the ViewData, or you could just call User as I think it's a property of ViewPage.
I found that User works, that is, User.Identity.Name or User.IsInRole("Administrator").
Try HttpContext.Current.User.
Public Shared Property Current() As
System.Web.HttpContext
Member of System.Web.HttpContext
Summary:
Gets or sets the System.Web.HttpContext object for the current HTTP request.
Return Values:
The System.Web.HttpContext for the current
HTTP request
You can get the name of the user in ASP.NET MVC4 like this:
System.Web.HttpContext.Current.User.Identity.Name
I realize this is really old, but I'm just getting started with ASP.NET MVC, so I thought I'd stick my two cents in:
Request.IsAuthenticated tells you if the user is authenticated.
Page.User.Identity gives you the identity of the logged-in user.
I use:
Membership.GetUser().UserName
I am not sure this will work in ASP.NET MVC, but it's worth a shot :)
getting logged in username: System.Web.HttpContext.Current.User.Identity.Name
UserName with:
User.Identity.Name
But if you need to get just the ID, you can use:
using Microsoft.AspNet.Identity;
So, you can get directly the User ID:
User.Identity.GetUserId();
In order to reference a user ID created using simple authentication built into ASP.NET MVC 4 in a controller for filtering purposes (which is helpful if you are using database first and Entity Framework 5 to generate code-first bindings and your tables are structured so that a foreign key to the userID is used), you can use
WebSecurity.CurrentUserId
once you add a using statement
using System.Web.Security;
We can use following code to get the current logged in User in ASP.Net MVC:
var user= System.Web.HttpContext.Current.User.Identity.GetUserName();
Also
var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; //will give 'Domain//UserName'
Environment.UserName - Will Display format : 'Username'
This page could be what you looking for:
Using Page.User.Identity.Name in MVC3
You just need User.Identity.Name.
Use System.Security.Principal.WindowsIdentity.GetCurrent().Name.
This will get the current logged-in Windows user.
For what it's worth, in ASP.NET MVC 3 you can just use User which returns the user for the current request.
If you are inside your login page, in LoginUser_LoggedIn event for instance, Current.User.Identity.Name will return an empty value, so you have to use yourLoginControlName.UserName property.
MembershipUser u = Membership.GetUser(LoginUser.UserName);
You can use following code:
Request.LogonUserIdentity.Name;
IPrincipal currentUser = HttpContext.Current.User;
bool writeEnable = currentUser.IsInRole("Administrator") ||
...
currentUser.IsInRole("Operator");
var ticket = FormsAuthentication.Decrypt(
HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
if (ticket.Expired)
{
throw new InvalidOperationException("Ticket expired.");
}
IPrincipal user = (System.Security.Principal.IPrincipal) new RolePrincipal(new FormsIdentity(ticket));
If you happen to be working in Active Directory on an intranet, here are some tips:
(Windows Server 2012)
Running anything that talks to AD on a web server requires a bunch of changes and patience. Since when running on a web server vs. local IIS/IIS Express it runs in the AppPool's identity so, you have to set it up to impersonate whoever hits the site.
How to get the current logged-in user in an active directory when your ASP.NET MVC application is running on a web server inside the network:
// Find currently logged in user
UserPrincipal adUser = null;
using (HostingEnvironment.Impersonate())
{
var userContext = System.Web.HttpContext.Current.User.Identity;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, ConfigurationManager.AppSettings["AllowedDomain"], null,
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
adUser = UserPrincipal.FindByIdentity(ctx, userContext.Name);
}
//Then work with 'adUser' from here...
You must wrap any calls having to do with 'active directory context' in the following so it's acting as the hosting environment to get the AD information:
using (HostingEnvironment.Impersonate()){ ... }
You must also have impersonate set to true in your web.config:
<system.web>
<identity impersonate="true" />
You must have Windows authentication on in web.config:
<authentication mode="Windows" />
In Asp.net Mvc Identity 2,You can get the current user name by:
var username = System.Web.HttpContext.Current.User.Identity.Name;
In the IIS Manager, under Authentication, disable:
1) Anonymous Authentication
2) Forms Authentication
Then add the following to your controller, to handle testing versus server deployment:
string sUserName = null;
string url = Request.Url.ToString();
if (url.Contains("localhost"))
sUserName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
else
sUserName = User.Identity.Name;
If any one still reading this then, to access in cshtml file I used in following way.
<li>Hello #User.Identity.Name</li>