Custom sessions, auth and jwt

Hi,

I have a requirement to implement a number of custom two-step authentication scenarios and would like to try and encapsulate them into a library for reuse between a number of different applications.

I am describing one below but there are several, all slightly different in formats/payloads and req/res requirements.


An incoming request contains a data payload. This data payload needs to be validated, any credentials in the payload authenticated or digital signatures verified.

A custom response needs to be serialised back to the client containing a pre-authenicated url
(no control over how that url is called in terms of verb, cookies or headers unfortunately so will be a GET request)

I’ve implemented a plugin which takes care of registering a service + some provider config options and dependencies, requestbinders for DTO custom deserialization and the validators for the incoming DTO’s

From the service, I can send an Authenicate { provider = "myprovider" Username="" Password="" } request to my custom authprovider via the gateway.

The authprovider picks up various configuration options and defaults, combines with my services authentication request, the original incoming DTO containing the payload and populates a custom session.

I also have a JWTAuthProvider registered in my AppHost project (with allowqueryparam options set) so my authenticate request returns a bearer token for me to append to a url and therefore get a preauthenicated url.

The preauth url is picked up by the JWTAuthProvider, verified and authenicated first.
It then hits my custom auth service endpoint.
The token is the converted into a session token cookie ‘ss-tok’ before finally redirecting the client to the secure content or
serializing the response back into whatever format is required depending on the authprovider.

The incoming request using this preauth url is not certain to be the original caller so no cookies etc can be relied upon and it requires the information that was sent in the initial request.

It doesn’t feel right though and there are a number of issues.

First of all, am I missing a trick here … the why are you not just doing/using…

Second, if not, I have a few questions which I hoping some helpful soul can nudge me in the right direction.

Questions:

  1. Is there are nice way to register a custom AuthProvider to the AuthFeature from with a plugin?

  2. Ideally the token should be single use, invalidated once redeemed. How can I invalidate the JWT and either a) get a new one or b) reconnect to the session populated in the initial request? (could perhaps just stash it in the cache I suppose)

  3. JWT sessions are rehydrated from the payload, the payload doesn’t contain the various different data payloads I need to support and some are quite large, I’m not sure it would be practical to have this information in the JWT and there are numerous different payloads required.

  4. I’m fine with using sessions and throwing away the JWT after it has been redeemed but I cannot seem to reload/reconnect to the session that was created/populated in the AuthProvider and therefore the information sent in the initial request is lost.

  5. I would prefer to use custom sessions or JWT payload rather than have to customise the custom userauth tables and the information is scoped per session rather than per user anyway.

Hope that makes some kind of sense…!

Thanks in advance.

I can’t really tell, the process is kind of vague so I’m not really sure what’s required due to your custom impl or whether it’s the simplest solution for what you’re trying to achieve. Without knowing your requirements, my general inclination would be to generate a token (e.g. Guid) store it in the database and return a link containing the token the user can use to authenticate with where I’d also use it to create a JWT for the User and return a ss-tok Cookie.

I’ve just added a AuthFeature.RegisterAuthProvider() API you can use in this commit. So if your plugin implements IPreInitPlugin, you can register an AuthProvider with:

public void Configure(IAppHost appHost)
{
    appHost.GetPlugin<AuthFeature>().RegisterAuthProvider(myAuthProvider);
}

This change is available from v5.1.1 that’s now available on MyGet.

This is why I’d look at storing a token in a database which is invalidated when a user authenticates with it. The JwtAuthProvider has an ValidateToken API’ you can use to add custom validation for JWT Auth requests but the beauty of JWT is that it’s self-encapsulated, require no external validation and is valid up to its expiry date. JWTs are designed so any server validation should applied when creating the token which is valid up to the expiration date. Applying per-request validation ruins the encapsulated stateless benefits of JWT, it also invalidates the implied contract that it’s valid until it expires.

You’d use Refresh Tokens to fetch a new JWT token with the latest User Session information and minimize the duration of stale session information in the JWT. It’s also where you’d apply any server validation and prevent users from being able to call Authenticated Services without Authenticating again.

That’s the balance you’d need to decide on. Generally JWTs contain the minimum session info to call Authenticated requests like the User Id, Name and any Roles/Permissions and validity (e.g. expiry). Any additional info you can just lookup on the server when you need to by userId.

1 Like

@mythz thanks for that, it is a bit vague I know but thanks for the auth register hook and I think just storing a token is a better way to go. Some food for thought :smile:

FYI I’ve resolved the previous issue with Sessions.

@mythz cheers I did wonder if it was me as I’d been working on a number of changes