Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public void init(Map<String, Object> 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")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,22 @@ The simplest possible `security.json` for registering the plugin without configu
----
{
"authentication": {
"class":"solr.JWTAuthPlugin",
"blockUnknown":"false"
"class":"solr.JWTAuthPlugin"
}
}
Comment thread
janhoy marked this conversation as resolved.
----

The plugin will by default require a valid JWT token for all traffic.
By default, `blockUnknown` is `true`, so all requests without a valid JWT token will be blocked.

If the `blockUnknown` property is set to `false` as in the above example, it is possible to start configuring the plugin using unauthenticated REST API calls, which is further described in section <<Editing JWT Authentication Plugin Configuration>>.
If you need to configure the plugin using unauthenticated REST API calls, set `blockUnknown` to `false` as further described in section <<Editing JWT Authentication Plugin Configuration>>.

== Configuration Parameters

//*TODO*: standard is not to put parameters in tables but use labeled lists instead
[%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`
Expand Down Expand Up @@ -167,7 +166,7 @@ Let's look at a more complex configuration, this time with two issuers configure
Let's comment on this config:

<1> Plugin class
<2> Make sure to block anyone without a valid token (this is also the default)
<2> Block anyone without a valid token (this is also the default)
<3> Fetch the user id from another claim than the default `sub`
<4> Require that the `foo` claim is one of "A" or "B" and that the `dept` claim is "IT"
<5> Require one of the scopes `solr:read`, `solr:write` or `solr:admin`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions solr/webapp/web/js/angular/controllers/security.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Loading