This is my first attempt to use the ASP.NET identity with the builtin authentication. All previous attempts resulted in having a manual check for user credentials and then setting FormsAuthentication
AuthCookie
. But I had some problems with a signalR connection not having authentication information this way. So I started from scratch with the builtin authentication.
So I extended my ApplicationUser
object with some fields:
public class ApplicationUser : IdentityUser
{
public long SteamId { get; set; }
public string Avatar { get; internal set; }
public string Name { get; internal set; }
public int Credits { get; internal set; }
public long? DiscordId { get; internal set; }
public DateTime? LastLogin { get; internal set; }
public DateTime RegisterDate { get; internal set; }
}
These fields will create new columns in my AspNetUsers
table. The problem is, I can't access these values in my views. For that I need to use claims if I understand correctly. These claims are stored in another table called AspNetUserClaims
. So I have to add those claims to the user
await UserManager.AddClaimAsync(user.Id, new Claim("Avatar", user.Avatar));
and creating a extension method to get the avatar from the principal
public static class ClaimsPrincipalExtension
{
public static string GetAvatar(this ClaimsPrincipal principal)
{
var avatar = principal.Claims.FirstOrDefault(c => c.Type == "Avatar");
return avatar?.Value;
}
}
Now I can access the avatar in my view
@(((ClaimsPrincipal)User).GetAvatar())
I don't think that's a really good and clean way to do this, but this is the first time I am using it, so I don't know what's the best practices to do. There are three main reasons why I don't like it:
AspNetUsers
table as column and once as a new entry in AspNetUserClaims
SteamId
, Credits
or RegisterDate
are saved as string in the AspNetUserClaims
table, and I have to convert them to int
, long
or DateTime
in the extension methodApplicationUser
What is the best way to handle additional fields?
AdditionalUserInformation
and store the json serialized string as claim and just have one extension method to return the object? Then the properties would have the correct type.ApplicationUser
in the view?I also checked some examples. Mostly they add those extension methods and mostly just string properties.
Examples
I am currently kinda stuck here on finding the best and maybe clean solution.
You can access AspNetUsers table with the name "Users" from your DbContext. First query AspNetUsers with current user's username or userId, then fill your ViewModel and send it to the view. The following code shows what I described:
[Authorize]
public ActionResult UserTopNavBar()
{
var userTopNavBarViewModel = new UserTopNavBarViewModel();
using(ApplicationDbContext _db = new ApplicationDbContext())
{
var user = _db.Users.FirstOrDefault(a => a.UserName == User.Identity.Name);
if (user != null)
{
userTopNavBarViewModel.Name = user.FirstName + " " + user.LastName;
userTopNavBarViewModel.Picture = user.Picture;
userTopNavBarViewModel.Id = user.Id;
}
}
return PartialView(userTopNavBarViewModel);
}
And this is my ViewModel
public class UserTopNavBarViewModel
{
public string Name { get; set; }
public byte[] Picture { get; set; }
public string Id { get; set; }
}