ASP.NET MVC 5 : get login username not pc user name [duplicate] - asp.net-mvc

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>

Related

How to perform one time action on first login using ASP.NET MVC5 Windows Authentication

I am creating web application using ASP.NET MVC5 framework with 'windows authentication' - i.e. I am creating an intranet application authenticating users against active directory.
When new user is defined in company's active directory, I'd need to catch his first login and redirect him onto profile page, where user is prompted to fill some info.
I am able to catch user's first login by simple look into the database, if the user has here his own record in some table. If not, the user is here first time and I can create him such record.
Here comes the deal - after extensive searching through possibilities it seems the only "reasonable" way how to do it is via custom AuthenticationFilter - specifically to put the DB check logic into
OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
method.
The reason why I put "reasonable" into the quotes is that on one hand, this approach fits into the MVC philosophy - by which I mean that it is not some 'hack' approach.
On the other hand - since I am using windows authentication, there is effectively no Login action in any controller. User can type whatever 'www.mysite.com/controller/action' url and if not logged in, there is no redirect to login page, the windows security box just appears prompting for credentials. Which means that I have to register my custom authentication filter globally to cover all controller/action patterns. That would mean that the DB check would be performed each and every request - I don't like this. I am not sure how much performance hit this could make, but also it doesn't seem right from design point of view.
The last thing I've tried was to use my authentication filter to catch 'unauthenticated' users and redirect them to some 'Login' action - but here I found that the windows security box is appearing before even the authentication filter is fired, so technically my custom authentication filter never catches an unauthenticated user.
So my question is - is there a better approach how to step in the logging process with one time action? Or I can use what I have - i.e. globally registered authentication filter performing DB check every request ?
Thanks
Finally I have some working solution for this.
The problem:
MVC5 APS.NET intranet application using windows authentication. After successful login against active directory we want to find out if the user is here for the first time and if so, create him record in application database.
The solution:
Since I am at the end of the day interested only in authenticated and authorized users I've created a globally registered action filter i.e. filter which will be applied to every single controller/action combination after successful authentication/authorization.
Inside this filter I am checking if the current session has flag IsNewSession set to true. If so, I am performing that check against application DB. That way even if the action filter is invoked each request I am doing roundtrip into database only once - during user's first request.
The implementation:
public class DbCheckFilter : ActionFilterAttribute
{
private AppDbContext db = new AppDbContext();
//we are overriding OnActionExecuting method since this one
//is executed prior the controller action method itself
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//is this a new session
if (filterContext.HttpContext.Session.IsNewSession)
{
//we are storing users in db based on their active directory
//Guid - therefore we need to get 'UserPrincipal' object
//instead of 'WindowsPrincipal' provided by filterContext
using (var principalContext = new PrincipalContext(ContextType.Domain))
{
var principal = UserPrincipal.FindByIdentity(principalContext, filterContext.HttpContext.User.Identity.Name);
if (principal != null)
{
//finally we perform the DB check itself
if (!CreateUserInDbIfNew(principal.Guid.Value, principal.DisplayName))
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
else
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
base.OnActionExecuting(filterContext);
}
I believe this is what you're looking for. Your db check will only happen once at this point. You can add this method to your Global.asax like so, which works with Windows Auth once authorized...
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
// Do your check here
// Do something
}

Redirect Authorize attribute if it fails to another view in asp.net mvc

so I have a question about the [Authorize] tag. I am required a user to have the role of admin to visit a certain view. It works great and only allows an "admin" to go to it instead of the "user". But whenever the user visits it gives me this:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Login.cshtml
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
So my question is, when a user visits how can I redirect them to another view?
So this is my controller for index:
[Authorize(Users = "Admin")]
public ActionResult Index()
{
var user = db.User.Include(u => u.UserRole);
return View(user.ToList());
}
You can solve this in two ways:
Let the index action be accessible by anonymous user and based on the role call different functions.
Create your own custom Authorization attribute (you can find an example here).
Both the approaches are fine, with no distinct advantage/disadvantage over one and another, so you could choose any of them.
Hope this helps.

User.IsInRole doesn't work

I have ASP.NET MVC 4 application. I use Simple Membership Provider allowing to tick remember me checkbox under login form. If ticked, persitent cookie .ASPXAUTH is created which expires 100 days from login date. And everything works fine, apart of main menu of the application.
Some parts of the menu are available for admin users only. I use:
#if (User.IsInRole("Administrator")) { #Html.Partial("_MainMenuPartial") }
to lock them from being rendered for regular user. This approach works fine just after logging into the system. When I return after a while and persistent cookie is used to authenticate me, I do get logged in, but
#User.IsInRole("Administrator")
returns "False" so I can't see admin menu items. At the same time
#User.Identity.Name
returns proper login name and
#User.Identity.IsAuthenticated
returns "True", what proves that persistent cookie works fine. Why can't I access user roles even though user is authenticated by the system then?
I had a smilar issue. In my case the problem solved when i log off and log in again.
Problem using roles with MVC5
I found a solution. In my web.config:
<modules>
<remove name="FormsAuthenticationModule" />
<remove name="RoleManager" />
</modules>
I added remove name="RoleManager" line, and the new AspNet.Identity code took over allowing me to use User.IsInRole(..)
http://forums.asp.net/t/1952572.aspx?Problem+using+roles+with+MVC5
Old question, but there's some missing information here. I ran into the same issue, and there's one thing to keep in mind. If you test the user identity (like User.IsInRole("admin")) just after authenticate (without send the response to client), Identity framework has not populated this session info yet (or at least, I could not found the way to do that). This info you're requesting for, is populated at some point after your controller return. If you want (I.E.) to redirect to different views after login, depending on the user role, you'll have to use a custom authorization filter.
Have you tried adding
[InitializeSimpleMembership]
in the controller where you're doing the check?
I had a similar problem with IsUserInRole returning false. By placing a watch on it, I was able to overcome the problem by using the overload described below. Try it, put a break point where you're getting false, and see what happens.
#if (Roles.IsUserInRole(Model.UserName, "Administrator"))
I'm pretty sure you could also use User.Identity.Name as the first parameter.
If you are using latest Identity framework please see if you are using following
services.AddIdentity<IdentityUser,IdentityRole>()
.AddEntityFrameworkStores<WebUserContext>()
.AddDefaultTokenProviders();
If you are using AddDefaultIdentity Roles don't get populated.
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<WebUserContext>()
.AddDefaultTokenProviders();
I had a similar issue, seems like authentication module is not wired up completely with the SimpleMembershipProvider. To get around that problem, you can use a Role class to access needed information. For example to check if the use in role you can use the following:
Roles.GetRolesForUser("sergey").Contains("Developer")
And so other useful methods when working wit SimpleMembershipProvider roles:
Roles.RoleExists("Developer")
Roles.CreateRole("Developer");
Roles.AddUserToRole("sergey", "Developer");
The "EmailConfirmed" of this account probably still false, try to change it to true
None of these answers worked for me, but I did find the answer here: https://thinkthencode.wordpress.com/2016/04/24/azure-ad-using-app-roles-for-authorization/
The key was adding the following to Startup.Auth.cs:
TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = "roles"
}
If you're using IdentityManager by Brock Allen to create roles and assign them to users then you should read this article: https://github.com/IdentityManager/IdentityManager.AspNetIdentity/issues/3
You'll need to uncomment the following line:
this.RoleClaimType = System.Security.Claims.ClaimTypes.Role;
Now you'll realize that your user that used to be in roles is no longer in them, and you'll have to re add them. If you take a look at the AspNetUserClaims table, you'll see claimType of Role and 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' you want the later.
Once you do this, User.IsInRole("rolename") behaves as expected.
I hope this helps someone, took me a while to figure this out.
I had a similar issue, but in my case the problem was that the Session timeout was not synced with the authentication timeout, so I was not kicked out automatically but my session was being expired and, since my allowed operations were stored in a Session Variable, I was not able to retrieve the correct options for the current user.
Try checking if your session is not expired even if you're still logged in
Quite old topic but can confirm in vs 2015 Web forms application works solution:
<modules>
<remove name="FormsAuthenticationModule" />
<remove name="RoleManager" /> <!--add this to web config-->
</modules>
I've been struggling with the MVC5 role manager for some time now. I've verified that User.IsInRole can return different results at the same time, and apparently this is because the User object is cached and needs to be invalidated. One way to do this is to log out and log back in again as one of the answers here specified. Just throw this in the controller that adds the new role:
UserManager.AddToRole(User.Identity.GetUserId(), "Administrator");
var updatedUser = await UserManager.FindByNameAsync(User.Identity.Name);
var newIdentity = await updatedUser.GenerateUserIdentityAsync(UserManager);
AuthenticationManager.SignOut();
AuthenticationManager.SignIn(newIdentity);
However, if the user has your application open in other windows this won't update all of them.
Clear all cookies and try to login again. If we changed our roles, the cookie might not be aware of it. Reset the Cookies and create a cookie with your new roles and try again.
Paste this code in Global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie =
Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket =
FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(new Char[] { ',' });
GenericPrincipal userPrincipal =
new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}
protected class RolesAttribute : AuthorizeAttribute
{
public RolesAttribute(params string[] roles)
{
Roles = String.Join(",", roles);
}
}
Several things could be going on and here are few general things to try:
Try to run in debug mode and make sure that the line of code gets executed - silly but might happen
As stated in other answers, try to log off and log back in
Make sure the role is spelled out correctly
Make sure that the proper user is assigned to the proper role id
Try to republish the entire solution to the server - in my case, everything worked fine locally but not on the server until full delete all and republish
If all fails, try to run out of a box project and test it before adding complexity
#inject SignInManager<IdentityUser> SignInManager
#inject UserManager<IdentityUser> UserManager
...
await UserManager.IsInRoleAsync(await UserManager.GetUserAsync(User),"admin")
Add Page in front of User. This works: Page.User.IsInRole("Administrator")
For my code it had to be plural, not singular:
User.IsInRole("Administrators")

