From 61051cfd6696e851f1f9bb6b4c9246526a31d52d Mon Sep 17 00:00:00 2001 From: IgorHorta Date: Fri, 27 Feb 2026 10:35:29 -0300 Subject: [PATCH] feat: add no-arg RevokeToken() for self-revocation Adds a no-arg RevokeToken() overload to AuthClient that revokes the currently authenticated session without requiring the caller to manually handle the access token. Previously, all auth login methods (LdapAuthLogin, UniversalAuthLogin, AwsAuthLogin, etc.) stored the token internally with no public way to retrieve it, making it impossible to call RevokeToken(token) after authentication without resorting to workarounds. The token is now tracked privately inside AuthClient and passed through to new instances created on re-authentication, so RevokeToken() works correctly across the full SDK lifecycle. --- .../java/com/infisical/sdk/InfisicalSdk.java | 2 +- .../infisical/sdk/resources/AuthClient.java | 21 +++++++++++++++--- .../com/infisical/sdk/InfisicalSdkTest.java | 17 ++++++++++++++ .../sdk/resources/AuthClientTest.java | 22 +++++++++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/infisical/sdk/InfisicalSdk.java b/src/main/java/com/infisical/sdk/InfisicalSdk.java index cac4701..187bcf1 100644 --- a/src/main/java/com/infisical/sdk/InfisicalSdk.java +++ b/src/main/java/com/infisical/sdk/InfisicalSdk.java @@ -29,7 +29,7 @@ private void onAuthenticate(String accessToken) { this.secretsClient = new SecretsClient(apiClient); this.foldersClient = new FoldersClient(apiClient); this.projectsClient = new ProjectsClient(apiClient); - this.authClient = new AuthClient(apiClient, this::onAuthenticate); + this.authClient = new AuthClient(apiClient, this::onAuthenticate, accessToken); } public AuthClient Auth() { diff --git a/src/main/java/com/infisical/sdk/resources/AuthClient.java b/src/main/java/com/infisical/sdk/resources/AuthClient.java index b74ce92..dbb4dc4 100644 --- a/src/main/java/com/infisical/sdk/resources/AuthClient.java +++ b/src/main/java/com/infisical/sdk/resources/AuthClient.java @@ -13,19 +13,27 @@ public class AuthClient { private final ApiClient apiClient; private final Consumer onAuthenticate; + private String currentAccessToken; public AuthClient(ApiClient apiClient, Consumer onAuthenticate) { this.apiClient = apiClient; this.onAuthenticate = onAuthenticate; } + public AuthClient(ApiClient apiClient, Consumer onAuthenticate, String initialToken) { + this.apiClient = apiClient; + this.onAuthenticate = onAuthenticate; + this.currentAccessToken = initialToken; + } + public void UniversalAuthLogin(String clientId, String clientSecret) throws InfisicalException { UniversalAuthLoginInput params = UniversalAuthLoginInput.builder().clientId(clientId).clientSecret(clientSecret) .build(); String url = String.format("%s%s", this.apiClient.GetBaseUrl(), "/api/v1/auth/universal-auth/login"); MachineIdentityCredential credential = this.apiClient.post(url, params, MachineIdentityCredential.class); - this.onAuthenticate.accept(credential.getAccessToken()); + this.currentAccessToken = credential.getAccessToken(); + this.onAuthenticate.accept(this.currentAccessToken); } public void LdapAuthLogin(LdapAuthLoginInput input) throws InfisicalException { @@ -37,7 +45,8 @@ public void LdapAuthLogin(LdapAuthLoginInput input) throws InfisicalException { String url = String.format("%s%s", this.apiClient.GetBaseUrl(), "/api/v1/auth/ldap-auth/login"); MachineIdentityCredential credential = this.apiClient.post(url, input, MachineIdentityCredential.class); - this.onAuthenticate.accept(credential.getAccessToken()); + this.currentAccessToken = credential.getAccessToken(); + this.onAuthenticate.accept(this.currentAccessToken); } public void AwsAuthLogin(String identityId) throws InfisicalException { @@ -53,13 +62,19 @@ public void AwsAuthLogin(AwsAuthLoginInput input) throws InfisicalException { String url = String.format("%s%s", this.apiClient.GetBaseUrl(), "/api/v1/auth/aws-auth/login"); MachineIdentityCredential credential = this.apiClient.post(url, input, MachineIdentityCredential.class); - this.onAuthenticate.accept(credential.getAccessToken()); + this.currentAccessToken = credential.getAccessToken(); + this.onAuthenticate.accept(this.currentAccessToken); } public void SetAccessToken(String accessToken) { + this.currentAccessToken = accessToken; this.onAuthenticate.accept(accessToken); } + public void RevokeToken() throws InfisicalException { + RevokeToken(this.currentAccessToken); + } + public void RevokeToken(String accessToken) throws InfisicalException { RevokeTokenInput input = RevokeTokenInput.builder().accessToken(accessToken).build(); diff --git a/src/test/java/com/infisical/sdk/InfisicalSdkTest.java b/src/test/java/com/infisical/sdk/InfisicalSdkTest.java index a2bbc6b..6be74cf 100644 --- a/src/test/java/com/infisical/sdk/InfisicalSdkTest.java +++ b/src/test/java/com/infisical/sdk/InfisicalSdkTest.java @@ -1,6 +1,7 @@ package com.infisical.sdk; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.List; @@ -16,6 +17,22 @@ public class InfisicalSdkTest { private static final Logger logger = LoggerFactory.getLogger(InfisicalSdkTest.class); + @Test + public void TestRevokeToken() { + EnvironmentVariables envVars = new EnvironmentVariables(); + + InfisicalSdk sdk = new InfisicalSdk(new SdkConfig.Builder().withSiteUrl(envVars.getSiteUrl()).build()); + + assertDoesNotThrow(() -> { + sdk.Auth().UniversalAuthLogin(envVars.getMachineIdentityClientId(), envVars.getMachineIdentityClientSecret()); + }); + + assertDoesNotThrow(() -> sdk.Auth().RevokeToken()); + + // Verify the token is actually revoked — revoking it again should fail + assertThrows(InfisicalException.class, () -> sdk.Auth().RevokeToken()); + } + @Test public void TestListSecrets() { EnvironmentVariables envVars = new EnvironmentVariables(); diff --git a/src/test/java/com/infisical/sdk/resources/AuthClientTest.java b/src/test/java/com/infisical/sdk/resources/AuthClientTest.java index 8fcef82..144072b 100644 --- a/src/test/java/com/infisical/sdk/resources/AuthClientTest.java +++ b/src/test/java/com/infisical/sdk/resources/AuthClientTest.java @@ -21,6 +21,28 @@ public class AuthClientTest { @Mock private ApiClient apiClient; + @Test + public void RevokeToken_noArg_throwsWhenNoTokenIsSet() { + AuthClient authClient = new AuthClient(apiClient, token -> {}); + + InfisicalException ex = assertThrows(InfisicalException.class, () -> authClient.RevokeToken()); + assertEquals("Access token is required", ex.getMessage()); + } + + @Test + public void RevokeToken_noArg_callsPostWithStoredToken() throws InfisicalException { + when(apiClient.GetBaseUrl()).thenReturn("http://localhost"); + AuthClient authClient = new AuthClient(apiClient, token -> {}); + authClient.SetAccessToken("stored-token-456"); + + authClient.RevokeToken(); + + verify(apiClient).post( + eq("http://localhost/api/v1/auth/token/revoke"), + any(RevokeTokenInput.class), + eq(Void.class)); + } + @Test public void RevokeToken_throwsWhenAccessTokenIsNull() { AuthClient authClient = new AuthClient(apiClient, token -> {});