-1

I am using the uncaught exception handler:

this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) =>
{
    res.WriteErrorBody(ex);
    Log.Error(ex);
    res.EndRequest(skipHeaders: true);
});

Sometimes when I haven't used the project for a while I will get a "Token has expired" exception that hits this handler. It doesn't return a 401 code to my front end so the front-end doesn't discard logon data and prompt user to logon again. There is no reponse data.

This is headers

Request URL: https://localhost:44308/json/reply/BlogsLookUpRequest
Referrer Policy: strict-origin-when-cross-origin
access-control-allow-origin: https://localhost:4200
content-length: 0
date: Sun, 25 Jul 2021 02:54:31 GMT
server: Kestrel
x-powered-by: ASP.NET
:authority: localhost:44308
:method: POST
:path: /json/reply/BlogsLookUpRequest
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en,en-GB;q=0.9
authorization: Bearer omitted
cache-control: no-cache
content-length: 165
content-type: application/json
cookie: omitted
pragma: no-cache
referer: https://localhost:4200/
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36

I tried:

this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) =>
{
    res.WriteErrorBody(ex);
    Log.Error(ex);
    if (ex.GetType() == typeof(TokenException))
    {
        res.StatusCode = 401;
    }
    res.EndRequest(skipHeaders: true);
});

But there is no response so no status code.

I am missing some understanding here as this doesn't always happen. I have frontend coded to direct to logon on a 401 error and that seems to happen in some situations with logon expiry.

Am I doing somethign wrong? How can I get SS to return a 401 when using an expired token?

This is the stack trace:

at ServiceStack.Auth.JwtAuthProviderReader.AssertJwtPayloadIsValid(JsonObject jwtPayload) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Auth\JwtAuthProviderReader.cs:line 779
   at ServiceStack.Auth.JwtAuthProviderReader.CreateSessionFromPayload(IRequest req, JsonObject jwtPayload) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Auth\JwtAuthProviderReader.cs:line 752
   at ServiceStack.Auth.JwtAuthProviderReader.PreAuthenticateAsync(IRequest req, IResponse res) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Auth\JwtAuthProviderReader.cs:line 538
   at ServiceStack.AuthenticateAttribute.<PreAuthenticateAsync>d__20.MoveNext() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 207
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work\191\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) in E:\A\_work\191\s\src\mscorlib\src\System\Runtime\CompilerServices\TaskAwaiter.cs:line 155
   at ServiceStack.AuthenticateAttribute.<ExecuteAsync>d__12.MoveNext() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 77
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work\191\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at ServiceStack.ServiceStackHost.<ApplyRequestFiltersSingleAsync>d__386.MoveNext() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 183
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work\191\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) in E:\A\_work\191\s\src\mscorlib\src\System\Runtime\CompilerServices\TaskAwaiter.cs:line 155
   at ServiceStack.ServiceStackHost.<ApplyRequestFiltersAsync>d__385.MoveNext() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 145
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in E:\A\_work\191\s\src\mscorlib\src\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs:line 132
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) in E:\A\_work\191\s\src\mscorlib\src\System\Runtime\CompilerServices\TaskAwaiter.cs:line 155
   at ServiceStack.Host.Handlers.GenericHandler.<ProcessRequestAsync>d__12.MoveNext() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\GenericHandler.cs:line 57
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Guerrilla
  • 13,375
  • 31
  • 109
  • 210
  • Does this answer your question? [ServiceStack Cors](https://stackoverflow.com/questions/19034514/servicestack-cors) – Jim G. Jul 25 '21 at 03:53

1 Answers1

1

Expired Tokens throw a TokenException which implements IHasStatusCode that does return a 401 Unauthorized HTTP Error.

This is confirmed by our tests as well as all Service Clients Automatically refreshing Access Tokens which relies on expired tokens returning a 401 Unauthorized error response.

Your Response Headers does not include the status code so it can't be determined what the Response Status Code that is actually being returned. I'd suggest using Fiddler so you can capture the raw HTTP Headers which will contain the response status code.

In case your custom error handling logic is interfering with it I would recommend that you don't try to interfere/handle any Exceptions that implement IHasStatusCode, e.g:

this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) =>
{
    if (ex is IHasStatusCode) return;
    res.WriteErrorBody(ex);
    Log.Error(ex);
    res.EndRequest(skipHeaders: true);
});
mythz
  • 141,670
  • 29
  • 246
  • 390