asp.net mvc keep object alive, information

i have this code
[HttpPost]
public ActionResult Index(LoginModel loginModel)
{
if (ModelState.IsValid)
{
// some lines of code . bla bla bla
TempData["loginModel"] = loginModel;
return RedirectToAction("index", "premium");
}
...
}
and this controller here
public ActionResult Index()
{
var loginModel = TempData["loginModel"] as LoginModel;
...
}
now, when the page loads, everything seems to work fine. but when i refresh, everything messes up, it says that the loginModel is like null. the question is, how can i like keep track of the current login users. i have forms authentication enabled. tnx
error is as below
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 22:
Line 23: var loginModel = TempData["loginModel"] as LoginModel;
Line 24: string username = loginModel.username;
Line 25: string password = loginModel.password;
Line 26: premiumModel.username = username;
Confusion
but when i refresh, everything messes up, it says that the loginModel
is like null
Answer
This is due to the fact that you have read the TempData key and Once it is read, data will be lost for that particular key.
var Value = TempData["keyName"] //Once read, data will be lost
Question
how can i like keep track of the current login users
Answer
So to persist the data even after the data is read you can Alive it like below
var Value = TempData["keyName"];
TempData.Keep(); //Data will not be lost for all Keys
TempData.Keep("keyName"); //Data will not be lost for this Key
TempData works in new Tabs/Windows also, like Session variable does.
You could use Session Variable also, Only major problem is that Session Variable are very heavy comparing with TempData. Finally you are able to keep the data across Controllers/Area also.
Hope this post will help you alot.
You only need to store the user's identity (username) once the user is authenticated - password is not needed. As such ASP.NET authentication already supports storing user's identity in the authentication cookie and you don't have to re-invent the wheel. You can get the identity using Controller.User property.
EDIT: I am assuming that you have set up your application correctly for Forms Authentication. Regardless, here are few how-to/tutorial links that start you on it:
http://www.apexa.net/Blog/web_design_Blog_20100319.aspx
http://www.asp.net/mvc/tutorials/authenticating-users-with-forms-authentication-cs
Explain solution so that you don't have to apply Authorize attribute on every action - http://blogs.msdn.com/b/rickandy/archive/2011/05/02/securing-your-asp-net-mvc-3-application.aspx
TempData does only live for one request. Therefore it's empty when you make the second request. If you'd want to do it like this you should use Session instead or you can have a look at forms authentication.
You should also consider VinayC advice and not store any password information in any state, especially not in clear text format.
I suggest you create a new MVC 3 project in Visual Studio via File > New. It will set up forms authentication for you, so you can see the best practices for the login and registration pages, signing the user in/out with the session cookie, and displaying user info like username.

