diff --git a/changelog/unreleased/SOLR-18215-jwt-auth-blockUnknown-default-true.yml b/changelog/unreleased/SOLR-18215-jwt-auth-blockUnknown-default-true.yml new file mode 100644 index 000000000000..08e26cf170ec --- /dev/null +++ b/changelog/unreleased/SOLR-18215-jwt-auth-blockUnknown-default-true.yml @@ -0,0 +1,8 @@ +title: JWT Authentication `blockUnknown` now defaults to `true`, blocking unauthenticated requests by default. Previously the code defaulted to `false` despite the reference guide documenting `true`. Users relying on pass-through must explicitly set `blockUnknown` to `false` in their security.json. +type: changed +authors: + - name: Jan Høydahl + url: https://home.apache.org/phonebook.html?uid=janhoy +links: + - name: SOLR-18215 + url: https://issues.apache.org/jira/browse/SOLR-18215 diff --git a/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java b/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java index 819f2293f9be..bdb0ac874c30 100644 --- a/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java +++ b/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java @@ -179,7 +179,7 @@ public void init(Map pluginConfig) { } blockUnknown = - Boolean.parseBoolean(String.valueOf(pluginConfig.getOrDefault(PARAM_BLOCK_UNKNOWN, false))); + Boolean.parseBoolean(String.valueOf(pluginConfig.getOrDefault(PARAM_BLOCK_UNKNOWN, true))); requireIssuer = Boolean.parseBoolean( String.valueOf(pluginConfig.getOrDefault(PARAM_REQUIRE_ISSUER, "true"))); diff --git a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java index f871c779ed44..55c51c754201 100644 --- a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java +++ b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java @@ -484,6 +484,15 @@ public void noHeaderBlockUnknown() { assertEquals(NO_AUTZ_HEADER, resp.getAuthCode()); } + @Test + public void noHeaderDefaultBlocksUnknown() { + // blockUnknown defaults to true — omitting it must block requests without a JWT + testConfig.remove("blockUnknown"); + plugin.init(testConfig); + JWTAuthPlugin.JWTAuthenticationResponse resp = plugin.authenticate(null); + assertEquals(NO_AUTZ_HEADER, resp.getAuthCode()); + } + @Test public void noHeaderNotBlockUnknown() { testConfig.put("blockUnknown", false); @@ -511,6 +520,7 @@ public void wellKnownConfigNoHeaderPassThrough() { .toString(); testConfig.put("wellKnownUrl", wellKnownUrl); testConfig.remove("jwk"); + testConfig.put("blockUnknown", false); plugin.init(testConfig); JWTAuthPlugin.JWTAuthenticationResponse resp = plugin.authenticate(null); assertEquals(PASS_THROUGH, resp.getAuthCode()); diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/jwt-authentication-plugin.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/jwt-authentication-plugin.adoc index 4a5094f62252..316b9ec465c1 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/jwt-authentication-plugin.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/jwt-authentication-plugin.adoc @@ -52,7 +52,7 @@ If the `blockUnknown` property is set to `false` as in the above example, it is [%header,format=csv,separator=;,cols="25%,50%,25%"] |=== Key ; Description ; Default -blockUnknown ; Set to `false` to if you need to perform configuration through REST API or if you use an Authorization Plugin and only want certain paths protected. By default all requests will require a token ; `true` +blockUnknown ; Set to `false` if you need to perform configuration through REST API or if you use an Authorization Plugin and only want certain paths protected. By default all requests will require a token ; `true` realm ; Name of the authentication realm to echo back in HTTP 401 responses. Will also be displayed in Admin UI login page ; 'solr-jwt' scope ; Whitespace separated list of valid scopes. If configured, the JWT access token MUST contain a `scope` claim with at least one of the listed scopes. Example: `solr:read solr:admin` ; requireIss ; Fails requests that lacks an `iss` (issuer) claim ; `true` diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc index 37180f2d30f3..a9fde5d46967 100644 --- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc +++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc @@ -97,6 +97,12 @@ The project normally doesn't remove functionality in a minor release, but we mad +NOTE: The previous parse-context-based configuration (`parseContext.config`) is no longer supported. Tika parser-specific properties must now be configured directly on the Tika Server itself, rather than through Solr configuration. Please refer to the Tika Server documentation for details on how to set these properties. +=== JWT Authentication + +The `blockUnknown` setting in the JWT Authentication plugin now defaults to `true`, meaning requests without a valid JWT token are blocked by default. +In Solr 9.10 and earlier, the code default was `false` (pass-through), which contradicted the reference guide documentation that described `true` as the default. +Users upgrading from 9.10 who relied on the pass-through behavior must explicitly set `"blockUnknown": false` in their `security.json`. + == Solr 9.10 === SolrJ diff --git a/solr/webapp/web/js/angular/controllers/security.js b/solr/webapp/web/js/angular/controllers/security.js index 52b5c2ac46a2..fd65a289988f 100644 --- a/solr/webapp/web/js/angular/controllers/security.js +++ b/solr/webapp/web/js/angular/controllers/security.js @@ -242,7 +242,7 @@ solrAdminApp.controller('SecurityController', function ($scope, $timeout, $cooki $scope.hideAll(); $scope.tls = false; - $scope.blockUnknown = "false"; // default setting + $scope.blockUnknown = "true"; // default setting $scope.realmName = "solr"; $scope.forwardCredentials = "false"; $scope.multiAuthWithBasic = false; @@ -371,7 +371,8 @@ solrAdminApp.controller('SecurityController', function ($scope, $timeout, $cooki //console.log(">> authn: "+JSON.stringify(authn)); - $scope.blockUnknown = authn["blockUnknown"] === true ? "true" : "false"; + var blockUnknown = authn["blockUnknown"]; + $scope.blockUnknown = (blockUnknown === false || blockUnknown === "false") ? "false" : "true"; $scope.forwardCredentials = authn["forwardCredentials"] === true ? "true" : "false"; if ("realm" in authn) {