Code review comment: But if I throw a `OIDCException` it is going to retry the discovery, right ? I just want to fail fast.

Code before review:
private TenantConfigContext createTenantContext(Vertx vertx, OidcTenantConfig oidcConfig, String tenantId) {
if (!oidcConfig.tenantEnabled) {
LOG.debugf("%s tenant configuration is disabled", tenantId);
return null;
}
OAuth2ClientOptions options = new OAuth2ClientOptions();
if (oidcConfig.getClientId().isPresent()) {
options.setClientID(oidcConfig.getClientId().get());
}
if (oidcConfig.getToken().issuer.isPresent()) {
options.setValidateIssuer(false);
}
if (oidcConfig.getToken().getExpirationGrace().isPresent()) {
JWTOptions jwtOptions = new JWTOptions();
jwtOptions.setLeeway(oidcConfig.getToken().getExpirationGrace().get());
options.setJWTOptions(jwtOptions);
}
if (oidcConfig.getPublicKey().isPresent()) {
if (oidcConfig.applicationType == ApplicationType.WEB_APP) {
throw new ConfigurationException("'public-key' property can only be used with the 'service' applications");
}
LOG.info("'public-key' property for the local token verification is set,"
+ " no connection to the OIDC server will be created");
options.addPubSecKey(new PubSecKeyOptions()
.setAlgorithm("RS256")
.setPublicKey(oidcConfig.getPublicKey().get()));
return new TenantConfigContext(new OAuth2AuthProviderImpl(vertx, options), oidcConfig);
}
if (!oidcConfig.getAuthServerUrl().isPresent() || !oidcConfig.getClientId().isPresent()) {
throw new ConfigurationException(
"Both 'auth-server-url' and 'client-id' or alterntively 'public-key' must be configured"
+ " when the quarkus-oidc extension is enabled");
}
options.setSite(oidcConfig.getAuthServerUrl().get());
if (oidcConfig.getIntrospectionPath().isPresent()) {
options.setIntrospectionPath(oidcConfig.getIntrospectionPath().get());
}
if (oidcConfig.getJwksPath().isPresent()) {
options.setJwkPath(oidcConfig.getJwksPath().get());
}
Credentials creds = oidcConfig.getCredentials();
if (creds.secret.isPresent() && (creds.clientSecret.value.isPresent() || creds.clientSecret.method.isPresent())) {
throw new ConfigurationException(
"'credentials.secret' and 'credentials.client-secret' properties are mutually exclusive");
}
if (creds.secret.isPresent()
|| creds.clientSecret.value.isPresent()
&& creds.clientSecret.method.orElseGet(() -> Secret.Method.BASIC) == Secret.Method.BASIC) {
options.setClientSecret(creds.secret.orElseGet(() -> creds.clientSecret.value.get()));
} else {
options.setClientSecretParameterName(null);
}
Optional<ProxyOptions> proxyOpt = toProxyOptions(oidcConfig.getProxy());
if (proxyOpt.isPresent()) {
options.setProxyOptions(proxyOpt.get());
}
if (oidcConfig.tls.verification == Verification.NONE) {
options.setTrustAll(true);
options.setVerifyHost(false);
}
final long connectionDelayInSecs = oidcConfig.getConnectionDelay().isPresent()
? oidcConfig.getConnectionDelay().get().toMillis() / 1000
: 0;
final long connectionRetryCount = connectionDelayInSecs > 1 ? connectionDelayInSecs / 2 : 1;
if (connectionRetryCount > 1) {
LOG.infof("Connecting to IDP for up to %d times every 2 seconds", connectionRetryCount);
}
OAuth2Auth auth = null;
for (long i = 0; i < connectionRetryCount; i++) {
try {
CompletableFuture<OAuth2Auth> cf = new CompletableFuture<>();
KeycloakAuth.discover(vertx, options, new Handler<AsyncResult<OAuth2Auth>>() {
@Override
public void handle(AsyncResult<OAuth2Auth> event) {
if (event.failed()) {
cf.completeExceptionally(toOidcException(event.cause()));
} else {
cf.complete(event.result());
}
}
});
auth = cf.join();
String endSessionEndpoint = OAuth2AuthProviderImpl.class.cast(auth).getConfig().getLogoutPath();
if (endSessionEndpoint == null && oidcConfig.logout.path.isPresent()) {
throw new RuntimeException(
"The application supports RP-Initiated Logout but the OpenID Provider does not advertise the end_session_endpoint");
}
break;
} catch (Throwable throwable) {
while (throwable instanceof CompletionException && throwable.getCause() != null) {
throwable = throwable.getCause();
}
if (throwable instanceof OIDCException) {
if (i + 1 < connectionRetryCount) {
try {
Thread.sleep(2000);
} catch (InterruptedException iex) {
}
} else {
throw (OIDCException) throwable;
}
} else {
throw new OIDCException(throwable);
}
}
}
return new TenantConfigContext(auth, oidcConfig);
}

