Custom AuthProvider Returning No Response on Error

I implemented the fantastic code linked at the bottom of the ServiceStack Auth documentation for implementing an Auth provider that supports OpenID Connect (http://estynedwards.com/blog/2016/01/30/ServiceStack-IdentityServer-Angular/).

The code works great when it is supposed to, handling the token, checking the group membership, etc. However, if I send a bad token, the server code errors out and no HttpError gets returned to the client (confirmed via Postman as well). Instead we just get “No Response.” When I run it in the debugger, the code internally is failing in the correct place and throwing the correct HttpError exception (e.g. token expired), but for some reason it doesn’t make it back to the client. I’m including my code here, though it is pretty much line for line the code in the article (the only 2 changes being the suggestion made in the comments there on PreAuthenticate to avoid the loop and added storing of the roles).

Why isn’t the HttpError making it back to the client?

 public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
    {
        var header = request.oauth_token;

        // if no auth header, 401
        if (string.IsNullOrEmpty(header))
        {  throw HttpError.Unauthorized(MissingAuthHeader);   }

        var headerData = header.Split(' ');

        // if header is missing bearer portion, 401
        if (string.Compare(headerData[0], "BEARER", StringComparison.OrdinalIgnoreCase) != 0)
        {   throw HttpError.Unauthorized(InvalidAuthHeader);     }

        try
        {    // set current principal to the validated token principal
            ClaimsPrincipal cPrincipal = JsonWebToken.ValidateToken(headerData[1], Certificate, Audience, Issuer);
            Thread.CurrentPrincipal = cPrincipal;

            if (HttpContext.Current != null)
            {
                // set the current request's user the the decoded principal
                HttpContext.Current.User = Thread.CurrentPrincipal;
            }

            // set the session's username to the logged in user
            session.UserName = Thread.CurrentPrincipal.Identity.Name;

            //set the sessions roles to the roles from the token so that authorization works
            session.Roles = (cPrincipal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value)).ToList();

            return OnAuthenticated(authService, session, new AuthTokens(), new Dictionary<string, string>());
        }
        catch (Exception ex)
        {
            throw new HttpError(HttpStatusCode.Unauthorized, ex);
        }
    }

    public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
    {
        return HttpContext.Current.User.Identity.IsAuthenticated && session.IsAuthenticated && string.Equals(session.UserName, HttpContext.Current.User.Identity.Name, StringComparison.OrdinalIgnoreCase);
    }

    public void PreAuthenticate(IRequest request, IResponse response)
    {
        var header = request.Headers["Authorization"];
        using (var authService = HostContext.ResolveService<AuthenticateService>(request))
        {
            authService.Post(new Authenticate
            {
                provider = Name,
                oauth_token = header
            });
        }
    }

}

Can you provide a small stand-alone example so we reproduce the issue and look into it?

And with any interoperability issues like this in future, please always include the raw HTTP Request/Response Headers so we can see exactly what’s being returned.

In case it helps anyone else, I had to modify the PreAuthenticate method do the below and now things work as expected in the case of a bad token being passed. Apparently, raising an HttpError in the preauthenticate method was causing the problem:

public void PreAuthenticate(IRequest request, IResponse response)
    {
        try
        {
            var header = request.Headers["Authorization"];
            using (var authService = HostContext.ResolveService<AuthenticateService>(request))
            {
                authService.Post(new Authenticate
                {
                    provider = Name,
                    oauth_token = header
                });
            }
        }
        catch (Exception ex)
        {
            throw new UnauthorizedAccessException(ex.Message);
        }
    }