Add support for using an AuthTokenManager with Neo4j

Neo4j Java driver introduced support for an `AuthTokenManager` that can
be used to define expiring tokens for authentication with a database.

This commit adds an `ObjectProvider<AuthTokenManager> authTokenManagers`
parameter to the corresponding auto configuration class. If the provider
resolves to a unique object, that `AuthTokenManager` will have precedence
over any static token.

See gh-36650
pull/36693/head
Michael Simons 1 year ago committed by Andy Wilkinson
parent 4f877db91a
commit 1f0a3901b2

@ -24,6 +24,7 @@ import java.util.Locale;
import java.util.concurrent.TimeUnit;
import org.neo4j.driver.AuthToken;
import org.neo4j.driver.AuthTokenManager;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.Config.TrustStrategy;
@ -70,11 +71,16 @@ public class Neo4jAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Driver neo4jDriver(Neo4jProperties properties, Environment environment,
Neo4jConnectionDetails connectionDetails,
ObjectProvider<ConfigBuilderCustomizer> configBuilderCustomizers) {
AuthToken authToken = connectionDetails.getAuthToken();
Neo4jConnectionDetails connectionDetails, ObjectProvider<ConfigBuilderCustomizer> configBuilderCustomizers,
ObjectProvider<AuthTokenManager> authTokenManagers) {
Config config = mapDriverConfig(properties, connectionDetails,
configBuilderCustomizers.orderedStream().toList());
AuthTokenManager authTokenManager = authTokenManagers.getIfUnique();
if (authTokenManager != null) {
return GraphDatabase.driver(connectionDetails.getUri(), authTokenManager, config);
}
AuthToken authToken = connectionDetails.getAuthToken();
return GraphDatabase.driver(connectionDetails.getUri(), authToken, config);
}

@ -18,7 +18,11 @@ package org.springframework.boot.autoconfigure.neo4j;
import java.time.Duration;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.neo4j.driver.AuthTokenManager;
import org.neo4j.driver.AuthTokenManagers;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
@ -31,6 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
@ -43,7 +48,6 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Michael J. Simons
* @author Stephane Nicoll
*/
@SpringBootTest
@Testcontainers(disabledWithoutDocker = true)
class Neo4jAutoConfigurationIntegrationTests {
@ -52,28 +56,71 @@ class Neo4jAutoConfigurationIntegrationTests {
.withStartupAttempts(5)
.withStartupTimeout(Duration.ofMinutes(10));
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4jServer::getBoltUrl);
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
registry.add("spring.neo4j.authentication.password", neo4jServer::getAdminPassword);
}
@SpringBootTest
@Nested
class DriverWithDefaultAuthToken {
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4jServer::getBoltUrl);
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
registry.add("spring.neo4j.authentication.password", neo4jServer::getAdminPassword);
}
@Autowired
private Driver driver;
@Autowired
private Driver driver;
@Test
void driverCanHandleRequest() {
try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) {
Result statementResult = tx.run("MATCH (n:Thing) RETURN n LIMIT 1");
assertThat(statementResult.hasNext()).isFalse();
tx.commit();
}
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(Neo4jAutoConfiguration.class)
static class TestConfiguration {
@Test
void driverCanHandleRequest() {
try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) {
Result statementResult = tx.run("MATCH (n:Thing) RETURN n LIMIT 1");
assertThat(statementResult.hasNext()).isFalse();
tx.commit();
}
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(Neo4jAutoConfiguration.class)
static class TestConfiguration {
@SpringBootTest
@Nested
class DriverWithDynamicAuthToken {
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4jServer::getBoltUrl);
registry.add("spring.neo4j.authentication.username", () -> "wrong");
registry.add("spring.neo4j.authentication.password", () -> "alsowrong");
}
@Autowired
private Driver driver;
@Test
void driverCanHandleRequest() {
try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) {
Result statementResult = tx.run("MATCH (n:Thing) RETURN n LIMIT 1");
assertThat(statementResult.hasNext()).isFalse();
tx.commit();
}
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(Neo4jAutoConfiguration.class)
static class TestConfiguration {
@Bean
AuthTokenManager authTokenManager() {
return AuthTokenManagers.expirationBased(() -> AuthTokens.basic("neo4j", neo4jServer.getAdminPassword())
.expiringAt(System.currentTimeMillis() + 5_000));
}
}
}

Loading…
Cancel
Save