Line under review: throw new RuntimeException(

Code after addressing the review:
private TenantConfigContext createTenantContext(Vertx vertx, OidcTenantConfig oidcConfig, String tenantId) {
if (!oidcConfig.tenantEnabled) {
LOG.debugf("%s tenant configuration is disabled", tenantId);
return null;
}
OAuth2ClientOptions options = new OAuth2ClientOptions();
if (oidcConfig.getClientId().isPresent()) {
options.setClientID(oidcConfig.getClientId().get());
}
if (oidcConfig.getToken().issuer.isPresent()) {
options.setValidateIssuer(false);
}
if (oidcConfig.getToken().getExpirationGrace().isPresent()) {
JWTOptions jwtOptions = new JWTOptions();
jwtOptions.setLeeway(oidcConfig.getToken().getExpirationGrace().get());
options.setJWTOptions(jwtOptions);
}
if (oidcConfig.getPublicKey().isPresent()) {
return createdTenantContextFromPublicKey(options, oidcConfig);
}
if (!oidcConfig.getAuthServerUrl().isPresent() || !oidcConfig.getClientId().isPresent()) {
throw new ConfigurationException(
"Both 'auth-server-url' and 'client-id' or alterntively 'public-key' must be configured"
+ " when the quarkus-oidc extension is enabled");
}
options.setSite(oidcConfig.getAuthServerUrl().get());
if (oidcConfig.getIntrospectionPath().isPresent()) {
options.setIntrospectionPath(oidcConfig.getIntrospectionPath().get());
}
if (oidcConfig.getJwksPath().isPresent()) {
options.setJwkPath(oidcConfig.getJwksPath().get());
}
Credentials creds = oidcConfig.getCredentials();
if (creds.secret.isPresent() && creds.clientSecret.value.isPresent()) {
throw new ConfigurationException(
"'credentials.secret' and 'credentials.client-secret' properties are mutually exclusive");
}
if ((creds.secret.isPresent() || creds.clientSecret.value.isPresent()) && creds.jwt.secret.isPresent()) {
throw new ConfigurationException(
"Use only 'credentials.secret' or 'credentials.client-secret' or 'credentials.jwt.secret' property");
}
if (creds.secret.isPresent() || creds.clientSecret.value.isPresent()
&& creds.clientSecret.method.orElseGet(() -> Secret.Method.BASIC) == Secret.Method.BASIC) {
options.setClientSecret(creds.secret.orElseGet(() -> creds.clientSecret.value.get()));
} else {
options.setClientSecretParameterName(null);
}
Optional<ProxyOptions> proxyOpt = toProxyOptions(oidcConfig.getProxy());
if (proxyOpt.isPresent()) {
options.setProxyOptions(proxyOpt.get());
}
if (oidcConfig.tls.verification == Verification.NONE) {
options.setTrustAll(true);
options.setVerifyHost(false);
}
final long connectionDelayInSecs = oidcConfig.getConnectionDelay().isPresent()
? oidcConfig.getConnectionDelay().get().toMillis() / 1000
: 0;
final long connectionRetryCount = connectionDelayInSecs > 1 ? connectionDelayInSecs / 2 : 1;
if (connectionRetryCount > 1) {
LOG.infof("Connecting to IDP for up to %d times every 2 seconds", connectionRetryCount);
}
OAuth2Auth auth = null;
for (long i = 0; i < connectionRetryCount; i++) {
try {
CompletableFuture<OAuth2Auth> cf = new CompletableFuture<>();
KeycloakAuth.discover(vertx, options, new Handler<AsyncResult<OAuth2Auth>>() {
@Override
public void handle(AsyncResult<OAuth2Auth> event) {
if (event.failed()) {
cf.completeExceptionally(toOidcException(event.cause()));
} else {
cf.complete(event.result());
}
}
});
auth = cf.join();
if (!ApplicationType.WEB_APP.equals(oidcConfig.applicationType)) {
if (oidcConfig.token.refreshExpired) {
throw new RuntimeException(
"The 'token.refresh-expired' property can only be enabled for " + ApplicationType.WEB_APP
+ " application types");
}
if (oidcConfig.logout.path.isPresent()) {
throw new RuntimeException(
"The 'logout.path' property can only be enabled for " + ApplicationType.WEB_APP
+ " application types");
}
}
String endSessionEndpoint = OAuth2AuthProviderImpl.class.cast(auth).getConfig().getLogoutPath();
if (oidcConfig.logout.path.isPresent()) {
if (!oidcConfig.endSessionPath.isPresent() && endSessionEndpoint == null) {
throw new RuntimeException(
"The application supports RP-Initiated Logout but the OpenID Provider does not advertise the end_session_endpoint");
}
}
break;
} catch (Throwable throwable) {
while (throwable instanceof CompletionException && throwable.getCause() != null) {
throwable = throwable.getCause();
}
if (throwable instanceof OIDCException) {
if (i + 1 < connectionRetryCount) {
try {
Thread.sleep(2000);
} catch (InterruptedException iex) {
}
} else {
throw (OIDCException) throwable;
}
} else {
throw new OIDCException(throwable);
}
}
}
return new TenantConfigContext(auth, oidcConfig);
}