12

Is there a way to override HttpContext.Current.User.Identity to add another property (screen name)?

My application uses Identity and I've left the unique identity as email. I store user data such as first / last name in a separate "Profile" table. Is there a way to store this information somewhere within HttpContext.Current?

It doesn't necessarily need to be within User. I have had a search and noticed there's a HttpContext.Current.ProfileBase. Not sure how to use it though - and I really don't want all the excess stuff that base comes with.

ryanyuyu
  • 6,366
  • 10
  • 48
  • 53
Fred Johnson
  • 2,539
  • 3
  • 26
  • 52
  • As I understand you have different table with additional user data. And you want fetch current user's data. Am I right? Are you using Entity Framework? And way you prefer to store those data to another table? – Sam FarajpourGhamari Aug 12 '15 at 20:06
  • `User` is really just an `IPrincipal` and `Identity` is just `IIdentity`. You can easily create your own implementation of `User` with it's own implementation of `Identity`. They just need to adhere to the interfaces. – TyCobb Aug 12 '15 at 20:10
  • Since you're using Asp.Net Identity, the way to do with is with Claims. See my answer posted below. – Brendan Green Aug 14 '15 at 01:08
  • Thanks, I am testing the answers tonight and will accept one then – Fred Johnson Aug 14 '15 at 12:26

4 Answers4

18

If you are using Asp.Net Identity, then this is very easy to do with claims.

In your SignInAsync method (or, wherever you are creating the claims identity), add the GivenName and Surname claim types:

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    // Add the users primary identity details to the set of claims.
    var your_profile = GetFromYourProfileTable();

    identity.AddClaim(new Claim(ClaimTypes.GivenName, your_profile == null ? string.Empty : your_profile.FirstName));
    identity.AddClaim(new Claim(ClaimTypes.Surname, your_profile == null ? string.Empty : your_profile.LastName));

    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

You then use an extension method to IIdentity to pull the information out of the claims identity:

public static ProfileName GetIdentityName(this IIdentity identity)
{
    if (identity == null)
        return null;

    var first = (identity as ClaimsIdentity).FirstOrNull(ClaimTypes.GivenName),
    var last = (identity as ClaimsIdentity).FirstOrNull(ClaimTypes.Surname)

    return string.Format("{0} {1}", first, last).Trim();
}

internal static string FirstOrNull(this ClaimsIdentity identity, string claimType)
{
    var val = identity.FindFirst(claimType);

    return val == null ? null : val.Value;
}

Then, in your application (in your controller or view), you can just do:

var name = User.Identity.GetIdentityName();
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Brendan Green
  • 11,676
  • 5
  • 44
  • 76
6

You can put value in HttpContext.Current.Items. It is dictionary which lifetime is single request.

You can use it like this:

public static string CurrentScreenName
{
    get
    {
        string screenName = (string)HttpContext.Current.Items["CurrentScreenName"];

        if (string.NullOrEmpty(screenName))
        {
             screenName = ResolveScreenName();
             HttpContext.Current.Items["CurrentScreenName"] = screenName;
        }
        return screenName;
    }
}

It will execute ResolveScreenName() only once for single request.

Also you can make extension method to access screen name from IIdentity

public static class Extensions
{
    public static string GetScreenName(this IIdentity identity)
    {
        return CurrentScreenName;
    }
}

And then use it like this:

string screenName = HttpContext.Current.User.Identity.GetScreenName();
Piotr Dory
  • 334
  • 2
  • 12
1

Absolutely! You need to create your own type that implements from IPrincipal, and take over security yourself. You can authenticate the user in an OWIN step, manually setting context.Request.User.

David Pfeffer
  • 38,869
  • 30
  • 127
  • 202
-1

I found one implementation:

var profile = db.UserProfile.Where(u => u.UserId == user.Id).FirstOrDefault();
ProfileBase httpProfile = ProfileBase.Create(user.UserName);
httpProfile.SetPropertyValue("FullName", profile.FullName);
httpProfile.SetPropertyValue("FirstName", profile.FirstName);
httpProfile.SetPropertyValue("LastName", profile.LastName);

Then to get later...

ProfileBase userProfile = ProfileBase.Create(HttpContext.User.Identity.Name);
var fullName = userProfile.GetPropertyValue("FullName"));
Fred Johnson
  • 2,539
  • 3
  • 26
  • 52