OMANSAK
OMANSAK

Reputation: 1332

Custom Authentication & Update Claims in ASP.NET CORE

I am developing web site with ASP.NET CORE that uses Claims for User Authentication and User Id and other infos keeps in Claims, is it security ?

ClaimsIdentity identity = new ClaimsIdentity(
                new[]
                {
                    new Claim(ClaimTypes.Name, userInfo.Name),
                    new Claim(ClaimTypes.Surname, userInfo.Surname),
                    new Claim("Image", userInfo.Image),
                    new Claim(ClaimTypes.NameIdentifier,result.Id.ToString()),
                    new Claim(ClaimTypes.IsPersistent, loginViewModel.RememberMe.ToString())
                },
                CookieName.User);
            HttpContext.SignOutAsync(CookieName.User).Wait();
            HttpContext.SignInAsync(CookieName.User, new ClaimsPrincipal(identity),
                new AuthenticationProperties
                {
                    IsPersistent = loginViewModel.RememberMe,
                    AllowRefresh = true
                }).Wait();

Sometime i need change user infos and it uses this. is it secure way ?

//Get 
int id = int.Parse(new ClaimsCookie(HttpContext).GetValue(CookieName.User, KeyName.Id));

//Set Update
new ClaimsCookie(HttpContext).SetValue(CookieName.User, new[] { KeyName.Name, KeyName.Surname }, new[] { model.Name, model.Surname });

Class :

namespace ...
{
    public class ClaimsCookie
    {
        private readonly HttpContext _httpContext;
        public ClaimsCookie(HttpContext httpContext)
        {
            _httpContext = httpContext;
        }

        public string GetValue(string cookieName, string keyName)
        {
            var principal = _httpContext.User;
            var cp = principal.Identities.First(i => i.AuthenticationType == cookieName.ToString());
            return cp.FindFirst(keyName).Value;
        }
        public async void SetValue(string cookieName, string[] keyName, string[] value)
        {
            if (keyName.Length != value.Length)
            {
                return;
            }
            if (_httpContext == null)
                return;
            var principal = _httpContext.User;
            var cp = principal.Identities.First(i => i.AuthenticationType == cookieName.ToString());
            for (int i = 0; i < keyName.Length; i++)
            {
                if (cp.FindFirst(keyName[i]) != null)
                {
                    cp.RemoveClaim(cp.FindFirst(keyName[i]));
                    cp.AddClaim(new Claim(keyName[i], value[i]));
                }

            }
            await _httpContext.SignOutAsync(cookieName);
            await _httpContext.SignInAsync(cookieName, new ClaimsPrincipal(cp),
                new AuthenticationProperties
                {
                    IsPersistent = bool.Parse(cp.FindFirst(KeyName.IsPersistent).Value),
                    AllowRefresh = true
                });
        }
        public async void SetValue(string cookieName, string keyName, string value)
        {
            var principal = _httpContext.User;
            var cp = principal.Identities.First(i => i.AuthenticationType == cookieName.ToString());

            if (cp.FindFirst(keyName) != null)
            {
                cp.RemoveClaim(cp.FindFirst(keyName));
                cp.AddClaim(new Claim(keyName, value));
            }
            await _httpContext.SignOutAsync(cookieName);
            await _httpContext.SignInAsync(cookieName, new ClaimsPrincipal(cp),
                new AuthenticationProperties
                {
                    IsPersistent = bool.Parse(cp.FindFirst(KeyName.IsPersistent).Value),
                    AllowRefresh = true
                });
        }
    }
    public static class CookieName
    {
        public static string Company => "CompanyUserProfilCookie";
        public static string User => "UserProfilCookie";
        public static string Admin => "AdminPanelCookie";
    }

    public static class KeyName
    {
        public static string Id => ClaimTypes.NameIdentifier;
        public static string Name => ClaimTypes.Name;
        public static string Surname => ClaimTypes.Surname;
        public static string IsPersistent => ClaimTypes.IsPersistent;
        public static string Image => "Image";
    }
}

I am setting HttpContext to this class from any Controller. Have any way static HttpContext, i dont want set from Controller ?

Upvotes: 0

Views: 3540

Answers (1)

Severius5
Severius5

Reputation: 548

One option is to inject IHttpContextAccessor from DI and access HttpContext from it.

Change ClaimsCookie constructor to reflect that:

private readonly HttpContext _httpContext;
public ClaimCookie(IHttpContextAccessor contextAccessor)
{
    _httpContext = contextAccessor.HttpContext;
}

Next you need to register both IHttpContextAccessor and ClaimCookie in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpContextAccessor();
    services.AddTransient<ClaimCookie>();
    ...rest of code ommited...
}

Then inject Your class and use is without providing HttpContext by yourself:

public class SomeController : Controller
{
    private readonly ClaimCookie _claimCookie;

    public SomeController(ClaimCookie claimCookie)
    {
        _claimCookie = claimCookie;
    }

    public async Task<IActionResult> SomeAction()
    {
        int id = int.Parse(_claimCookie.GetValue(CookieName.User, KeyName.Id));
        await _claimCookie.SetValue(CookieName.User, new[] { KeyName.Name, KeyName.Surname }, new[] { model.Name, model.Surname });
        ...
    }

Also read msdn's best practices in asynchronous programming why you should't use async void.
And about security (im not an expert) you also shouldn't store sensitive data in cookies, if You need so then store encrypted data.

Upvotes: 2

Related Questions