How to obtain a list of Users from ASP.NET Identity? - asp.net

Edit: This question is outdated
The Identity Framework was a moving target at the moment I asked this. The authors changed quite a few things and they have decoupled several others, making everything easier.
Have a look at the Asp.NET Identity Sample project on github.
I'm creating a small application that requires user management. Registration is not allowed, instead there is a super user that will create and modify login information.
I'm using the new ASP.NET Identity membership system, and sure enough, creating users and adding roles is easy and intuitive.
Now, my question: How to obtain a list of users using the AuthenticationIdentityManager class that is used by the generated AccountController class? I couldn't find a way to access the user list from my controller.
(By the way, the new name "Identity" may sound awesome to some people but it is a pain to search for.)
Edit: If I try to do this
ApplicationDbContext UsersContext = new ApplicationDbContext();
UsersContext.Users.ToList(); // Exception
I get an exception Invalid column name 'Discriminator'. The definition of ApplicationDbContext is generated automatically by the new application wizard:
using Microsoft.AspNet.Identity.EntityFramework;
namespace Cobranzas.Models
{
public class ApplicationUser : User
{
}
public class ApplicationDbContext : IdentityDbContextWithCustomUser<ApplicationUser>
{
}
}
So my guess is that Discriminator column is for telling apart ApplicationUser from User. However, it does not exists in my database (which was created automatically by the application.)

I found out that I wasn't using the derived ApplicationUser object for anything, so I just went ahead and changed all uses of it for plain old User. Then I just changed ApplicationDbContext definition for the following:
public class ApplicationDbContext : IdentityDbContext<
User, UserClaim, UserSecret, UserLogin,
Role, UserRole, Token, UserManagement>
{
}
And now I can access the user list:
UsersContext = new ApplicationDbContext();
...
UsersContext.Users.ToList();
However, I think this will come back and haunt me in the future (I'll probably need to add more fields to User) so probably I'll have to use the same approach as in this question:
Get all role names in ASP.NET MVC5 Identity system
Edit: Since I got the need to add a new property, I had to revert my changes. So I went ahead and did a line by line comparison with the ASP.NET Identity Sample Project, and found out that the generated project had the following line:
IdentityManager = new AuthenticationIdentityManager(new IdentityStore());
while the Sample application had included the database context in the constructor. So I added it in my constructor, recreated the database and the problem went away.
IdentityManager = new AuthenticationIdentityManager(new IdentityStore(new ApplicationDbContext()));

Create ASP .NET MVC5 project by default
Create ASP .NET Identity tables properly and change connection string as well.
To get users just do the following test
A. Go to AccountController
B. Create any dummy method and put there
var context = new ApplicationDbContext();
var allUsers = context.Users.ToList();

For RTM, you will have to drop down to your DbContext or whatever your specific store implementation has to enumerate all users. In the next release, we will most likely be adding an optional IQueryable Users/Roles method on the Manager classes that stores can implement to expose IQueryables for both users and stores.

using System.Linq;
using System.Data;
using System.Data.Entity;
var db = new ApplicationDbContext();
var Users = db.Users.Include(u => u.Roles);

If we can use the following type of Constructor in Identity AccountController.
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
UserManager = userManager;
AccessTokenFormat = accessTokenFormat;
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
then we can directly used UserManager object to get user list like
var userList= UserManager.Users.ToList();

You can do this by explicitly setting right types:
var userStore = new UserStore<IdentityUser>();
var userManager = new UserManager<IdentityUser>(userStore);
IQueryable<IdentityUser> usersQuery = userManager.Users;
List<IdentityUser> users = usersQuery.ToList();
Imoports:
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Linq;
using System.Collections.Generic;

Related

How can I get current user ID using IHttpContextAccessor?

I am currently using .NET Core and I am trying to get the current user ID. I understand that System.Web is not available in NET Core, so I tried using IHttpContextAccessor.
I have also added this into my Startup.cs: service.AddHttpContextAccessor()
I then tried looking up for the user id by doing this in my controller:
public Controller(IHttpContextAccessor httpContextAccessor){
var userId = httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier)
}
But it always returns null, does anyone knows why and able to advise? I have also disabled anonymousAuthentication and set windowsAuthentication to true.
Edit
The only changes I did to my Startup.cs is in the ConfigureServices method.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddHttpContextAccessor();
}
Are you sure, that you need IHttpContextAccessor?
There is a better way to get Id from claims actually:
You can use ControllerBase.User property, but at first make sure that your controller is derived from Controller or ControllerBase (last one is without views support).
public class YourController : Controller
{
...
var id = User.FindFirstValue(ClaimTypes.NameIdentifier)
...
}
There is a better way to get Id from claims actually:
You can use the ControllerBase.User property, but at first, make sure that your controller is derived from Controller or ControllerBase (the last one is without views support).
Use the following code snippet to get ASPNET ID
string currentUser = _http.HttpContext.User.Claims.ToList().Find(r => r.Type == "id").Value;
If you've included "ClaimTypes.Name" with the username value in claims when token was generated.
Then you can access the username using IHttpContextAccessor, if respective dependency is added, like:
var currentUserName = _httpContextAccessor.HttpContext.User.Claims.First(c => c.Type == ClaimTypes.Name).Value;
Then you can access the user like:
var user = await _userManager.FindByNameAsync(currentUserName);
and hence the userId:
var userId = user.Id;
You'll need an instance of UserManager<ApplicationUser>. The easiest way to get an instance of this class is add it as an argument to your class constructor and it will be provided via dependency injection.
string userId = UserManager.GetUserId(httpContextAccessor.HttpContext.User);
Don't forget to check for null values.