ASP.NET MVC Authorization and hyperlinks

I am using successfully custom authorization in ASP.NET MVC. It simply involves a comparison between User.Identity and the owner of the object in context.
It works like a charm when used in simple conditions. It becomes more complicated when I try to call 2 actions in one web request.
Lets say I want to display an image which would be generated on-the-fly by my application. This image is generated by a controller, thus, it can be referenced by an URL even if it doesn't exist physically. I have decided that the user must be signed in and be the owner to view it, so I apply my authorization mechanizm to it.
Example: <img src="http://myapplication.com/images/generate/3" />
When I include such an image in a page via its action hyperlink, I expect that the authenticated user will still be in context on server side when the image is generating. This is not the case in my tests. The image never displays because my authorization check doesn't work. In the image controller, User.Identity is empty as if the user has not signed it.
In the meantime, the same user is still signed in to the website and can continue to browse with his identity in context... without those images working properly.
I wonder how to make this process work securely...
Thank you very much!
Marc Lacoursiere
RooSoft Computing inc.
Just wondering if you've checked if
Thread.CurrentPrincipal
is also empty in the controller? It should contain the same value.
Another suggestion would be to store the User.Identity value in a session?
You need to set up your identity in global.asax on every request. I'm using a custom Principal and Identity for this.
private void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (!Request.IsAuthenticated)
{
SetIdentity(new MyIdentity
{ Type = UserType.Inactive, Id = int.MinValue });
}
else
{
HttpCookie authCookie = Request.Cookies[
FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket =
FormsAuthentication.Decrypt(authCookie.Value);
var identity = Repository.GetIdentity
(authTicket.Name, new HttpRequestWrapper(Request));
SetIdentity(identity);
}
}
}
private void SetIdentity(MyIdentity identity)
{
Context.User = new MyPrincipal { Identity = identity };
Thread.CurrentPrincipal = Context.User;
}
This works, but I don't guarantee it to be secure. You should review this article on FormsAuthentication vulnerabilities prior to going live with this code. You have to understand that this code assumes the cookie is valid and hasn't been hijacked. There are some additional security measures that can be taken to reduce these vulnerabilities which this code doesn't show.
This may be when the site link in browser is http:\www.mysite.com (or http:\subdomain.mysite.com ) and you are using http:\mysite.com\image\5 in your application. Form authentication uses cookies. And these cookies may belong to domains and subdomains.
To find out what is going on I suggest to use FireFox with FireBug installed. Enable Net and Console tab for your site and make a complete refresh of the page. After you'll see requests in one of these tabs (Net tab exactly). At the left of the request you can see 'a plus' button, after you click it you'll see Headers and Response tabs (more detailed description of firebug). Have a look at Headers tab and try to find something like FORMAUTH (or what you've set in config as a forms cookie name). If you not see it - the problem is in domains.

Resources