Park Jay
Park Jay

Reputation: 279

How can we catch unauthorized exception which been thrown by quarkus

I am facing this problem but don't know how to achieve it.

I have a graphql endpoint to fetch list of user, it already enabled authentication check. Basically, when I send a request fetchUsers without authorization header it will throw exception or status code to let the user know, but currently, it just response

{
    "errors": [
        {
            "message": null,
            "locations": [
                {
                    "line": 2,
                    "column": 3
                }
            ],
            "path": [
                "fetchUsers"
            ],
            "extensions": {
                "classification": "DataFetchingException"
            }
        }
    ],
    "data": {
        "fetchUsers": null
    }
}

And in the backend server, there have some exception throw:

SRGQL012000: Data Fetching Error: io.quarkus.security.UnauthorizedException
        at io.quarkus.security.runtime.interceptor.check.AuthenticatedCheck.apply(AuthenticatedCheck.java:28)
        at io.quarkus.security.runtime.interceptor.SecurityConstrainer.check(SecurityConstrainer.java:28)
        at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Subclass.check$$superforward1(SecurityConstrainer_Subclass.zig:100)
        at io.quarkus.security.runtime.interceptor.SecurityConstrainer_Subclass$$function$$1.apply(SecurityConstrainer_Subclass$$function$$1.zig:41)
        at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
        at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
        at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:49)
        at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(InvocationInterceptor_Bean.zig:521)

Is there any way to catch this Unauthorized exception and custom it, to response 401 and the error message that we want to response.

Upvotes: 2

Views: 1258

Answers (1)

Borislav Gizdov
Borislav Gizdov

Reputation: 1960

You can use ExceptionMapper<UnauthorizedException> to handle this type of exception. However, it did not work before Quarkus version v2.14.x. If you are using an older version, try updating first and then implementing the mapper. I spent a lot of time struggling with this until I found a solution.

Here's an example code that handles the exception and displays the error in JSON format:

package org.acme.filters;

import io.quarkus.security.UnauthorizedException;
import io.vertx.core.http.HttpServerRequest;
import javax.inject.Inject;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.jboss.logging.Logger;

/**
 * The type Unauthorized error mapper.
 * Requires quarkus 2.14.+ to work.
 */
@Provider
public class UnauthorizedErrorMapper implements ExceptionMapper<UnauthorizedException> {
  @Inject
  Logger log;

  @Context
  UriInfo info;

  @Context
  HttpServerRequest request;
  private static final Response.Status status = Response.Status.UNAUTHORIZED;

  @Override
  public Response toResponse(UnauthorizedException exception) {
    log.warn(exception.getMessage(), exception);
    String message = exception.getMessage();
    int code = status.getStatusCode();
    String unauthorized = status.getReasonPhrase().toLowerCase();
    var error = new ErrorResponse(code, message, unauthorized);
    return Response
        .status(code)
        .entity(error)
        .build();
  }
}

I created a sample project with Quarkus v2.16.7 for handling authentication exceptions such as "Forbidden", "Unauthorized", and "Authenticated Failed".

https://github.com/bgizdov/quarkus-authentication-exceptions-handling

Upvotes: 0

Related Questions