I have been trying to find an explanation, but are coming rather short, as to how exactly identity works with mvc core. I have found numerous guides on how to implement it and I have and it all works great, but I want to understand it under the hood at the very least on a high level.
My current understanding is that when a user passes their credentials, identity library will issue a token and that token will be written to the browser's cookies. Now all further requests will have the user identified based on that browser cookie. However, I can't seem to find explanations past that. Why is this safe, why can't I steal that cookie and use it as my own? I know there is more to this and potentially I have understood the above part wrong.
In any case, I'm either looking for a high-level explanation on how this works or a good reference that can delve more into details.
how exactly identity works with mvc core.
As @Chris Pratt says, what you're talking about is the security subsystem. Since you're talking about cookie, I'll take the authentication scheme of cookie as an example.
The built-in security could be mainly found in 4 projects:
The entry point to understand how authentication works is the AuthenticationMiddleware
. This middleware will try to authenticate every request if possible:
public async Task Invoke(HttpContext context)
{
// ...
// Give any IAuthenticationRequestHandler schemes a chance to handle the request
var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
if (handler != null && await handler.HandleRequestAsync())
{
return;
}
}
// Use the default scheme to authenticate request
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
{
context.User = result.Principal;
}
}
await _next(context);
}
Usually, this middleware runs before other middlewares/mvc thus you can intercept requests as you need.
When you want to access an url
protected by [Authorize]
without login, it will ask you to sign in through some scheme. You can configure your services to use different schemes as you like, such as Jwt Bearer, cookies, and so on.
If you're using the cookie scheme, CookieAuthenticationHandler will do the heavy lifting :
Note all these are done by Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler
, i.e. a handler defined in aspnet/Security
, not the aspnet/Identity
library.
why can't I steal that cookie and use it as my own?
Of course you can steal someone's cookie and use it as your own. Actually, if Alice's cookie is stolen by Bob (let's say through XSS
or sniffering
), Bob will be treated as Alice. ASP.NET Core (and other technologies such as PHP/Python/Java) cannot prevent this and there're quite a lot to do to prevent the stealing :
HTTPS
rather than HTTP
<
,>
,<img onclick='javascript:'
and so on to prevent XSSAlso, you don't need to steal someone's cookie sometimes. By CSRF
, you simply "borrow" his cookie.
Why is this safe
Typically, even if it's possible to steal someone's cookie or borrow someone's cookie in theory, it will only happen when you're developing your app in a wrong way or deploy them in an insecure way.
Another thing is that you could hardly fake a cookie on client side.