JWT Auth no longer returns bearerToken after upgrade to 4.5.8

After upgrading from 4.5.6 -> 4.5.8, JWT Authentication is no longer working/returning the bearerToken in our authentication requests.

I verified by downgrading back to 4.5.6 that everything still worked without any code changes.

I’m hoping it’s just a config change that I missed in the release notes or otherwise. I do not have a stand alone project (nor do i have time at the moment to create one).

Here are the code snippets of how I have things setup.

 private void ConfigureAuth(Container container)
    {
        IAppSettings appSettings = new AppSettings();
     
        var auth = new AuthFeature(
            () => new CustomUserSession(),
            new IAuthProvider[]
            {
                container.Resolve<MssCredentialsAuthProvider>(),
                new JwtAuthProvider(appSettings){
                    CreatePayloadFilter = (payload,session) =>
                    {
                        CustomUserSession customSession = session as CustomUserSession;

                        payload["userId"] = customSession.UserAuthId;
                        payload["companyId"] = customSession.Company;
                        payload["companyName"] = customSession.CompanyName;
                        payload["companyRoles"] = customSession.CompanyRoles.ToJson();
                    }

                }
            })
        {
            IncludeAssignRoleServices = false,
            IncludeRegistrationService = false,
            IncludeAuthMetadataProvider = false,
            DeleteSessionCookiesOnLogout = true
        };

        Plugins.Add(auth);
    }

My web.config has the following options defined:

<add key="jwt.RequireSecureConnection" value="false" />
<add key="jwt.AuthKeyBase64" value="hidden" />
<add key="jwt.HashAlgorithm" value="HS256" />

The MssCredentialsAuthProvider has the baseclass of CredentialsAuthProvider .

Please see this answer for details OnAuthenticationRequired question

Only requests that authenticate will return the token.

So has the implementation of CredentialsAuthProvider changed? When I call the authentication endpoint to authenticate is when I do not get the token returned. I’ve actually not tried already authenticated requests. Since I subclass it in my auth provider, I’m wondering if there might be something I’m now missing to indicate it’s authenticated and create the token to return?

CredentialsAuthProvider hasn’t changed, what’s changed is that tokens are only returned “on authentication requests”.

What client code are you using to request a token?

Right now I’m testing using Postman as it runs all of our tests. But it also fails in our angular2 app. We are not using any specific servicestack client libraries.

Then you will likely need to explicitly logout (e.g. calling /auth/logout) to force an authentication as authenticating when you’re authenticated currently skips authentication - I’ll look into having this configurable so authentication requests will always authenticate.

But i’m not authenticated. Calling logout does nothing to fix the situation.

I will have to spend some time next week to create a sample project. It’s just not something I have time for this week.
Thanks.

I’ve changed the default behavior where it now lets you re-authenticate if you’re already authenticated (overridable with AuthFeature.SkipAuthenticationIfAlreadyAuthenticated = true) so it should now return the tokens after authenticating multiple times.

This change is available from v4.5.9 which is now available on MyGet.

Thanks. I’ve not gotten the time to get back to looking at this. Just had a big release this week so hoping to look into this again soon.

It’s been a while, but thought I’d update this. After a lot of frustration with my custom AuthProvider not returning the BearerToken I found that there is a DidAuthenticate property on the AuthFilterContext that is looked at in JwtAuthProvider.Execute. It partially determines if a BearerToken can be returned.

So, in our custom AuthProvider I had to make sure i added the following in the OnAuthenticated method.

authService.Request.Items[Keywords.DidAuthenticate] = (object)true;

Once this was added the BearerToken was returned. And, the rest of the comments and linked posts made a lot more sense.

1 Like

For future readers, I did not have to do this:

authService.Request.Items[Keywords.DidAuthenticate] = (object)true;,

but then I’m calling the base method, which probably does it:

return base.OnAuthenticatedAsync(authService, session, tokens, authInfo, token);

However I’ve found two other things that make JwtAuthProvider not return the token in the way you expect:

  1. calling over http without adding RequireSecureConnection=false to the JwtAuthProvider.
  2. Not setting UseTokenCookie=false in the JwtAuthProvider's constructor – bearer token is returned in a cookie instead of the response – so it’s returned but not where you might expect it
1 Like

These are both expected.

Secure HttpOnly Cookies should only be returned over a secure connection unless explicitly disabled and from v6 JWT defaults to using Token Cookies which is the recommended usage or JWTs to prevent XSS attacks from being able to retrieve JWT Auth Tokens returned in HTTP Response payloads.

I did not know about that new JWT recommendation. SS keeps me up to date and was the first place I heard about Svelte actually.

Did not intend this as a bug report at all, just helping people out where to find stuff.

JWT over regular http is quite useful if HTTPS is terminated on the web server or a load balancer. Of course not recommended otherwise.

Many older clients probably still fetch bearer token from response, so if suddenly it doesn’t work after an upgrade it useful to know why and where it has gone to.

2 Likes

Thanks for this.

I was looking all over to figure out what was missing, and it was the UserTokenCookie = false setting that fixed it for us.

1 Like