Im thinking of getting usernames of my site using this in my view(Razor syntax):
#MySite.Helpers.Utils.UserName
heres the utils class:
public class Utils
{
static FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
public static string UserName { get { return id.Ticket.UserData; } }
}
Are there any potential problems with this code?
The reason Im doing it like this is because Im going to store username in the userdata field of a new FormsAuthenticationTicket when the user logs in.
I'm handling it like this because Im using facebook connect and want to store there ID in the username field in the db and their usernames/fullnames in a separate table.
so my logic to handle facebook usernames and my site registered usernames needs to be handled differently. Upon login Im thinking of handling it there then setting userdata as the actual username.
therefore throughout the site i can just get the logged in users name using : #MySite.Helpers.Utils.UserName
does this sound ok? will the fact that its a static variable be an issue?
or is there a better way to manage this? session variables maybe?
thanks
The reason Im doing it like this is
because Im going to store username in
the userdata field of a new
FormsAuthenticationTicket when the
user logs in.
The username of the currently logged in user is already stored in the authentication cookie. You don't need to store it once again in the UserData. And in order to retrieve it in your Razor template you could simply:
#User.Identity.Name
Obviously it is recommended to decorate the controller action rendering this view with the [Authorize] attribute to ensure that a user is authenticated before accessing it or you might get a NullReferenceException with this code.
As an alternative you could write a helper:
public static MvcHtmlString Username(this HtmlHelper htmlHelper)
{
var identity = htmlHelper.ViewContext.HttpContext.User.Identity;
if (identity.IsAuthenticated)
{
return MvcHtmlString.Create(identity.Name);
}
return MvcHtmlString.Empty;
}
which you could use like this:
#Html.Username()
Related
What is the fast way (best way) to get current user in ASP.NET Identity?
I wrote this code for getting current user but I don't know that is the best way or not?
public class MVCController : Controller
{
public User CurrentUser
{
get
{
string currentUserId = User.Identity.GetUserId();
User currentUser = DataContextFactory.GetDataContext().Users.FirstOrDefault(x => x.Id.ToString() == currentUserId);
return currentUser;
}
}
}
With Identity v2 the best way to get a user is to use the UserManager object.
var user = userManager.FindById(user.Identity.GetUserId());
Rather than a DB hit, we should add all required information in user claims during authentication and retrieve them from claims during next calls. It will be the fastest way to get commonly used user information and the same time we avoid any database calls. You can take a look on some claims helper methods Github link
I am creating a basic authentication system with MVC 4 that uses custom logic. I have a UserModel class (which inherits from IPrincipal) that stores data I need to be persistent. To do this I am using the following code in my Controller:
if (ModelState.IsValid)
{
if (userModel.IsValidUser())
{
FormsAuthentication.SetAuthCookie(userModel.Username, false);
HttpContext.User = userModel;
// User is now logged in; send them to Index method to load MyeMan data
return RedirectToAction("Index", "Login");
}
}
Then, in the Index action:
if (IsUserLoggedIn())
{
UserModel userModel = (UserModel) HttpContext.User; // This line throws error
}
The error I get is:
Unable to cast object of type 'System.Web.Security.RolePrincipal' to
type 'MyProj.UserModel'.
When I look in debug, the HttpContext.User accepts the UserModel without complaint. Only when it redirects to the different action does its datatype change.
Am I doing something wrong or is this the complete wrong way to go about storing UserModel persisently without Sessions? Sessions will expire independently of the AuthCookie; I was told HttpContext.User is the way to go.
Assigning the user will work, but this assignment will not persist between requests. You have to make sure to set up the user at the beginning of each request, perhaps in a custom AuthorizeAttribute or IHttpModule. For example, you might have logic like:
Retrieve the relevant cookie from the request
Verify that the cookie corresponds to a valid session (e. g. by querying a database containing this information)
Retrieve the session information based on the cookie and store it in the User property
Also, when you assign HttpContext.Current.User consider assigning Thread.CurrentPrincipal as well.
Read Passing Data in an ASP.NET MVC Application
You can use TempData to pass the data between the action. It will be available for only subsequent requests
TempData["User"] = userModel;
// User is now logged in; send them to Index method to load MyeMan data
return RedirectToAction("Index", "Login");
In Index
UserModel user= (UserModel)TempData["User"];
How do we get the current user, within an secure ApiController action, without passing the userName or userId as a parameter?
We assume that this is available, because we are within a secure action. Being in a secure action means that the user has already authenticated and the request has her bearer token. Given that WebApi has authorized the user, there may be a built in way to access the userId, without having to pass it as an action parameter.
In WebApi 2 you can use RequestContext.Principal from within a method on ApiController
You can also access the principal using the User property on ApiController.
So the following two statements are basically the same:
string id;
id = User.Identity.GetUserId();
id = RequestContext.Principal.Identity.GetUserId();
Hint lies in Webapi2 auto generated account controller
Have this property with getter defined as
public string UserIdentity
{
get
{
var user = UserManager.FindByName(User.Identity.Name);
return user;//user.Email
}
}
and in order to get UserManager - In WebApi2 -do as Romans (read as AccountController) do
public ApplicationUserManager UserManager
{
get { return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
}
This should be compatible in IIS and self host mode
None of the suggestions above worked for me. The following did!
HttpContext.Current.Request.LogonUserIdentity.Name
I guess there's a wide variety of scenarios and this one worked for me. My scenario involved an AngularJS frontend and a Web API 2 backend application, both running under IIS. I had to set both applications to run exclusively under Windows Authentication.
No need to pass any user information. The browser and IIS exchange the logged on user credentials and the Web API has access to the user credentials on demand (from IIS I presume).
Karan Bhandari's answer is good, but the AccountController added in a project is very likely a Mvc.Controller. To convert his answer for use in an ApiController change HttpContext.Current.GetOwinContext() to Request.GetOwinContext() and make sure you have added the following 2 using statements:
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
In .Net Core use User.Identity.Name to get the Name claim of the user.
If you are using Asp.Identity UseManager, it automatically sets the value of
RequestContext.Principal.Identity.GetUserId()
based on IdentityUser you use in creating the IdentityDbContext.
If ever you are implementing a custom user table and owin token bearer authentication, kindly check on my answer.
How to get user context during Web Api calls?
Hope it still helps. :)
string userName;
string userId;
if (HttpContext.Current != null && HttpContext.Current.User != null
&& HttpContext.Current.User.Identity.Name != null)
{
userName = HttpContext.Current.User.Identity.Name;
userId = HttpContext.Current.User.Identity.GetUserId();
}
Or based on Darrel Miller's comment, maybe use this to retrieve the HttpContext first.
// get httpContext
object httpContext;
actionContext.Request.Properties.TryGetValue("MS_HttpContext", out httpContext);
See also:
How to access HTTPContext from within your Web API action
Sorry for the basic question, first time with Web MVC4 in C#...
I'm creating a web interface for an application I've written in C#/SQL. I've been able to attach the MVC4 framework to the SQL DB. Now I want to secure what people can do based on group membership in AD. I have the authentication in my web.config set to "Windows" and it properly displays the User.Identity.Name that i'm logged in with. So I know it's pulling up the current logged in user. More over, I need to be able to authenticate a user outside of the active directory domain in the case of an android or ipad device. I haven't gotten that far yet though... for the most part, I'd like to auto authenticate the logged in user if possible then prompt for a username/password if none exists.
Ok, also I already know how to pull group membership for a user in AD. But I need to run that AD query and store that information somewhere that can be accessed on each page. Then on each page how do I access that variable?
For example, I don't want to display a menu option if they don't have access to it so that variable needs to be used to either display or not display the menu option that's being secured. Also, I assume I need to add that security on the webpage as well so that if someone tries to go there manually they cannot.
I assume I don't want to use session variables for security reasons..
In the past with Adobe Flex I used a singleton to manage the session state. I did a search out there and people are saying that it's probably not a good idea in C#. Not many examples of this anyway...
What are you doing to do this?
Here is what I would recommend. Start looking for examples of the ActiveDirectoryMembershipProvider Class. This MembershipProvider combined with Forms Authentication will provide you with a secure system to authenticate users.
Once authenticated, you need to authorize your users to access resources by combining the Active Directory Role Provider(ADRP) (to determine User Groups) with the standard way of Securing your MVC Application.
To get you started I created these simple extension methods when you can extend to use the ADRP (as I haven't used the ADRP).
public static class IPrincipalExtensions
{
private static _adminName = "Administrator";
public static bool IsAnonymous(this IPrincipal instance)
{
return (instance == null);
}
public static bool IsAdminOrInRole(this IPrincipal instance, string role)
{
if (instance == null
|| instance.Identity == null
|| !instance.Identity.IsAuthenticated)
{
return false;
}
bool result = instance.IsInRole(role)
|| instance.IsInRole(IPrincipalExtensions._adminName));
return result;
}
}
Then I also extended the default AuthorizeAttibute to give me an attribute I can use solely for Administrators:
public class AuthorizeAdministratorAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
bool result = false;
IPrincipal user = httpContext.User;
if (user.Identity.IsAuthenticated)
{
result = user.IsAdmin();
}
return result;
}
}
This uses the same extension methods provided in my IPrincipalExtensions so I don't repeat myself. Some might find this overkill as the following two lines are equal:
[Authorize("Administrator")]
[AuthorizeAdministrator]
However, since the first example is using a string, a simple mistype denies access, and if I decided to change the role/group name to "Admins" it becomes more difficult. So using the second one (which I could argue is strongly typed) if the group changes, I only have to change the name in one location.
So I'm using SignalR, it's setup and working correctly on my Website.
Let's suppose user A logs in (I am using the Membership API). When A logs in I am calling the connection from .js located in my masterpage. That will assign this use a specific userId.
Let's say now user B logs in goes does some event and that event needs to notify user A from codebehind.
So what I am trying to do here is notify user B of use A's action from CodeBehind. How will user B know user A's ID and how does the whole thing work? I couldn't find help in the documentation as it does not go into that kind of stuff.
How can this be achieved? Thanks.
I realize this has already been answered, but there another option that folks might find helpful. I had trouble finding info on how to do this, so hopefully this helps someone else.
You can override the SignalR ClientID generation and make it use the membership UserID. This means you do not have to maintain a CleintID -> UserID mapping.
To do this, you create a class that implements the IClientIdFactory interface. You can do something like:
public class UserIdClientIdFactory : IClientIdFactory
{
public string CreateClientId(HttpContextBase context)
{
// get and return the UserId here, in my app it is stored
// in a custom IIdentity object, but you get the idea
MembershipUser user = Membership.GetUser();
return user != null ?
user.ProviderUserKey.ToString() :
Guid.NewGuid().ToString();
}
}
And then in your global.asax:
SignalR.Infrastructure.DependencyResolver.Register(typeof(IClientIdFactory), () => new UserIdClientIdFactory());
EDIT -- as nillls mentioned below, things have changed in the signalR version 0.4. Use ConnectionId rather than ClientId:
public class UserIdClientIdFactory : IConnectionIdFactory
{
public string CreateConnectionId(SignalR.Hosting.IRequest request)
{
// get and return the UserId here, in my app it is stored
// in a custom IIdentity object, but you get the idea
MembershipUser user = Membership.GetUser();
return user != null ?
user.ProviderUserKey.ToString() :
Guid.NewGuid().ToString();
}
}
And DependencyResolver has moved:
SignalR.Hosting.AspNet.AspNetHost.DependencyResolver.Register(typeof(IConnectionIdFactory), () => new UserIDClientIdFactory());
Hope this helps someone!
Your app needs to store a mapping of SignalR client (connection) IDs to user ids/names. That way, you can look up the current SignalR client ID for user B and then use it to send a message directly to them. Look at the chat sample app at https://github.com/davidfowl/JabbR for an example of this.