Identity in ASP.NET Core
ASP.NET Core has a built-in identity system that allows to use:
- internal accounts - stored in our database (by default SQL acessed with EF Core)
- external accounts with OpenId Connect
There is middleware for:
- Authentication - sets the
HttpContextif the user is recognized (e.g. via a cookie or token). It uses authentication services to recognize the user.
- Authorization - checks if the endpoint’s requirements are fulfilled. If not, the request is short-circuited.
There is a UI package that contains various account management pages to be used with internal accounts. They can be overriden to customize them.
HttpContext contains the
User property, which is configured via the
Authentication middleware. It contains all the claims of the logged-in user.
AuthorizeAttribute may be applied:
- on controller
- on action
- on Razor Page
If it’s applied globally, but we want to allow anonymous access to some selected
endpoint (e.g. login page), we can use the
AllowAnonymousAttribute to that
[Authorize]- require the user to be logged and nothing more
[Authorize(Admin)]- require the
Adminpolicy to be satisfied
The policies are defined in the
[Authorize] attribute may be applied to an endpoint multiple times. In
such a case all of them have to be satisfied (AND).
Web Apps with UI redirect the user to the login page (if user not logged in) or return a message that access is denied (if user doesn’t meet requirements).
Web APIs return 401 when no access token is attached or 403 if the token doesn’t have the required claims.
Roles vs Claims
Nowadays, it is recommended to use the Claims-based authorization, although the Roles-based model is also available.
Sometimes, to figure out if access shoud be granted, lookin over caller’s claims
is not enough. We might have to call the database and check if the requested
data belongs to the caller. This requires imperative code instead of declarative
way of applying the
The action/Page that requires such authorization can use the
IAuthorizationService (via DI). It allows us to easily execute policies that
we define for our resources during the action/Page execution. It returns either
success or fail result, which we can use to either continue execution or return
To define such custom policies, we need
AuthorizationHandler<T,U>. We also need to registed the policy in bootstrap.