Reputation: 29234
The tutorials on enabling authentication work all right, but what identifier should be used to store data for a user in the database? The only thing easily available is User.Name
, which seems to be my email address.
I see in the database there is an AspNetUsers
table with that as the UserName
column, and a varchar Id
column that appears to be a GUID and is the primary key. It seems like the 'Id' field is the logical value to use, but it's not readily available in my app. I found I can get to it like this:
string ID_TYPE = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
var id = User.Claims.Where(x => x.Type == ID_TYPE).Select(x => x.Value).FirstOrDefault();
But that seems like a weird way to go about it. Is that the proper value to use say if I want to create a 'Posts' table that has a user associated with a post?
I've looked at these pages and it seems that a lot of this might be due to Microsoft integrating the same login process with ActiveDirectory.
Is there a reason to make the id so hard to get to and the name so easy? Should I be using the name instead? Should I be careful not to let the user change their user name then?
Upvotes: 1
Views: 558
Reputation: 2077
In your controller use dependency injection to get the user manager: Create a class MyUser that has your extended properties
public class MyUser : IdentityUser
{
public string MyExendedInfo { get; set; }
public int MyOtherInfo {get;set;}
}
add this property to the database using migration, or manually add it.
In Startup.cs in Configure Services add:
services.AddIdentity<MyUser, IdentityRole>()
Now inject this in your controller class:
private readonly UserManager<MyUser> _userManager;
public HomeController(
UserManager<MyUser> userManager)
{
_userManager = userManager;
}
Now you can access your additional proporties and your Id (if you still need this) in your action methods like this:
var user = await _userManager.GetUserAsync(HttpContext.User);
var id = user.Id;
var myExtendedInfo = user.MyExtendedInfo;
var myOtherInfo = user.MyOtherInfo;
etc
You can also update information about your user:
user.myExtendedInfo = "some string";
user.MyOtherInfo = myDatabase.pointer;
var result = await _userManager.UpdateAsync(user);
if (!result.Succeeded)
{
//handle error
}
So as long as you want only limited additional data stored in the database, you can create a custom user class, and use the Identity system to store it for you. I would not store it myself. If however, you need to store large information in a separate table and/or reference the user from other tables, the Id is the correct field to use and you can access it as shown above.
I don't know what the best practice is for how much information can be stored in AspNetUsers, versus in claims, versus in your own table, but since the provided table already stores things like user name, phonenumber etc, I think it is Ok to extend it like this.
Upvotes: 0
Reputation: 2141
The shortest path to UserId is:
User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
Or create extension like so if you need to access UserId a lot:
public static class ClaimsPrincipalExtensions
{
public static string GetUserId(this ClaimsPrincipal principal)
{
if (principal == null)
return null; //throw new ArgumentNullException(nameof(principal));
string ret = "";
try
{
ret = principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
}
catch (System.Exception)
{
}
return ret;
}
}
Usage:
User.GetUserId()
Upvotes: 3