Authentication
The connector authenticates to Neo4j with the authentication type set in the authentication.type option.
| Type | Description |
|---|---|
|
No authentication. |
|
Username and password. Default. |
|
Kerberos ticket. |
|
Static bearer token. |
|
Custom authentication scheme, principal and credentials. |
|
Bearer token obtained and refreshed from an OAuth 2.0 or OpenID Connect identity provider. See OIDC. |
Every option authentication.<type>.<parameter> is passed to the authentication type as <parameter>.
<type> must match the value of authentication.type exactly, for example oidc, not OIDC.
val df = spark.read
.format("org.neo4j.spark.DataSource")
.option("url", "neo4j://localhost:7687")
.option("authentication.type", "basic")
.option("authentication.basic.username", "myuser")
.option("authentication.basic.password", "neo4jpassword")
.option("labels", "Person")
.load()
df = (
spark.read.format("org.neo4j.spark.DataSource")
.option("url", "neo4j://localhost:7687")
.option("authentication.type", "basic")
.option("authentication.basic.username", "myuser")
.option("authentication.basic.password", "neo4jpassword")
.option("labels", "Person")
.load()
)
To set the authentication options once for the whole Spark session, add the neo4j. prefix, for example neo4j.authentication.type.
For the options of the basic, kerberos, custom and bearer types, see the list of available configuration settings.
OIDC
The oidc type obtains bearer tokens from an OAuth 2.0 or OpenID Connect identity provider, and refreshes them before they expire or when Neo4j rejects them.
It is included in the connector JAR file, so no extra dependency is required.
Neo4j must be configured for single sign-on with the same identity provider.
The issuer, the audience and the username claim of the token must match the Neo4j dbms.security.oidc.<name>.* settings.
val df = spark.read
.format("org.neo4j.spark.DataSource")
.option("url", "neo4j+s://neo4j.example.com:7687")
.option("authentication.type", "oidc")
.option("authentication.oidc.issuer", "https://keycloak.example.com/realms/neo4j")
.option("authentication.oidc.clientId", "neo4j-client")
.option("authentication.oidc.clientSecret", "<client secret>")
.option("authentication.oidc.scope", "openid")
.option("labels", "Person")
.load()
df = (
spark.read.format("org.neo4j.spark.DataSource")
.option("url", "neo4j+s://neo4j.example.com:7687")
.option("authentication.type", "oidc")
.option("authentication.oidc.issuer", "https://keycloak.example.com/realms/neo4j")
.option("authentication.oidc.clientId", "neo4j-client")
.option("authentication.oidc.clientSecret", "<client secret>")
.option("authentication.oidc.scope", "openid")
.option("labels", "Person")
.load()
)
Behavior
-
Set one of
issuer,discoveryUrlortokenEndpoint. -
When
issueris set, the discovery document must contain the same issuer, orexpectedIssuerif set. Otherwise, the connector rejects the document. -
The connector never follows redirects from the token endpoint.
-
The connector does not contact the identity provider until it first connects to Neo4j.
-
The Spark driver and every Spark executor request their own tokens. Files set in
clientSecretFile,privateKeyFile,subjectTokenFileandtrustStoreFilemust be available at the same path on every node. -
The token expiry is read from
expires_in, then from the JWTexpclaim, then fromdefaultTtlSeconds. The connector treats the token as expiredrefreshSkewSecondsearlier. -
The connector reads only PKCS#8 keys. To convert a
BEGIN RSA PRIVATE KEYorBEGIN EC PRIVATE KEYfile, run:openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pk8.pem
Options
All options have the authentication.oidc. prefix, for example authentication.oidc.clientId.
| Option | Description | Default |
|---|---|---|
|
Base URL of the identity provider.
The discovery document is read from |
(none) |
|
URL of the discovery document.
Use it when the document is not at |
Derived from |
|
Issuer that the discovery document must contain. Set it only when the identity provider is reached at one address and advertises another, for example behind a reverse proxy. |
Value of |
|
URL of the token endpoint. Skips discovery. |
From the discovery document |
| Option | Description | Default |
|---|---|---|
|
One of |
|
|
Username for the |
(none) |
|
Password for the |
(none) |
|
Space-separated scopes. |
(none) |
|
Value of the |
(none) |
|
Value of the |
(none) |
|
Additional request parameter, sent as is. Overrides any other parameter with the same name. |
(none) |
|
Initial refresh token for the |
(none) |
|
File with the subject token for the |
(none) |
|
Type of the subject token. |
|
| Option | Description | Default |
|---|---|---|
|
Client ID.
Required unless |
(none) |
|
Client secret. |
(none) |
|
File with the client secret, instead of |
(none) |
|
One of |
|
|
PKCS#8 private key file, PEM or DER, for |
(none) |
|
Key ID ( |
(none) |
|
One of |
|
|
Claim of the signed JWT.
The connector sets |
(none) |
|
Lifetime of the signed JWT, in seconds. |
|
| Option | Description | Default |
|---|---|---|
|
Response field that contains the token: |
|
|
Number of seconds before expiry when the connector treats the token as expired. |
|
|
Token lifetime, in seconds, when the response has no |
|
| Option | Description | Default |
|---|---|---|
|
Connection timeout, in milliseconds. |
|
|
Request timeout, in milliseconds. |
|
|
Number of retries on timeouts and on HTTP status |
|
|
Initial wait between retries, in milliseconds. Doubles on each retry, up to 30 seconds. |
|
|
Trust store with the certificate of the identity provider, for self-signed or private certificates. |
(JVM default) |
|
Password of the trust store. |
(none) |
|
Type of the trust store. |
|
|
HTTP proxy host.
Set together with |
(JVM default) |
|
HTTP proxy port.
Set together with |
(JVM default) |
| Option | Description | Default |
|---|---|---|
|
Set of default options for an identity provider: |
(none) |
Examples
The following examples show the connector options and the matching Neo4j settings.
Keycloak
.option("authentication.type", "oidc")
.option("authentication.oidc.issuer", "https://keycloak.example.com/realms/neo4j")
.option("authentication.oidc.clientId", "neo4j-client")
.option("authentication.oidc.clientSecret", "<client secret>")
.option("authentication.oidc.scope", "openid")
To authenticate as a user rather than as a client, use the password grant:
.option("authentication.type", "oidc")
.option("authentication.oidc.issuer", "https://keycloak.example.com/realms/neo4j")
.option("authentication.oidc.grantType", "password")
.option("authentication.oidc.username", "<username>")
.option("authentication.oidc.password", "<password>")
.option("authentication.oidc.clientId", "neo4j-client")
.option("authentication.oidc.clientSecret", "<client secret>")
.option("authentication.oidc.scope", "openid")
dbms.security.oidc.keycloak.issuer=https://keycloak.example.com/realms/neo4j
dbms.security.oidc.keycloak.audience=account
dbms.security.oidc.keycloak.client_id=neo4j-client
dbms.security.oidc.keycloak.claims.username=preferred_username
dbms.security.oidc.keycloak.claims.groups=groups
dbms.security.oidc.keycloak.well_known_discovery_uri=https://keycloak.example.com/realms/neo4j/.well-known/openid-configuration
Okta
Set issuer to a custom authorization server, for example https://example.okta.com/oauth2/default.
Do not use the org authorization server (https://example.okta.com): its access tokens are only for Okta’s own APIs, and Neo4j cannot verify them.
.option("authentication.type", "oidc")
.option("authentication.oidc.profile", "okta")
.option("authentication.oidc.issuer", "https://example.okta.com/oauth2/<authorization server id>")
.option("authentication.oidc.clientId", "<client id>")
.option("authentication.oidc.clientSecret", "<client secret>")
.option("authentication.oidc.scope", "neo4j.read")
dbms.security.oidc.okta.issuer=https://example.okta.com/oauth2/<authorization server id>
dbms.security.oidc.okta.audience=api://neo4j
dbms.security.oidc.okta.claims.username=sub
dbms.security.oidc.okta.claims.groups=groups
Microsoft Entra ID
The scope must be <application ID URI>/.default.
.option("authentication.type", "oidc")
.option("authentication.oidc.profile", "entra")
.option("authentication.oidc.issuer", "https://login.microsoftonline.com/<tenant>/v2.0")
.option("authentication.oidc.clientId", "<application id>")
.option("authentication.oidc.clientSecret", "<client secret>")
.option("authentication.oidc.scope", "api://neo4j/.default")
dbms.security.oidc.entra.issuer=https://login.microsoftonline.com/<tenant>/v2.0
dbms.security.oidc.entra.audience=<application id>
dbms.security.oidc.entra.claims.username=sub
dbms.security.oidc.entra.claims.groups=roles
The connector authenticates with a service account key.
Extract private_key from the service account JSON file into a PKCS#8 PEM file, and make it available on every node.
.option("authentication.type", "oidc")
.option("authentication.oidc.profile", "google")
.option("authentication.oidc.privateKeyFile", "/etc/spark/secrets/service-account.pk8.pem")
.option("authentication.oidc.privateKeyId", "<private_key_id from the service account JSON file>")
.option("authentication.oidc.assertion.claim.iss", "[email protected]")
.option("authentication.oidc.assertion.claim.sub", "[email protected]")
.option("authentication.oidc.assertion.claim.target_audience", "neo4j")
dbms.security.oidc.google.issuer=https://accounts.google.com
dbms.security.oidc.google.audience=neo4j
dbms.security.oidc.google.claims.username=email
Add your own authentication type
You can add an authentication type of your own:
-
Add a dependency on
org.neo4j.connectors:commons-driver-auth-spi.<dependency> <groupId>org.neo4j.connectors</groupId> <artifactId>commons-driver-auth-spi</artifactId> <version>{connectors-commons-version}</version> <scope>provided</scope> </dependency> -
Implement
org.neo4j.connectors.driver.auth.AuthTokenManagerFactory:-
getName()returns the name of the authentication type, the value ofauthentication.type. The name must not clash with an existing authentication type. -
create(AuthConfig, AuthContext)returns the driverAuthTokenManager.
-
-
Register the class in
META-INF/services/org.neo4j.connectors.driver.auth.AuthTokenManagerFactory. -
Add the JAR file to the classpath of the Spark driver and executors, for example with the
--jarsoption ofspark-submit.
AuthConfig contains the options of the authentication type:
-
authentication.<type>.usernameandauthentication.<type>.passwordare available throughusername()andpassword(). -
Any other
authentication.<type>.<parameter>option is available throughget("<parameter>").
public class MyAuthTokenManagerFactory implements AuthTokenManagerFactory {
@Override
public String getName() {
return "my-type";
}
@Override
public AuthTokenManager create(AuthConfig config, AuthContext context) {
AuthToken token = AuthTokens.bearer(config.require("token"));
return AuthTokenManagers.basic(() -> token);
}
}
.option("authentication.type", "my-type")
.option("authentication.my-type.token", "<token>")
Authentication supplier (legacy)
Before the AuthTokenManagerFactory interface, you added your own authentication type by implementing org.neo4j.connectors.authn.AuthenticationTokenSupplierFactory from the org.neo4j.connectors:commons-authn-spi library.
The connector still supports these authentication suppliers, including the keycloak supplier from the org.neo4j.connectors:commons-authn-keycloak library, and configures them in the same way.
When both an AuthTokenManagerFactory and an AuthenticationTokenSupplierFactory have the same name, the connector uses the AuthTokenManagerFactory.
For new applications, use the oidc type or add your own authentication type instead.
To replace the keycloak supplier with the oidc type, set grantType to password and include the realm in the issuer URL:
keycloak option |
oidc option |
|---|---|
|
|
|
|
|
|
|
|
|
|
See the Keycloak example.