Get Current Principal as my Custom Application User in ASP.Net Core Identity

In previous versions of ASP.NET, if I wanted to have a custom class as my current logged in user, what I did was: I let the FormsAuthentication module do its work, and then, in the PostAuthenticateRequest event I replaced the current Principal (HttpContext.Current.User) with my custom principal object that I fetched from the database (with some caching for performance).
How can I achieve the same in ASP.NET Identity? I have my own ApplicationUser (not the default that comes with the EntityFramework ASP.NET Identity) and my own UserStore.
In every authenticated request, I have the HttpContext.User as a ClaimsPrincipal object. Is there a way to replace that with my CustomClaimsPrincipal?
Is there another, better way, to retrieve the current ApplicationUser instance based on the current ClaimsPrincipal?
If you have your own IUserStore you can implement IUserClaimStore to customize the claims identity which is passed to the claims principal.
If you need to replace the default claims principal you should implement the IUserClaimsPrincipalFactory and pass your implementation to the SignInManager and register the configured manager to your owin context.
It should look like this along the lines.
(Assuming you are using ASP.NET Core Identity, for Identity v2 the interfaces and constructors may differ!)
class CustomClaimsFactory<TUser> : Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory<TUser>
where TUser : class
{
public Task<ClaimsPrincipal> CreateAsync(TUser user)
{
// create and return your custom principal
}
}
class OwinStartup
{
public void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext(CreateSignInManager);
}
Microsoft.AspNetCore.Identity.SignInManager CreateSignInManager()
{
UserManager manager; // the manager that uses your custom IUserStore
IHttpContextAccessor accessor; // I don't know where to get it from...
var factory = new CustomClaimsFactory();
return new SignInManager(manager, accessor, factory, null, null, null);
}
}
For ASP.Net Core the OWIN-like startup configuration is done via dependency injection.

WCF Services using same entity model class but exposes different in client

I am new to WCF Services and can't get rid of this problem. For the next version of our web application I want to make use of WCF as webservice. Currently I am stuck with this problem:
To try WCF out I made 2 services: EmployeeService and AuthenticationService. I also made a datacontract Employee.
In AuthenticationService I use EmployeeService to get the logged Employee
Now in my client (ASP MVC Web) I add both Services as I need them both. But then when I try to use the object Employee I get the error :
Employee' is an ambiguous reference between 'IWA.Portal.AuthenticationService.Employee' and 'IWA.Portal.EmployeeService.Employee
The reason I want to make multiple services is to group them functionally. Example: Everything regarding employees will be under EmployeeService and everything regarding job will be under JobService.
How can I fix this or how should I structure my webservice?
Currently my webservice solution consists of :
Project.DataContracts (Entities)
Project.ServiceContracts (Interfaces)
Project.Services (Services, NHibernate & Castle Windsor)
Any help is much appreciated! Thx
AuthenticationService
public class AuthenticationService : IAuthenticationService
{
private readonly IEmployeeService _employeeService;
public AuthenticationService(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
public Employee Authenticate()
{
var employee = _employeeService.Get(1);
return employee;
}
}
Code in my client (Controller)
readonly EmployeeServiceClient _employeeService = new EmployeeServiceClient();
readonly AuthenticationServiceClient _authenticationService = new AuthenticationServiceClient();
Employee authedEmployee = _authenticationService.Authenticate();
Employee test = _employeeService.Get(827);
Looks like your namespaces are clashing and to fix it you will need to use full names in your code when referring to a class so instead of just Employee use
AuthenticationService.Employee auth_emp = new AuthenticationService.Employee();
and
EmployeeService.Employee es_emp = new EmployeeService.Employee();
This will solve your problem.

ASP.Net Identity 2 Using a custom data access layer like Enterprise Library

I am new to asp.net identity (ver. 2) and am about to start implementing it one of our MVC projects using the Claims based authorization mechanism instead of role based. I having been going through this link where what I understand from what is written is that I need to inherit Microsoft.AspNet.Identity.UserManager and create a CustomUserManager class and override its methods and then implement Microsoft.AspNet.Identity.EntityFramework.IUserStore to be consumed by my CustomUserManager class at the very least. There are other interfaces that I think were designed to be implemented for certain specific conditions like in my case the IUserClaimStore since I want to go with Claims based authorization. The reason mentioned is that I can change the store at a later date incase I want to change my persistence mechanism.
My questions are:
Since I am never going to change the persistence mechanism, is it really required that I implement all those classes and interfaces?
Going through the sample code the most important methods seem to be the following two code blocks:
Identity Creation and save to session (code in DoLogin Method)
// over simplified user object creation
UserPoco userObject= MyDAL.GetUserDatabyLoginDetails(username,password);
//identity created
var identity = CustomImplementationOfCreateIdentity(userObject, DefaultAuthenticationTypes.ApplicationCookie);
//saved to session
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
CheckAccess
public class AppClaimsAuthManager: ClaimsAuthorizationManager
{
public override bool CheckAccess(AuthorizationContext context)
{
var resource = context.Resource.First().Value;
var action = context.Action.First().Value;
//bool retVal = context.Principal.HasClaim("MyAction", "SampleResource");
bool retVal = context.Principal.HasClaim(action, resource);
bool baseRetVal= base.CheckAccess(context);
return retVal;
}
}
which is then used in controller methods like so
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "delete", Resource = "SomeResource")]
public ActionResult ClaimsBasedActionMethod()
{
return View();
}
Does it really matter how my user object is created via the CustomManager and CustomUserstore class implementations? Once the user name and password is verified and claims fetched from DB and my userObject created, I should be good to go right? I want this data to be fetched my service layer using enterprise library which I don't want to clog up with all identity framework related references.
Thoughts?

