simpleidserver / SimpleIdServer

OpenID, OAuth 2.0, SCIM2.0, UMA2.0, FAPI, CIBA & OPENBANKING Framework for ASP.NET Core
https://simpleidserver.com/
Apache License 2.0
693 stars 91 forks source link

Can't handle SCIM Internal Server Errors #573

Closed LazaroOnline closed 1 month ago

LazaroOnline commented 10 months ago

We need a way to handle Internal server errors (500) generated in SCIM APIs that allows to handle the request in a different way and possibly return different responses other than 500 in the case of a known issue that should not be 500 but for example 400 instead.

The problem is those controllers are wrapped inside a try {... } catch (Exception ex) {} that catches all exceptions of all types in the BulkController.cs and the BaseApiController.cs. While I could write a middleware that checks if the response status code was 500, it is too late and the response was already sent to the client.

Possible solutions would be:

function bool MyOnInternalServerErrorHandler(HttpContext context, Exception exception) { bool isHandled = false; if (IsKnownIssue(exception)) { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; context.Response.ContentType = MediaTypeNames.Application.Json; isHandled = true; } return isHandled ; }


Then in SCIM BaseApiController.cs:
```cs
....
catch(Exception ex)
{
    var isHandledError = _options.OnInternalServerError?.Invoke(HttpContext, ex) ?? false;
    if (!isHandledError ) {
        _logger.LogError(ex, ex.Message);
        return this.BuildError(HttpStatusCode.InternalServerError, ex.Message, SCIMConstants.ErrorSCIMTypes.InternalServerError);
    }
}
simpleidserver commented 10 months ago

Hello,

First thank you for your proposal :) We have made some changes in the release\4.0.4 branch to support your requirement. You can easily subscribe to internal server errors like this and return a custom error message. If NULL is returned, then the default result will be returned. The function takes the following parameters on entry:

services.AddSIDScim(_ =>
{
    _.IgnoreUnsupportedCanonicalValues = false;
    _.IsNoContentReturned = false;
    _.SCIMEvents = new SCIMHostEvents
    {
        OnInternalServerError = async (ctx, e, c) =>
        {
            var contentResult = new ContentResult();
            contentResult.StatusCode = 400;
            contentResult.Content = JsonSerializer.Serialize(new
            {
                message = "hello"
            });
            contentResult.ContentType = "application/json";
            return contentResult;
        }
    };
});

KR,

SID

LazaroOnline commented 10 months ago

Thanks a lot! that's exactly what we needed in our project. I could not test it though because we need to migrate first to the latest version, but once we do we will use this!