Rest – Stateful authentication in REST API using tokens

asp.net-coreasp.net-mvc-web-apiauthenticationrestweb-api

I have recently started on a project involving a REST API. The API requires authentication with requirements for administrators to be able to view logged in users and to be able to revoke specific login-sessions immediately. The API is consumed primarily by a SPA and a native application.

During my search for existing implementations in ASP.NET Core 2x I am however having some trouble. It seems there are 4 main methods of authentication:

  1. Cookie-based
  2. JSON Web Tokens
  3. OAuth 1 and 2
  4. 3rd party services such as Microsoft, Google, Twitter etc.

Due to the API being consumed by a native application cookie based authentication isn't viable. There is no requirement for integration with 3rd parties (such as Google), so that isn't an option either. Much like in the same way there is no requirement for the API to be consumed by an unknown number of 3rd party applications, which effectively rules out OAuth.

Now I am left with JSON Web Tokens, but… They also have issues. Mainly the requirement of immediate revocation of logins is important, however, this is not possible when using JWTs. A possible solution is maintaining a revocation list, but that defeats their stateless nature as each request to the API would need to check this list. But as this is not a large-scale application the stateless feature is unimportant at the moment. I can't use tokens with a short lifetime either as the requirement for immediate revocation doesn't work well with this. Here is an article, which perfectly explains my issues with JWTs as sessions.

So now we are at the big problem. There are no existing solutions supported out of the box in ASP.NET Core available.

Question 1: Any alternatives or remarks of the previously mentioned issues, which would change the conclusion?

I have searched the vast space that is the internet for anything, which would meet the requirements, but is unable to find anything else, but JWTs and OAuth… Everyone uses JWTs for everything it seems. So this has led me to what I feared: I need to write my own implementation 🙁

The optimal solution would be:

  1. The client exchanges username/password for a random token
  2. The client sends the token in the Authorization HTTP header much like JWT may do.
  3. The token is used to fetch the user's AuthenticationTicket upon an incoming request and the token is verified.
  4. Logouts or revocation removes the token (and effectively the AuthenticationTicket) in a centralized store

Looking through the source code for the existing solutions for mainly JWT and Cookie authentication in ASP.NET Core I realize I can reuse quite a bit of the existing implementations and integrate well with the framwork, but I would rather avoid writing anything security related myself.

Question 2: Anyone know an implementation, which satisfies this flow or can be configured to?

As a closing note. I know storing session state server-side is against pure REST principles, but I find this far more practical given the requirements. To overcome any scaling issues over a small number of containers I plan to use a centralized server (redis as an example) as cache/storage, which should be more than enough to handle the expected traffic several times over.

Best Answer

Question 1: Any alternatives or remarks of the previously mentioned issues, which would change the conclusion?

Cookies are just headers, your native client can add and read them them no problem. Not sure if the built in solution allows revocation though.

JWT/OAuth The reason revocation isnt supported is to enable to idea that resources can validate the request without contacting a central server. Avoiding that bottleneck

However! any solution with immediate revocation will require that you validate on a central server.

Implementing this extra check is simple. eg with the IdentityModel nuget

public class MyJwtSecurityTokenHandler : System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler
{
    public override ClaimsPrincipal ValidateToken(string token, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
    {
       return  myAuthService.ValidateToken(token, validationParameters, out validatedToken);
    }
}

The auth server can keep track of issued tokens, expose a revoke endpoint and a LoggedInUsers endpoint. Just like the old MembershipProvider...

Question 2: Anyone know an implementation, which satisfies this flow or can be configured to?

You want an out of the box solution, MembershipProvider and getting your native client to understand cookies is probably the closest you will get. You could go for the Cookieless option, but having the token in the url is considered less secure and its probably hard to handle on the client anyway.

But with .net Core, I'm unsure that it fulfils all your goals, and it's definitely swimming against the tide of JWT tokens with claims.

I would go with OAuth and JWT and program the revocation custom extras myself. Ensuring that I do validate the JWT normally as well as checking for revocation.

I would expect the requirement for logged in users and revocation to eventually be dropped and this would allow me to simply remove it.

In Fact, lets move the logged in users right out to a reporting component rather than auth, we can get better stats that way anyway

Related Topic