2

I am developing role based authorization. After role is successfully defined with User.AddIdentity it disappears when I exit the page.

[AllowAnonymous]
[HttpPost]
public IActionResult Index(User user)
{
    try
    {
    var currentUser = _UserService.login(user, _context);                

    if (currentUser.userID != 0)
    {                                        
        CookieOptions options = new CookieOptions();
        options.Expires = DateTime.Now.AddDays(1);

        var identity = new ClaimsIdentity(new[] {
            new Claim(ClaimTypes.Name, currentUser.NAME_SURNAME),                                                
            new Claim(ClaimTypes.Role, "Admin")                        
        },
        "ApplicationCookie");    

        User.AddIdentity(new ClaimsIdentity(identity));

        var isin = User.IsInRole("Admin");

        var cacheValue = _UserService.stringToMd5(currentUser.NAME_SURNAME);
        Response.Cookies.Append("login_cache", cacheValue, options);                                    

        TempData["error"] = null;
        return RedirectToAction("index", "home");
    }
    else
    {
        TempData["error"] = "Kullanıcı adı yada şifre yanlıştır.";
        return RedirectToAction("index", "home");
    }                    
    }
    catch(Exception ex){
        TempData["error"] = ex.Message;
        //TempData["error"] = "User not found.";
        return RedirectToAction("index", "home");
    }
} 


[Area("Admin")]
[Authorize(Roles = "Admin")]
public class FaqController : Controller
{
    ....
}

Startup.cs

public void ConfigureServices(IServiceCollection services) 
{
    services.AddDistributedMemoryCache();
    services.AddSession();
    services.AddSession(options => {
    options.IdleTimeout = TimeSpan.FromMinutes(60);
});

    services.AddMvc();           

    services.AddDbContext<ModelContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseAuthentication();

    app.UseMvc(routes =>
{
    routes.MapRoute(
       name: "admin",
       template: "{area}/{controller=Home}/{action=Index}/{id?}");
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");               
});
}   
2
  • How do you authenticate the user? Please share your startup class Commented Oct 2, 2018 at 10:25
  • I added startup.cs Commented Oct 2, 2018 at 10:50

2 Answers 2

3

You haven't define how the authentication should work for your application. This should be done in the ConfigureServices method in Startup class. There you need to tell the framework to look for a cookie and from that authenticate the user.

I have modify your cookie creation and added the default asp.net core way. I then enabled the cookie authentication by adding AddAuthentication() in the ConfigureServices method by this line

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie();

Here's a full example

[AllowAnonymous]
[HttpPost]
public IActionResult Index(User user)
{
    try
    {
        var currentUser = _UserService.login(user, _context);                
        if (currentUser.userID != 0)
        {                                        
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, currentUser.NAME_SURNAME),                                                
                new Claim(ClaimTypes.Role, "Admin")      
            };

            var claimsIdentity = new ClaimsIdentity(
                claims, CookieAuthenticationDefaults.AuthenticationScheme);

            var authProperties = new AuthenticationProperties
            {
                ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1)
            };

            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme, 
                new ClaimsPrincipal(claimsIdentity), 
                authProperties);

            return RedirectToAction("index", "home");
        }
        else
        {
            TempData["error"] = "Kullanıcı adı yada şifre yanlıştır.";
            return RedirectToAction("index", "home");
        }                    
    }
    catch(Exception ex){
        TempData["error"] = ex.Message;
        //TempData["error"] = "User not found.";
        return RedirectToAction("index", "home");
    }

} 

Then the startup

public void ConfigureServices(IServiceCollection services) 
{
    services.AddDistributedMemoryCache();
    services.AddSession();
    services.AddSession(options => {
        options.IdleTimeout = TimeSpan.FromMinutes(60);
    });

    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie();

    services.AddMvc();           

    services.AddDbContext<ModelContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
           name: "admin",
           template: "{area}/{controller=Home}/{action=Index}/{id?}");
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");               
    });
}   
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much. Can you tell me how to logout process, please?
0

You need a Claim Transformer and you create policies based on roles

//ClaimsTransformer.cs

public class ClaimsTransformer : IClaimsTransformation
{
    private IRepository _repository;
    private IHttpContextAccessor _httpContextAccessor;        
    private IMemoryCache _cache;

    public ClaimsTransformer(IRepository repository, IHttpContextAccessor httpContextAccessor, IMemoryCache cache)
    {
        _repository = repository;
        _httpContextAccessor = httpContextAccessor;           
        _cache = cache;
    }
    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
   {
        if (principal.Identity.IsAuthenticated)
        {
            var currentPrincipal = (ClaimsIdentity)principal.Identity;

            var ci = (ClaimsIdentity)principal.Identity;
            var cacheKey = ci.Name;

            if (_cache.TryGetValue(cacheKey, out List<Claim> claims))
            {
                currentPrincipal.AddClaims(claims);
            }
            else
            {
                claims = new List<Claim>();
                var isUserMasterAdmin = await _repository.IsUserMasterAdmin(ci.Name);
                if (isUserMasterAdmin)
                {
                    var c = new Claim(ClaimTypes.Role, "MasterAdmin");
                    claims.Add(c);
                }

                var isUserDeptAdmin = await _repository.IsUserDeptAdmin(ci.Name);
                if (isUserDeptAdmin)
                {
                    var c = new Claim(ClaimTypes.Role, "DeptAdmin");
                    claims.Add(c);
                }

                _cache.Set(cacheKey, claims);
                currentPrincipal.AddClaims(claims);
            }                
        }

        return await Task.FromResult(principal);
    }
}

//Startup.cs

public void ConfigureServices(IServiceCollection services)
{
   services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
   services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
   ...

   services.AddAuthorization(options =>
        {
            options.AddPolicy("MasterAdminsOnly", policy => policy.RequireClaim(ClaimTypes.Role, "MasterAdmin"));
            options.AddPolicy("AdminsOnly", policy => policy.RequireClaim(ClaimTypes.Role, "MasterAdmin", "DeptAdmin"));
        });
}

//Controller.cs

[Authorize(Policy = "MasterAdminsOnly")]
public class UsersController : Controller
{
  ....
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.