Repository: quarkusio/quarkus
Issue: 'The supplier returned null' message if OIDC server connection fails 

### Describe the bug

Is it really fixed here https://github.com/quarkusio/quarkus/pull/26661 ? 
I am using oidc-client and followed this [guide](https://quarkus.io/guides/security-openid-connect-client-reference) for config. I am hitting head for many hours without knowing where is error and  why NPE. I don't know why there is no explicit message.

**Error:**
{"timestamp":"2022-09-02T15:22:14.35Z","sequence":99,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus.runtime.Application","level":"ERROR","message":"Failed to start application (with profile prod)","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"powo-backend-staging-7c8f5f7787-vf7xb","processName":"quarkus-run.jar","processId":1,"stackTrace":"java.lang.NullPointerException: The supplier returned `null`\\n\\tat io.smallrye.mutiny.operators.uni.UniOnFailureTransform$UniOnFailureTransformProcessor.onFailure(UniOnFailureTransform.java:62)\\n\\tat io.smallrye.mutiny.operators.uni.builders.UniCreateFromPublisher$PublisherSubscriber.onError(UniCreateFromPublisher.java:81)\\n\\tat io.smallrye.mutiny.helpers.HalfSerializer.onError(HalfSerializer.java:56)\\n\\tat io.smallrye.mutiny.helpers.StrictMultiSubscriber.onFailure(StrictMultiSubscriber.java:91)\\n\\tat io.smallrye.mutiny.subscription.MultiSubscriber.onError(MultiSubscriber.java:73)\\n\\tat io.smallrye.mutiny.subscription.SerializedSubscriber.onFailure(SerializedSubscriber.java:102)\\n\\tat io.smallrye.mutiny.operators.multi.MultiRetryWhenOp$RetryWhenOperator.testOnFailurePredicate(MultiRetryWhenOp.java:136)\\n\\tat io.smallrye.mutiny.operators.multi.MultiRetryWhenOp$RetryWhenOperator.onFailure(MultiRetryWhenOp.java:119)\\n\\tat io.smallrye.mutiny.subscription.MultiSubscriber.onError(MultiSubscriber.java:73)\\n\\tat io.smallrye.mutiny.converters.uni.UniToMultiPublisher$UniToMultiSubscription.onFailure(UniToMultiPublisher.java:103)\\n\\tat io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:54)\\n\\tat io.smallrye.mutiny.vertx.AsyncResultUni.lambda$subscribe$1(AsyncResultUni.java:37)\\n\\tat io.smallrye.mutiny.vertx.DelegatingHandler.handle(DelegatingHandler.java:25)\\n\\tat io.vertx.ext.web.client.impl.HttpContext.handleFailure(HttpContext.java:386)\\n\\tat io.vertx.ext.web.client.impl.HttpContext.execute(HttpContext.java:380)\\n\\tat io.vertx.ext.web.client.impl.HttpContext.next(HttpContext.java:355)\\n\\tat io.vertx.ext.web.client.impl.HttpContext.fire(HttpContext.java:322)\\n\\tat io.vertx.ext.web.client.impl.HttpContext.fail(HttpContext.java:303)\\n\\tat io.vertx.ext.web.client.impl.HttpContext.lambda$handleCreateRequest$6(HttpContext.java:486)\\n\\tat io.vertx.core.impl.future.FutureImpl$3.onFailure(FutureImpl.java:153)\\n\\tat io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:75)\\n\\tat io.vertx.core.impl.future.FutureImpl.tryFail(FutureImpl.java:230)\\n\\tat io.vertx.core.impl.future.PromiseImpl.tryFail(PromiseImpl.java:23)\\n\\tat io.vertx.core.http.impl.HttpClientImpl.lambda$doRequest$8(HttpClientImpl.java:645)\\n\\tat io.vertx.core.net.impl.pool.Endpoint.lambda$getConnection$0(Endpoint.java:52)\\n\\tat io.vertx.core.http.impl.SharedClientHttpStreamEndpoint$Request.handle(SharedClientHttpStreamEndpoint.java:162)\\n\\tat io.vertx.core.http.impl.SharedClientHttpStreamEndpoint$Request.handle(SharedClientHttpStreamEndpoint.java:123)\\n\\tat io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:55)\\n\\tat io.vertx.core.impl.ContextBase.emit(ContextBase.java:239)\\n\\tat io.vertx.core.net.impl.pool.SimpleConnectionPool$ConnectFailed$1.run(SimpleConnectionPool.java:384)\\n\\tat io.vertx.core.net.impl.pool.CombinerExecutor.submit(CombinerExecutor.java:50)\\n\\tat io.vertx.core.net.impl.pool.SimpleConnectionPool.execute(SimpleConnectionPool.java:245)\\n\\tat io.vertx.core.net.impl.pool.SimpleConnectionPool.lambda$connect$2(SimpleConnectionPool.java:259)\\n\\tat io.vertx.core.http.impl.SharedClientHttpStreamEndpoint.lambda$connect$2(SharedClientHttpStreamEndpoint.java:104)\\n\\tat io.vertx.core.impl.future.FutureImpl$3.onFailure(FutureImpl.java:153)\\n\\tat io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:75)\\n\\tat io.vertx.core.impl.future.FutureImpl.tryFail(FutureImpl.java:230)\\n\\tat io.vertx.core.impl.future.Composition$1.onFailure(Composition.java:66)\\n\\tat io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:75)\\n\\tat io.vertx.core.impl.future.FailedFuture.addListener(FailedFuture.java:98)\\n\\tat io.vertx.core.impl.future.Composition.onFailure(Composition.java:55)\\n\\tat io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:75)\\n\\tat io.vertx.core.impl.future.FutureImpl.tryFail(FutureImpl.java:230)\\n\\tat io.vertx.core.impl.future.PromiseImpl.tryFail(PromiseImpl.java:23)\\n\\tat io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:55)\\n\\tat io.vertx.core.impl.ContextBase.emit(ContextBase.java:239)\\n\\tat io.vertx.core.net.impl.NetClientImpl.failed(NetClientImpl.java:302)\\n\\tat io.vertx.core.net.impl.NetClientImpl.lambda$connectInternal$4(NetClientImpl.java:270)\\n\\tat io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578)\\n\\tat io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:552)\\n\\tat io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:491)\\n\\tat io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:184)\\n\\tat io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:35)\\n\\tat io.vertx.core.net.impl.NetClientImpl.connectInternal(NetClientImpl.java:256)\\n\\tat io.vertx.core.net.impl.NetClientImpl.lambda$connectInternal$5(NetClientImpl.java:275)\\n\\tat io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)\\n\\tat io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)\\n\\tat io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)\\n\\tat io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:503)\\n\\tat io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)\\n\\tat io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)\\n\\tat io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)\\n\\tat java.base/java.lang.Thread.run(Thread.java:833)\\n"}
{"timestamp":"2022-09-02T15:22:14.351Z","sequence":100,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus.runtime.Application","level":"DEBUG","message":"Stopping application","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"powo-backend-staging-7c8f5f7787-vf7xb","processName":"quarkus-run.jar","processId":1}
{"timestamp":"2022-09-02T15:22:14.352Z","sequence":101,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus.runtime.Application","level":"DEBUG","message":"Shutting down with exit code 1","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"powo-backend-staging-7c8f5f7787-vf7xb","processName":"quarkus-run.jar","processId":1}

### Expected behavior

The message "OIDC Server is not available" should be thrown instead of NPE

### Actual behavior

java.lang.NullPointerException: The supplier returned `null`

### How to Reproduce?

**My code :** 
@Path("/auth")
public class LoginResource {
    @Inject
    OidcClient oidcClient;
    
    public Response ssoAuthentication(@QueryParam("code") String code) {
        Map<String, String> grantParams = new HashMap<>();
        grantParams.put(OidcConstants.CODE_FLOW_CODE, code);
        grantParams.put(OidcConstants.CODE_FLOW_REDIRECT_URI, redirectUriParam);
        Tokens tokens = oidcClient.getTokens(grantParams).await().indefinitely();
         Cookie cookieAccessToken = Cookie.cookie("accesstoken", accessToken).setSameSite(CookieSameSite.STRICT).setMaxAge(tokens.getAccessTokenExpiresAt());
         return Response.status(RestResponse.Status.FOUND).location(uri)
                .header(HttpHeaders.SET_COOKIE, cookieAccessToken.encode())
   }
}

**My application.properties:**
quarkus.oidc-client.auth-server-url=https://auth.tech.okta
quarkus.oidc-client.client-id=aaaaa-bbbbbb-cccc-dddd-fffff
quarkus.oidc-client.credentials.client-secret.value=zsdsfdazerty
quarkus.oidc-client.credentials.client-secret.method=post
quarkus.oidc-client.grant.type=code

### Output of `uname -a` or `ver`

_No response_

### Output of `java -version`

_No response_

### GraalVM version (if different from Java)

_No response_

### Quarkus version or git rev

2.11.1.Final

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

_No response_

### Additional information

_No response_

Changed files:
extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java
extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java

diff --git a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java
index bbb62b55b0c..38b79326312 100644
--- a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java
+++ b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java
@@ -124,7 +124,7 @@ public Uni<Tokens> get() {
                         .atMost(oidcConfig.connectionRetryCount)
                         .onFailure().transform(t -> {
                             LOG.warn("OIDC Server is not available:", t.getCause() != null ? t.getCause() : t);
-                            // don't wrap t to avoid information leak
+                            // don't wrap it to avoid information leak
                             return new OidcClientException("OIDC Server is not available");
                         });
                 return response.onItem()
diff --git a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java
index 8d81feff307..6afd8a46642 100644
--- a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java
+++ b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java
@@ -409,7 +409,11 @@ public static Uni<JsonObject> discoverMetadata(WebClient client, String authServ
                 .retry()
                 .withBackOff(CONNECTION_BACKOFF_DURATION, CONNECTION_BACKOFF_DURATION)
                 .expireIn(connectionDelayInMillisecs)
-                .onFailure().transform(t -> t.getCause());
+                .onFailure().transform(t -> {
+                    LOG.warn("OIDC Server is not available:", t.getCause() != null ? t.getCause() : t);
+                    // don't wrap it to avoid information leak
+                    return new RuntimeException("OIDC Server is not available");
+                });
     }
 
     private static byte[] getFileContent(Path path) throws IOException {
diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
index dce213e2786..817a1a5b206 100644
--- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
+++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
@@ -578,7 +578,10 @@ private void createRealm(String keycloakUrl, RealmRepresentation realm) {
                     .retry()
                     .withBackOff(Duration.ofSeconds(2), Duration.ofSeconds(2))
                     .expireIn(10 * 1000)
-                    .onFailure().transform(t -> t.getCause());
+                    .onFailure().transform(t -> {
+                        return new RuntimeException("Keycloak server is not available"
+                                + (t.getMessage() != null ? (": " + t.getMessage()) : ""));
+                    });
             realmStatusCodeUni.await().atMost(Duration.ofSeconds(10));
         } catch (Throwable t) {
             LOG.errorf("Realm %s can not be created: %s", realm.getRealm(), t.getMessage());