Servicestack Transparent Server Auto Refresh of JWT Tokens does not work

46 Views Asked by At

I have api service configured to support JWT tokens as below

 appHost.Plugins.Add(new AuthFeature(() => new CustomUserSession(),
     [
     new JwtAuthProvider(appSettings) {
         
         UseTokenCookie = true,
         ExpireTokensIn = TimeSpan.FromMinutes(1),
         ExpireRefreshTokensIn = TimeSpan.FromDays(1)
     },
     new CredentialsAuthProvider(appSettings) {  },
     new GoogleAuthProvider(appSettings) {  }          
     ])
 {
     IncludeDefaultLogin = false,
     ValidateRedirectLinks = AuthFeature.AllowAllRedirects
 });
  • The Servicestack Api is hosted at https://localhost:5555
  • The WASM Blazor client is hosted at https://localhost:5551

The problem is that once Barer Token is expired the ss-tok cookie is not icluded by the browser into http request (the ss-reftok is still included). This results int http response 401 response on any request to api. My question is: do I need to add any custom processing on client or server side to refresh barear token.

update 21/01/2024 in fact I see exception on API server side on attempt to refresh token

fail: ServiceStack.ServiceStackHost[0]
      The input string 'w9YFY55pKWxSNbmwb7HE' was not in a correct format.
      System.FormatException: The input string 'w9YFY55pKWxSNbmwb7HE' was not in a correct format.
         at System.Number.ThrowFormatException[TChar](ReadOnlySpan`1 value)
         at System.Int32.Parse(String s)
         at ServiceStack.Auth.OrmLiteAuthRepositoryBase`2.<>c__DisplayClass87_0.<<GetUserAuthAsync>b__0>d.MoveNext() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Server/Auth/OrmLiteAuthRepositoryAsync.cs:line 325
      --- End of stack trace from previous location ---
         at ServiceStack.Auth.OrmLiteAuthRepository`2.ExecAsync[T](Func`2 fn) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Server/Auth/OrmLiteAuthRepositoryAsync.cs:line 33
         at ServiceStack.Auth.OrmLiteAuthRepositoryBase`2.GetUserAuthAsync(String userAuthId, CancellationToken token) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Server/Auth/OrmLiteAuthRepositoryAsync.cs:line 324
         at ServiceStack.RequestExtensions.GetSessionFromSourceAsync(IRequest request, String userAuthId, Func`3 validator, CancellationToken token) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/RequestExtensions.cs:line 317
         at ServiceStack.RequestExtensions.GetSessionFromSourceAsync(IRequest request, String userAuthId, Func`3 validator, CancellationToken token) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/RequestExtensions.cs:line 332
         at ServiceStack.Auth.JwtAuthProvider.CreateAccessTokenFromRefreshToken(String refreshToken, IRequest req) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Auth/JwtAuthProvider.cs:line 430
         at ServiceStack.Auth.GetAccessTokenService.Any(GetAccessToken request) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Auth/JwtAuthProvider.cs:line 505
         at ServiceStack.Host.ServiceRunner`1.ExecuteAsync(IRequest req, Object instance, TRequest requestDto) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Host/ServiceRunner.cs:line 149

When debugging external sources I see that method public override async Task<string> CreateAccessTokenFromRefreshToken(string refreshToken, IRequest req) takes userId as var userId = jwtPayload["sub"]; which is not int.

It seems that refresh token is created with some non int value for sub

I have resolved the issue by set assigning session.UserAuthId to CustomUserSession.Id in the CustomUserSession.OnAuthenticatedAsync. It works, now the sub of refresh token has the expected integer value. I think there might be issue when authentication is done using Google Auth Provider.

0

There are 0 best solutions below