7676import org .elasticsearch .common .CheckedRunnable ;
7777import org .elasticsearch .common .Nullable ;
7878import org .elasticsearch .common .Strings ;
79- import org .elasticsearch .common .SuppressForbidden ;
8079import org .elasticsearch .common .collect .Tuple ;
8180import org .elasticsearch .common .util .concurrent .EsExecutors ;
8281import org .elasticsearch .common .util .concurrent .ListenableFuture ;
9594import java .net .URI ;
9695import java .net .URISyntaxException ;
9796import java .net .URL ;
98-
9997import java .net .URLEncoder ;
10098import java .nio .charset .Charset ;
10199import java .nio .charset .StandardCharsets ;
100+ import java .nio .file .Files ;
102101import java .nio .file .Path ;
103102import java .security .AccessController ;
104103import java .security .PrivilegedAction ;
111110import java .util .concurrent .atomic .AtomicReference ;
112111
113112import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .ALLOWED_CLOCK_SKEW ;
114- import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_CONNECT_TIMEOUT ;
115113import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_CONNECTION_READ_TIMEOUT ;
114+ import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_CONNECT_TIMEOUT ;
116115import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_MAX_CONNECTIONS ;
117116import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_MAX_ENDPOINT_CONNECTIONS ;
118117import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_SOCKET_TIMEOUT ;
@@ -142,7 +141,7 @@ public OpenIdConnectAuthenticator(RealmConfig realmConfig, OpenIdConnectProvider
142141 this .sslService = sslService ;
143142 this .httpClient = createHttpClient ();
144143 this .watcherService = watcherService ;
145- this .idTokenValidator .set (createIdTokenValidator ());
144+ this .idTokenValidator .set (createIdTokenValidator (true ));
146145 }
147146
148147 // For testing
@@ -314,10 +313,11 @@ private void validateAccessToken(AccessToken accessToken, JWT idToken) {
314313 * @throws ParseException if the file cannot be parsed
315314 * @throws IOException if the file cannot be read
316315 */
317- @ SuppressForbidden (reason = "uses toFile" )
318316 private JWKSet readJwkSetFromFile (String jwkSetPath ) throws IOException , ParseException {
319317 final Path path = realmConfig .env ().configFile ().resolve (jwkSetPath );
320- return JWKSet .load (path .toFile ());
318+ // avoid using JWKSet.loadFile() as it does not close FileInputStream internally
319+ String jwkSet = Files .readString (path , StandardCharsets .UTF_8 );
320+ return JWKSet .parse (jwkSet );
321321 }
322322
323323 /**
@@ -589,7 +589,7 @@ private CloseableHttpAsyncClient createHttpClient() {
589589 /*
590590 * Creates an {@link IDTokenValidator} based on the current Relying Party configuration
591591 */
592- IDTokenValidator createIdTokenValidator () {
592+ IDTokenValidator createIdTokenValidator (boolean addFileWatcherIfRequired ) {
593593 try {
594594 final JWSAlgorithm requestedAlgorithm = rpConfig .getSignatureAlgorithm ();
595595 final int allowedClockSkew = Math .toIntExact (realmConfig .getSetting (ALLOWED_CLOCK_SKEW ).getMillis ());
@@ -600,12 +600,16 @@ IDTokenValidator createIdTokenValidator() {
600600 new IDTokenValidator (opConfig .getIssuer (), rpConfig .getClientId (), requestedAlgorithm , clientSecret );
601601 } else {
602602 String jwkSetPath = opConfig .getJwkSetPath ();
603- if (jwkSetPath .startsWith ("https://" )) {
603+ if (jwkSetPath .startsWith ("http://" )) {
604+ throw new IllegalArgumentException ("The [http] protocol is not supported as it is insecure. Use [https] instead" );
605+ } else if (jwkSetPath .startsWith ("https://" )) {
604606 final JWSVerificationKeySelector keySelector = new JWSVerificationKeySelector (requestedAlgorithm ,
605607 new ReloadableJWKSource (new URL (jwkSetPath )));
606608 idTokenValidator = new IDTokenValidator (opConfig .getIssuer (), rpConfig .getClientId (), keySelector , null );
607609 } else {
608- setMetadataFileWatcher (jwkSetPath );
610+ if (addFileWatcherIfRequired ) {
611+ setMetadataFileWatcher (jwkSetPath );
612+ }
609613 final JWKSet jwkSet = readJwkSetFromFile (jwkSetPath );
610614 idTokenValidator = new IDTokenValidator (opConfig .getIssuer (), rpConfig .getClientId (), requestedAlgorithm , jwkSet );
611615 }
@@ -620,7 +624,7 @@ IDTokenValidator createIdTokenValidator() {
620624 private void setMetadataFileWatcher (String jwkSetPath ) throws IOException {
621625 final Path path = realmConfig .env ().configFile ().resolve (jwkSetPath );
622626 FileWatcher watcher = new FileWatcher (path );
623- watcher .addListener (new FileListener (LOGGER , () -> this .idTokenValidator .set (createIdTokenValidator ())));
627+ watcher .addListener (new FileListener (LOGGER , () -> this .idTokenValidator .set (createIdTokenValidator (false ))));
624628 watcherService .add (watcher , ResourceWatcherService .Frequency .MEDIUM );
625629 }
626630
0 commit comments