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.