Add role in ASP.NET Identity

How can I add a Role in the new ASP.NET Identity system (1.0)?
There is a UserStore class but no RoleStore class.
I can't find any documentation on this issue.
RoleManager = new RoleManager<IdentityRole>(
new RoleStore<IdentityRole>(new MyDbContext()));
var roleresult = RoleManager.Create(new IdentityRole(roleName));
Starting with the .NET Framework 4.5, Windows Identity Foundation (WIF) has been fully integrated into the .NET Framework.
I would advice to examine the possibility, in my opinion the preferred, to implement Authorization through Claims (Expressing Roles as Claims).
When the IsInRole() method is called, there is a check made to see if the current user has that role.
In claims-aware applications, the role is expressed by a role claim type that should be available in the token.
The role claim type is expressed using the following URI:
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
So from the UserManager you can do something like this (without the RoleManager):
var um = new UserManager();
um.AddClaimAsync(1, new Claim(ClaimTypes.Role, "administrator"));
Claims can simplify and increase the performance of authentication and authorization processes.
You can use the roles stored as claims to eliminate back-end queries every time authorization takes place.
Using Claims you will not need the RoleStore anymore (at least for the equivalent authorization purposes...)
I used below snippets in one sample asp.net web page page_load for starting to grasp the way ASP Identity works
UserManager userManager = new UserManager();
var roleStore = new RoleStore<IdentityRole>(new ApplicationDbContext());
var roleManager = new RoleManager<IdentityRole>(roleStore);
var applicationRoleAdministrator = new IdentityRole("superadmin");
if (!roleManager.RoleExists(applicationRoleAdministrator.Name))
{
roleManager.Create(applicationRoleAdministrator);
}
ApplicationUser applicationUserAdministrator = userManager.FindByName(User.Identity.Name);
if (!userManager.GetRoles(applicationUserAdministrator.Id).Contains("superadmin"))
{
Response.Redirect("~/account/login.aspx?ReturnUrl=" + Request.Url.AbsolutePath);
}
Of course below ApplicationDbContext is automatically generated with ASP.NET 4.5+ templates like below
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
}
Also Create application Role Manager class too
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
//return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
return new ApplicationRoleManager(new RoleStore<IdentityRole>(new ApplicationDbContext()));
}
}
also add below line in your startup.Auth.cs => ConfigureAuth(IAppBuilder app) method
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
And then in your controller:
private ApplicationRoleManager _roleManager;
public ApplicationRoleManager RoleManager
{
get
{
return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
}
private set
{
_roleManager = value;
}
}
I am new to this Identity Stuff and I am not sure if it is necessary or I am doing it clean and right, but these steps worked for me
ASP.NET identity is claims aware with respect to roles. That really confused me because in the previous system you configured membership and role providers in web.config.
The issue for me is that I have code like this:
HttpContext.Current.User.IsInRole("some role")
Fortunately, this logic still works. You can see the logic in the CreateAsync function in ClaimsIdentityFactory.cs which is in Microsoft.AspNet.Identity.Core. One of the arguments is UserManager. It asks it if it SupportsUserRole and if so then it calls GetRolesAsync and adds each role as a claim to the ClaimIdentity. There is no need to do this yourself.
IsInRole uses claims as described here:
http://msdn.microsoft.com/en-us/library/hh545448.aspx

Resources