JWT Authentication Plugin
Solr can support JSON Web Token (JWT) based Bearer authentication with the use of the JWTAuthPlugin.
This allows Solr to assert that a user is already authenticated with an external Identity Provider by validating that the JWT formatted access token is digitally signed by the Identity Provider. The typical use case is to integrate Solr with an OpenID Connect enabled IdP.
Module
This is provided via the jwt-auth
Solr Module that needs to be enabled before use.
Enable JWT Authentication
To use JWT Bearer authentication, the security.json
file must have an authentication
part which defines the class being used for authentication along with configuration parameters.
The simplest possible security.json
for registering the plugin without configuration is:
{
"authentication": {
"class":"solr.JWTAuthPlugin",
"blockUnknown":"false"
}
}
The plugin will by default require a valid JWT token for all traffic.
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.
Configuration Parameters
Key | Description | Default |
---|---|---|
blockUnknown |
Set to |
|
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 |
|
requireIss |
Fails requests that lacks an |
|
requireExp |
Fails requests that lacks an |
|
algAllowlist |
JSON array with algorithms to accept: |
Default is to allow all algorithms |
jwkCacheDur |
Duration of JWK cache in seconds |
|
principalClaim |
What claim id to pull principal from |
|
rolesClaim |
What claim id to pull user roles from. Both top-level claim and nested claim is supported. Use |
By default the scopes from |
claimsMatch |
JSON object of claims (key) that must match a regular expression (value). Example: |
|
adminUiScope |
Define what scope is requested when logging in from Admin UI |
If not defined, the first scope from |
redirectUris |
Valid location(s) for redirect after external authentication. Takes a string or array of strings. Must be the base URL of Solr, e.g., https://solr1.example.com:8983/solr/ and must match the list of redirect URIs registered with the Identity Provider beforehand. |
Defaults to empty list, i.e., any node is assumed to be a valid redirect target. |
trustedCerts |
One or more X.509 SSL certificates in plaintext PEM or PKCS#7 formats, that should be trusted when talking to IdPs. Newlines must be replaced with |
Defaults to Java truststore |
trustedCertsFile |
Path to a file of type PEM, DER or PKCS#7, containing one or more X.509 SSL certificates that should be trusted when talking to IdPs. Can also be an array of file paths. See paragraph Trusting the IdP server for more about its usage. |
Defaults to Java truststore |
issuers |
List of issuers (Identity providers) to support. See section Issuer configuration for configuration syntax |
Issuer Configuration
This plugin supports one or more token issuers (IdPs).
Issuers are configured as a list of JSON objects under the issuers
configuration key.
The first issuer in the list is the "Primary Issuer", which is the one used for logging in to the Admin UI.
Key | Description | Default |
---|---|---|
name |
A unique name of the issuer. Used to manipulate list through API. |
|
wellKnownUrl |
URL to an OpenID Connect Discovery endpoint |
|
clientId |
Client identifier for use with OpenID Connect. Required to authenticate with Admin UI. Needed for primary issuer only |
|
jwksUrl |
A URL to a JWKs endpoint. Must use https protocol. Optionally an array of URLs in which case all public keys from all URLs will be consulted when validating signatures. |
Auto configured if |
jwk |
As an alternative to |
|
iss |
Unique issuer id as configured on the IdP. Incoming tokens must have a matching |
Auto configured if |
aud |
Validates that the |
Uses |
authorizationEndpoint |
The URL for the Id Provider’s authorization endpoint |
Auto configured if |
tokenEndpoint |
The URL for the Id Provider’s token endpoint |
Auto configured if |
authorizationFlow |
Specifies the OAuth 2.0 flow to be used. Supported flows are 'implicit' and 'code_pkce' (for authorization code with 'Proof Key for Code Exchange'). Note: 'implicit' is deprecated and it is highly recommended to use 'code_pkce' instead. |
implicit |
For backwards compatibility, all the configuration keys for the primary issuer may be configured as top-level keys, except name .
|
More Configuration Examples
With JWKS URL
To start enforcing authentication for all users, requiring a valid JWT in the Authorization
header, you need to configure the plugin with one or more JSON Web Keys (JWK).
This is a JSON document containing the key used to sign/encrypt the JWT.
It could be a symmetric or asymmetric key.
The JWK can either be fetched (and cached) from an external HTTPS endpoint or specified directly in security.json
.
Below is an example of the former:
{
"authentication": {
"class": "solr.JWTAuthPlugin",
"jwksUrl": "https://my.key.server/jwk.json"
}
}
With Admin UI Support
This example shows configuration using OpenID Connect Discovery with a well-known URI for automatic configuration of many common settings, including ability to use the Admin UI with an OpenID Connect enabled Identity Provider.
{
"authentication": {
"class": "solr.JWTAuthPlugin",
"wellKnownUrl": "https://idp.example.com/.well-known/openid-configuration",
"clientId": "xyz",
"redirectUris": "https://my.solr.server:8983/solr/"
}
}
In this case, jwksUrl
, iss
, and authorizationEndpoint
will be automatically configured from the fetched configuration.
Complex Example
Let’s look at a more complex configuration, this time with two issuers configured, where one uses a static embedded JWK:
{
"authentication": {
"class": "solr.JWTAuthPlugin", (1)
"blockUnknown": true, (2)
"principalClaim": "solruid", (3)
"claimsMatch": { "foo" : "A|B", "dept" : "IT" }, (4)
"scope": "solr:read solr:write solr:admin", (5)
"algAllowlist" : [ "RS256", "RS384", "RS512" ], (6)
"issuers": [ (7)
{
"name": "example1-static", (8)
"jwk": { (9)
"e": "AQAB",
"kid": "k1",
"kty": "RSA",
"n": "3ZF6w....vjbCXxw"
},
"clientId": "solr-client-12345", (10)
"iss": "https://example.com/idp", (11)
"aud": "https://example.com/solr" (12)
},
{
"name": "example2",
"wellKnownUrl": "https://example2.com/.well-known/oidc", (13)
"aud": "https://example2.com/solr"
}
],
"trustedCertsFile": "/path/to/certsFile.pem" (14)
}
}
Let’s comment on this config:
1 | Plugin class |
2 | Make sure to 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 roles 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 |
6 | Only accept RSA algorithms for signatures |
7 | Array of issuer configurations |
8 | Each issuer object should have a unique name |
9 | Here we pass the JWK inline instead of referring to a URL with jwksUrl |
10 | Set the client id registered with Identity Provider |
11 | Configure the issuer id. Will be used for validating tokens. A token’s 'iss' claim must match one of the configured issuer IDs. |
12 | Configure the audience claim. A token’s 'aud' claim must match 'aud' for one of the configured issuers. |
13 | This issuer is auto-configured through discovery, so 'iss' and JWK settings are not required |
14 | Provides SSL certificate(s) to trust IdP https communication. |
Using non-SSL URLs
In production environments you should always use SSL protected HTTPS connections, otherwise you open yourself up to attacks.
However, in development, it may be useful to use regular HTTP URLs, and bypass the security check that Solr performs.
To support this you can set the system property -Dsolr.auth.jwt.allowOutboundHttp=true
at startup.
Trusting the IdP server
All communication with the Oauth2 server (IdP) is done over HTTPS.
By default, Java’s built-in TrustStore is used.
However, by configuring one of the options trustedCertsFile
or trustedCerts
, the plugin will instead trust the set of certificates provided, not any certificate signed by a root CA.
This is both more secure and also lets you trust self-signed certificates.
It also has the benefit of working even if Solr is not started in SSL mode.
Please configure either the trustedCerts
or trustedCertsFile
option.
Configuring both will cause an error. If trustedCertsFile
is an array of strings, Solr will parse certificates from all files.
Multiple Authentication Schemes
Solr provides the MultiAuthPlugin to support multiple authentication schemes based on the Authorization
header.
This allows you to configure Solr to delegate user management and authentication to an OIDC provider using the JWTAuthPlugin
,
but also allow a small set of service accounts to use Basic
authentication when using OIDC is not supported or practical.
Editing JWT Authentication Plugin Configuration
All properties mentioned above can be set or changed using the Authentication API.
You can thus start with a simple configuration with only class
and blockUnknown=false
configured and then configure the rest using the API.
Set a Configuration Property
Set properties for the authentication plugin.
Each of the configuration keys in the table above can be used as parameter keys for the set-property
command.
Example:
-
V1 API
-
V2 API
curl http://localhost:8983/solr/admin/authentication -H 'Content-type:application/json' -H 'Authorization: Bearer xxx.yyy.zzz' -d '{
"set-property": {
"blockUnknown":true,
"wellKnownUrl": "https://example.com/.well-known/openid-configuration",
"scope": "solr:read solr:write"
}
}
'
curl http://localhost:8983/api/cluster/security/authentication -H 'Content-type:application/json' -H 'Authorization: Bearer xxx.yyy.zzz' -d '{
"set-property": {
"blockUnknown":true,
"wellKnownUrl": "https://example.com/.well-known/openid-configuration",
"scope": "solr:read solr:write"
}
}
'
Insert a valid JWT access token in compact serialization format (xxx.yyy.zzz
above) to authenticate with Solr once the plugin is active, or leave blockUnknown=false
until configuration is complete and then switch it to true
to start enforcing.
There is currently no support for adding multiple token issuers though REST API, however you can work around this by configuring a single issuer through the API by using the 'issuer' properties as top-level properties. |
Using Clients with JWT Auth
cURL
To authenticate with Solr when using the cURL utility, supply a valid JWT access token in an Authorization
header, as follows (replace xxxxxx.xxxxxx.xxxxxx with your JWT compact token):
curl -H "Authorization: Bearer xxxxxx.xxxxxx.xxxxxx" http://localhost:8983/solr/admin/info/system
Admin UI
When this plugin is enabled, users will be redirected to a login page in the Admin UI once they attempt to do a restricted action. The page has a button that users will click and be redirected to the Identity Provider’s login page.
If more than one issuer (IdP) is configured, the first in the list will be used for Admin UI. Once authenticated, the user will be redirected back to Solr Admin UI to the last known location. The session will last as long as the JWT token expiry time and is valid for one Solr server only. That means you have to login again when navigating to another Solr node. There is also a logout menu in the left column where user can explicitly log out.