2

I am facing following issue: I am trying to secure my ASP.NET Core Web API by using role-based authentication.

I have added the following lines to ConfigureServices():

// Authorization
services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddDefaultTokenProviders()
        .AddEntityFrameworkStores<ApplicationDbContext>();
services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/api/Account/Login";
        options.AccessDeniedPath = "/api/Account/AccessDenied";
        options.SlidingExpiration = true;
    });

And to Configure():

// Authorization
app.UseAuthentication();

using (var scope = app.ApplicationServices.CreateScope())
{
    CreateRoles(scope.ServiceProvider.GetService<RoleManager<IdentityRole>>()).Wait();
    CreateUsers(scope.ServiceProvider.GetService<UserManager<ApplicationUser>>()).Wait();
}

CreateRoles() and CreateUsers() are working fine: these methods create some roles and an admin user, store them in the corresponding SQL tables and in the user/role manager.

Now I am able to protect my controllers with [Authorize]. Accessing API calls that are tagged with [AllowAnonymous] is possible.

But how can I log in to the API and access the other API calls?

To do that, I have created an account controller as follows:

[Route("/api/Account")]
public class AccountController : Controller
{
    public AccountController()
    {
    }

    [HttpPost]
    [Route("Login")]
    public async Task<IActionResult> Login()
    {
    }
}

I have read many articles on this topic, but I can not get the login up and running. So the goal is to log in with a user stored in the User Manager and access some API calls that require authentication. Could someone try to explain how I can achieve it?

1 Answer 1

2

You need to use SignInManager<>.PasswordSignInAsync() to sign in user. It will assign necessary cookies to process authentication. It may look like this:

public class AccountController : Controller
{
    private readonly SignInManager<ApplicationUser> _signInManager;
    public AccountController(SignInManager<ApplicationUser> signInManager)
    {
        _signInManager = signInManager;
    }

    public async Task<IActionResult> Login(string login, string password)
    {
        var result = await _signInManager.PasswordSignInAsync(login, password, true, lockoutOnFailure: false);

        if (result.Succeeded)
        { 
            //process successful result
        }
        else
        {
            //process failed result
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much. That's exactly what I was looking for. I didn't know that there is something like a SignInManager. I've changed my code and it all works fine. One last question (little bit off-topic): I've noticed that I get an error 404 if I try to access an API call that needs authentication without beeing authenticated. Is it possible to change this status code to something meaningful, e.g. 401 by default?
I'm not sure why it happens in your case. It may be related to cookies handler managed by Identity that tries to redirect unauthorized requests. Try to see this answer
Thank you. I will have a look at this link.

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.