diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java index 1394b5c9..93dfcf6e 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java @@ -25,7 +25,6 @@ import org.springframework.http.HttpEntity; import org.springframework.scheduling.TaskScheduler; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; import org.springframework.vault.VaultException; import org.springframework.vault.authentication.event.*; import org.springframework.vault.client.VaultHttpHeaders; @@ -149,11 +148,18 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu @Override public void destroy() { + revoke(); + } + + /** + * Revoke and drop the current {@link VaultToken}. + * @since 3.0.2 + */ + public void revoke() { Optional token = getToken(); - setToken(Optional.empty()); - token.filter(TokenWrapper::isRevocable).map(TokenWrapper::getToken).ifPresent(this::revoke); + setToken(Optional.empty()); } /** diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManager.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManager.java index 1afa27b6..6ddb4a01 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManager.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManager.java @@ -26,7 +26,6 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.scheduling.TaskScheduler; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; import org.springframework.vault.VaultException; import org.springframework.vault.authentication.event.*; import org.springframework.vault.client.VaultHttpHeaders; @@ -145,6 +144,23 @@ public class ReactiveLifecycleAwareSessionManager extends LifecycleAwareSessionM revokeNow(tokenMono); } + /** + * Revoke and drop the current {@link VaultToken}. + * @return a mono emitting completion upon successful revocation. + * @since 3.0.2 + */ + public Mono revoke() { + return doRevoke(this.token.get()).doOnSuccess(unused -> this.token.set(EMPTY)); + } + + /** + * Revoke and drop the current {@link VaultToken} now. + * @since 3.0.2 + */ + public void revokeNow() { + revoke().block(Duration.ofSeconds(5)); + } + /** * Revoke a {@link VaultToken} now and block execution until revocation completes. * @param tokenMono diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerIntegrationTests.java index 017858de..a17775b0 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerIntegrationTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerIntegrationTests.java @@ -99,6 +99,33 @@ class LifecycleAwareSessionManagerIntegrationTests extends IntegrationTestSuppor sessionManager.renewToken(); } + @Test + void shouldRevokeToken() { + + final LoginToken loginToken = createLoginToken(); + TokenAuthentication tokenAuthentication = new TokenAuthentication(loginToken); + + LifecycleAwareSessionManager sessionManager = new LifecycleAwareSessionManager(tokenAuthentication, + this.taskScheduler, prepare().getRestTemplate()); + + sessionManager.getSessionToken(); + sessionManager.revoke(); + + prepare().getVaultOperations().doWithSession(restOperations -> { + + try { + restOperations.getForEntity("auth/token/lookup/{token}", Map.class, loginToken.toCharArray()); + fail("Missing HttpStatusCodeException"); + } + catch (HttpStatusCodeException e) { + // Compatibility across Vault versions. + assertThat(e.getStatusCode()).isIn(HttpStatus.BAD_REQUEST, HttpStatus.NOT_FOUND, HttpStatus.FORBIDDEN); + } + + return null; + }); + } + @Test void shouldRevokeOnDisposal() { diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManagerIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManagerIntegrationTests.java index 765328ee..d59555a0 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManagerIntegrationTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManagerIntegrationTests.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import org.assertj.core.util.Files; @@ -171,6 +172,36 @@ class ReactiveLifecycleAwareSessionManagerIntegrationTests extends IntegrationTe }); } + @Test + void shouldRevokeToken() { + + LoginToken loginToken = createLoginToken(); + + ReactiveLifecycleAwareSessionManager sessionManager = new ReactiveLifecycleAwareSessionManager( + () -> Flux.fromStream(Stream.of((VaultToken) loginToken)).next(), this.taskScheduler, + prepare().getWebClient()); + + sessionManager.getSessionToken() // + .as(StepVerifier::create) // + .expectNext(loginToken) // + .verifyComplete(); + sessionManager.revokeNow(); + + prepare().getVaultOperations().doWithSession(restOperations -> { + + try { + restOperations.getForEntity("auth/token/lookup/{token}", Map.class, loginToken.toCharArray()); + fail("Missing HttpStatusCodeException"); + } + catch (HttpStatusCodeException e) { + // Compatibility across Vault versions. + assertThat(e.getStatusCode()).isIn(HttpStatus.BAD_REQUEST, HttpStatus.NOT_FOUND, HttpStatus.FORBIDDEN); + } + + return null; + }); + } + private LoginToken createLoginToken() { VaultTokenOperations tokenOperations = prepare().getVaultOperations().opsForToken();