In this article I will demonstrate how to restrict controller access to users that have already logged in. In the second part I will show how to do authentication using a REST Controller.
Access Restriction
In order to restrict access to a Controller you only have to add the Authorize Attribute to Controller as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[Route("api/[controller]")] [Authorize] public class StatisticController : Controller { private readonly AppContext _db; public StatisticController(AppContext db) { _db = db; } [HttpGet] public IActionResult Get() { ... } } |
After adding this Attribute all consumers of this REST service that are not logged in will get a status code 302 redirect to the default login location. I will demonstrate how this location and behavior can be modified in a future article.
In my example all logged in users should have access to the Controller. By modifying the Authorize attribute, you can also check for claims and roles instead.
Authentication – Log in and Log out via REST
Because my application is a Single Page Application (SPA) using AngularJS, I want to be able to log in and out via REST API calls via JavaScript.
Therefore I had to create a new AuthController shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class AuthController : Controller { private readonly SignInManager<AppUser> _signInManager; public AuthController(SignInManager<AppUser> signInManager) { _signInManager = signInManager; } [HttpPost] [Route("api/[controller]/login")] public async Task<IActionResult> Login([FromBody] LoginParams loginParams) { var res = await _signInManager.PasswordSignInAsync(loginParams.Username, loginParams.Password,true,true); if (!res.Succeeded) { return HttpUnauthorized(); } return Ok(); } [HttpPost] [Route("api/[controller]/logout")] public async Task<IActionResult> Logout() { await _signInManager.SignOutAsync(); return Ok(); } [HttpGet] [Route("api/[controller]/status")] public IActionResult Status() { return Ok(User.Identity.IsAuthenticated); } } |
In order to sign in, sign out or check for login status a SignInManager object is injected into the constructor. This class has not to be specifically registered in the Startup.cs and is provided by default.
LoginParams is a simple class consisting of a username and password as shown below:
1 2 3 4 5 |
public class LoginParams { public string Username { get; set; } public string Password { get; set; } } |
After you posted a username and password to
1 |
api/auth/login |
you are logged in and should be able to access all Controllers protected by the Authorize attribute. Keep in mind that you should not protect the AuthController itself by an Authorize attribute. Otherwise you can only log in if you are already authenticated 🙂
Summary
This article demonstrates how to log in, log out or check for login state via a REST Controller using ASP .NET 5 Identity. There is one caveat, however. While returning a 302 redirect to the login page for unauthenticated users is great, if you are directly visiting a REST controller via the browser, I would prefer a 401 unauthenticated for ajax requests. This is not the case by default, however. So if you consume the REST service and are not logged, the response will be the content of the login page. I will show how to change the status code for API calls to 401 in the next article.