OAuth2 Interoperability

Ah, what I create about a ResponseFilter that I can remove the session cookies if I detect that my provider is configured in the AuthFeature AND that the request has a Bearer token? Would that work you think?

So I got my CustomAuthProviderReader to set: req.Items["somekey"] = true;, and then configured this in my appHost.Config:

            appHost.GlobalResponseFilters.Add((request, response, dto) =>
            {
                if (request.Items.ContainsKey("somekey"))
                {
                    response.DeleteSessionCookies();
                }
            });

Testing with JsonServiceClient seems to indicate that the cookies have gone.

Do you reckon that this is a safe approach? (I’ve not missed anything)

No it’s not related, Session Cookies are always sent if AuthFeature/SessionFeature is enabled unless you disable them with Config.SetCookie. If you don’t want to disable them entirely, you can override AppHost.AllowSetCookie and chose when Cookies shouldn’t be added.

Deleting Cookies is different to not adding them in the first place as it requires sending an automatically expired cookie which tells the client to remove the Cookie which just like adding Cookies this needs to be done before writing the response body. The behavior is also such that if the client had the Cookies added due to using a different Auth Provider, deleting cookies tells them to remove them as well.

OK, I will try that.

Puzzled. Since the JWTAuthProviderReader is supposed to also do session-less auth with the JWT (like we are with access_token), doesn’t it also not want to send session cookies back? Otherwise, wouldn’t the JsonServiceClient just use the session get automatically authed, and not bother to re-send the JWT bearer token with every request?

Theres no harm in sending Cookies that don’t reference Authenticated User Sessions which can be used for more than just Auth, e.g. Anon SessionBag & Tracking. I’d just be ignoring them if you want to have the least invasive impact.

Are you saying the JwtAuthProviderReader does or does not send session cookies?
If it does, why doesn’t the JsonServiceClient just use that session and NOT bother to send the JWT in every request.

I’ve previously mentioned what sends Cookies:

The SessionFeature Plugin is added by the AuthFeature so if either is registered they will ensure the ss-id/pid Cookies are added.

JWT’s are completely stateless, The Session Cookies are just Id’s so using them means there needs to be an Authenticated User Session persisted on the Server in the registered Caching provider, JWT doesn’t have any such dependencies.

Sorry. I am asking the question in the wrong way. Sorry for the frustration I am causing you, that is not intentional.

I’ll have one last crack at it, if you will permit me?

As you know, my goal is to implement a truly session-less ‘AuthProvider’ of our own that handles OAuth2 ‘access_token’ so we can align our services to the Auth framework of ServiceStack. But we definitely don’t want server-side sessions, or session cookies going to the client. Truly session-less.
The nearest thing we already have to that, it seems, is the JwtAuthProviderReader. which is hailed to be free from state on the server. I want to understand how this provider works on the wire, to see what we can learn from it, and whether we have a different beast or not.

So, to your point, given this is how one would normally configure the JwtAuthProviderReader in their appHost.Configure:

public override void Configure(Container container)
{
    Plugins.Add(new AuthFeature(() => new AuthUserSession(),
        new IAuthProvider[] {
            new JwtAuthProviderReader(AppSettings) {
                HashAlgorithm = "RS256",
                PublicKeyXml = AppSettings.GetString("PublicKeyXml")
            },
        }));
}

It looks like the SessionFeature will always be in play for any AuthProvider, since all AuthProviders are configured in the AuthFeature.
Which means that to use any of the [Authenticate] or [RequireAnyRoles] attributes the AuthProvider is required to set up a session, and populating it with user info and roles etc. Which means the SessionFeature is, by default, writing session cookies in the response. (unless we do something to stop it).

If the client handles those session cookies, like JsonServiceClient does natively, then it will send them back to the service on subsequent calls.
Since the SessionFeature is in play in the service, I presume the client has no obligation to resend the Bearer token, since the session is already established on the server. So we now have session state on the server, no?

We want to get away from any session persistence or any session cookies, and go truly session-less on the server.

So my question to you has been how to do that? In other words how to enforce that a client sends a Bearer token each request, and how not to send session cookies to it.

Now, at this point in the thread much of that has been answered and I have an implementation that does what it should on the wire. I am grateful for that help.
I was just wanting to know (a) if the JwtAuthProviderReader was truly intended to be session-less, and (b) if so, how did it do it, since the code in the JwtAuthProviderReader, gives me no clue how.

It might also be that the JwtAuthProviderReader uses session as all providers do, session cookies goes back and forth to the client, and the client can choose between session-less or not, by including the cookies or not. And that’s fine too. I was looking for affirmation is all.

Right, the SessionFeature ensures the ss-id/ss-pid Cookies are added on Requests that are missing them. It doesn’t require that Sessions are persisted in the Caching Provider, with IAuthWithRequest providers (like JWT) they’re only stored in the incoming IRequest.Items[Keywords.Session] dictionary, not in the Caching provider.

JWT’s are stored in the JWT Format:

{Base64UrlHeader.Base64UrlPayload.Base64UrlSignature}

If it’s configured with a BearerToken, e.g:

var client = new JsonServiceClient(service1BaseUrl) { 
    BearerToken = jwtToken 
};

Then the JWT token is added added to each Request as an Authorization Bearer Token:

Authorization: Bearer {JWT}

It can also be configured with the ss-tok Cookie so it gets sent with every request, which you can do at Authentication with the UseTokenCookie option:

var authResponse = client.Send(new Authenticate {
    provider = "credentials",
    UserName = username,
    Password = password,
    UseTokenCookie = true
});

On Successful Authentication it will set the JWT Token on the ss-tok Cookie which can be retrieved with:

var jwtToken = client.GetTokenCookie(); //From ss-tok Cookie

Both the Cookie and BearerToken are then sent on every request.

Sending Cookies doesn’t force User Sessions to be persisted on the Server. All IAuthWithRequest providers do not persist the User Session, they only populate the Session on the incoming Request’s IRequest.Items[Keywords.Session] dictionary, which anything that validates Authentication (e.g. [Authenticate] or [RequiredRole]) checks first to validate the User.