From dae60ffdb3a44d8b6f4c3b180269960d397cbd6b Mon Sep 17 00:00:00 2001 From: saileshwar-skyflow Date: Fri, 23 Jan 2026 11:54:14 +0530 Subject: [PATCH 1/3] SK-2505: add support for custom token uri --- .../java/com/skyflow/config/Credentials.java | 10 + .../java/com/skyflow/errors/ErrorMessage.java | 2 +- .../serviceaccount/util/BearerToken.java | 38 +++- .../serviceaccount/util/SignedDataTokens.java | 42 +++- src/main/java/com/skyflow/utils/Utils.java | 20 +- .../utils/validations/Validations.java | 6 + src/test/java/com/skyflow/SkyflowTests.java | 199 ++++++++++++++++++ .../serviceaccount/util/BearerTokenTests.java | 144 +++++++++++++ .../util/SignedDataTokensTests.java | 176 ++++++++++++++++ 9 files changed, 609 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/skyflow/config/Credentials.java b/src/main/java/com/skyflow/config/Credentials.java index f1865dc7..21545279 100644 --- a/src/main/java/com/skyflow/config/Credentials.java +++ b/src/main/java/com/skyflow/config/Credentials.java @@ -9,11 +9,13 @@ public class Credentials { private String credentialsString; private String token; private String apiKey; + private String tokenUri; public Credentials() { this.path = null; this.context = null; this.credentialsString = null; + this.tokenUri = null; } public String getPath() { @@ -63,4 +65,12 @@ public String getApiKey() { public void setApiKey(String apiKey) { this.apiKey = apiKey; } + + public String getTokenUri() { + return tokenUri; + } + + public void setTokenUri(String tokenUri) { + this.tokenUri = tokenUri; + } } diff --git a/src/main/java/com/skyflow/errors/ErrorMessage.java b/src/main/java/com/skyflow/errors/ErrorMessage.java index ac6adfd0..9d5b540f 100644 --- a/src/main/java/com/skyflow/errors/ErrorMessage.java +++ b/src/main/java/com/skyflow/errors/ErrorMessage.java @@ -44,7 +44,7 @@ public enum ErrorMessage { MissingClientId("%s0 Initialization failed. Unable to read client ID in credentials. Verify your client ID."), MissingKeyId("%s0 Initialization failed. Unable to read key ID in credentials. Verify your key ID."), MissingTokenUri("%s0 Initialization failed. Unable to read token URI in credentials. Verify your token URI."), - InvalidTokenUri("%s0 Initialization failed. Token URI in not a valid URL in credentials. Verify your token URI."), + InvalidTokenUri("%s0 Initialization failed. Invalid Skyflow credentials. The token URI must be a string and a valid URL."), JwtInvalidFormat("%s0 Initialization failed. Invalid private key format. Verify your credentials."), InvalidAlgorithm("%s0 Initialization failed. Invalid algorithm to parse private key. Specify valid algorithm."), InvalidKeySpec("%s0 Initialization failed. Unable to parse RSA private key. Verify your credentials."), diff --git a/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java b/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java index 21000f0f..29825e61 100644 --- a/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java +++ b/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java @@ -34,6 +34,7 @@ public class BearerToken { private final String ctx; private final ArrayList roles; private final String credentialsType; + private final String tokenUri; private BearerToken(BearerTokenBuilder builder) { this.credentialsFile = builder.credentialsFile; @@ -41,6 +42,7 @@ private BearerToken(BearerTokenBuilder builder) { this.ctx = builder.ctx; this.roles = builder.roles; this.credentialsType = builder.credentialsType; + this.tokenUri = builder.tokenUri; } public static BearerTokenBuilder builder() { @@ -48,7 +50,7 @@ public static BearerTokenBuilder builder() { } private static V1GetAuthTokenResponse generateBearerTokenFromCredentials( - File credentialsFile, String context, ArrayList roles + File credentialsFile, String context, ArrayList roles, String overrideTokenUri ) throws SkyflowException { LogUtil.printInfoLog(InfoLogs.GENERATE_BEARER_TOKEN_FROM_CREDENTIALS_TRIGGERED.getLog()); try { @@ -58,7 +60,7 @@ private static V1GetAuthTokenResponse generateBearerTokenFromCredentials( } FileReader reader = new FileReader(String.valueOf(credentialsFile)); JsonObject serviceAccountCredentials = JsonParser.parseReader(reader).getAsJsonObject(); - return getBearerTokenFromCredentials(serviceAccountCredentials, context, roles); + return getBearerTokenFromCredentials(serviceAccountCredentials, context, roles, overrideTokenUri); } catch (JsonSyntaxException e) { LogUtil.printErrorLog(ErrorLogs.INVALID_CREDENTIALS_FILE_FORMAT.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), Utils.parameterizedString( @@ -71,7 +73,7 @@ private static V1GetAuthTokenResponse generateBearerTokenFromCredentials( } private static V1GetAuthTokenResponse generateBearerTokenFromCredentialString( - String credentials, String context, ArrayList roles + String credentials, String context, ArrayList roles, String overrideTokenUri ) throws SkyflowException { LogUtil.printInfoLog(InfoLogs.GENERATE_BEARER_TOKEN_FROM_CREDENTIALS_STRING_TRIGGERED.getLog()); try { @@ -80,7 +82,7 @@ private static V1GetAuthTokenResponse generateBearerTokenFromCredentialString( throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidCredentials.getMessage()); } JsonObject serviceAccountCredentials = JsonParser.parseString(credentials).getAsJsonObject(); - return getBearerTokenFromCredentials(serviceAccountCredentials, context, roles); + return getBearerTokenFromCredentials(serviceAccountCredentials, context, roles, overrideTokenUri); } catch (JsonSyntaxException e) { LogUtil.printErrorLog(ErrorLogs.INVALID_CREDENTIALS_STRING_FORMAT.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), @@ -89,7 +91,7 @@ private static V1GetAuthTokenResponse generateBearerTokenFromCredentialString( } private static V1GetAuthTokenResponse getBearerTokenFromCredentials( - JsonObject credentials, String context, ArrayList roles + JsonObject credentials, String context, ArrayList roles, String overrideTokenUri ) throws SkyflowException { try { JsonElement privateKey = credentials.get("privateKey"); @@ -111,17 +113,19 @@ private static V1GetAuthTokenResponse getBearerTokenFromCredentials( } JsonElement tokenURI = credentials.get("tokenURI"); - if (tokenURI == null) { + if (tokenURI == null && overrideTokenUri == null) { LogUtil.printErrorLog(ErrorLogs.TOKEN_URI_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingTokenUri.getMessage()); } + String finalTokenUri = (overrideTokenUri != null) ? overrideTokenUri : tokenURI.getAsString(); + PrivateKey pvtKey = Utils.getPrivateKeyFromPem(privateKey.getAsString()); String signedUserJWT = getSignedToken( - clientID.getAsString(), keyID.getAsString(), tokenURI.getAsString(), pvtKey, context + clientID.getAsString(), keyID.getAsString(), finalTokenUri, pvtKey, context ); - String basePath = Utils.getBaseURL(tokenURI.getAsString()); + String basePath = Utils.getBaseURL(finalTokenUri); API_CLIENT_BUILDER.url(basePath); ApiClient apiClient = API_CLIENT_BUILDER.token("token").build(); AuthenticationClient authenticationApi = apiClient.authentication(); @@ -174,10 +178,10 @@ public synchronized String getBearerToken() throws SkyflowException { V1GetAuthTokenResponse response; String accessToken = null; if (this.credentialsFile != null && Objects.equals(this.credentialsType, "FILE")) { - response = generateBearerTokenFromCredentials(this.credentialsFile, this.ctx, this.roles); + response = generateBearerTokenFromCredentials(this.credentialsFile, this.ctx, this.roles, this.tokenUri); accessToken = response.getAccessToken().get(); } else if (this.credentialsString != null && Objects.equals(this.credentialsType, "STRING")) { - response = generateBearerTokenFromCredentialString(this.credentialsString, this.ctx, this.roles); + response = generateBearerTokenFromCredentialString(this.credentialsString, this.ctx, this.roles, this.tokenUri); accessToken = response.getAccessToken().get(); } LogUtil.printInfoLog(InfoLogs.GET_BEARER_TOKEN_SUCCESS.getLog()); @@ -191,6 +195,7 @@ public static class BearerTokenBuilder { private String ctx; private ArrayList roles; private String credentialsType; + private String tokenUri; private BearerTokenBuilder() { } @@ -221,6 +226,19 @@ public BearerTokenBuilder setRoles(ArrayList roles) { return this; } + public BearerTokenBuilder setTokenUri(String tokenUri) throws SkyflowException { + if (tokenUri != null && !tokenUri.isEmpty()) { + try { + new java.net.URL(tokenUri); + this.tokenUri = tokenUri; + } catch (MalformedURLException e) { + LogUtil.printErrorLog(ErrorLogs.INVALID_TOKEN_URI.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidTokenUri.getMessage()); + } + } + return this; + } + public BearerToken build() { return new BearerToken(this); } diff --git a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java index 70a5a330..f483cbf3 100644 --- a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java +++ b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java @@ -9,6 +9,7 @@ import com.skyflow.errors.SkyflowException; import com.skyflow.logs.ErrorLogs; import com.skyflow.logs.InfoLogs; +import com.skyflow.serviceaccount.util.SignedDataTokens.SignedDataTokensBuilder; import com.skyflow.utils.Utils; import com.skyflow.utils.logger.LogUtil; import io.jsonwebtoken.Jwts; @@ -16,6 +17,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; +import java.net.MalformedURLException; import java.security.PrivateKey; import java.util.ArrayList; import java.util.Date; @@ -29,6 +31,7 @@ public class SignedDataTokens { private final String ctx; private final ArrayList dataTokens; private final Integer timeToLive; + private final String tokenUri; private SignedDataTokens(SignedDataTokensBuilder builder) { this.credentialsFile = builder.credentialsFile; @@ -37,6 +40,7 @@ private SignedDataTokens(SignedDataTokensBuilder builder) { this.ctx = builder.ctx; this.dataTokens = builder.dataTokens; this.timeToLive = builder.timeToLive; + this.tokenUri = builder.tokenUri; } public static SignedDataTokensBuilder builder() { @@ -44,7 +48,7 @@ public static SignedDataTokensBuilder builder() { } private static List generateSignedTokenFromCredentialsFile( - File credentialsFile, ArrayList dataTokens, Integer timeToLive, String context + File credentialsFile, ArrayList dataTokens, Integer timeToLive, String context, String overrideTokenUri ) throws SkyflowException { LogUtil.printInfoLog(InfoLogs.GENERATE_SIGNED_TOKENS_FROM_CREDENTIALS_FILE_TRIGGERED.getLog()); List responseToken; @@ -55,7 +59,7 @@ private static List generateSignedTokenFromCredentialsF } FileReader reader = new FileReader(String.valueOf(credentialsFile)); JsonObject serviceAccountCredentials = JsonParser.parseReader(reader).getAsJsonObject(); - responseToken = generateSignedTokensFromCredentials(serviceAccountCredentials, dataTokens, timeToLive, context); + responseToken = generateSignedTokensFromCredentials(serviceAccountCredentials, dataTokens, timeToLive, context, overrideTokenUri); } catch (JsonSyntaxException e) { LogUtil.printErrorLog(ErrorLogs.INVALID_CREDENTIALS_FILE_FORMAT.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), Utils.parameterizedString( @@ -69,7 +73,7 @@ private static List generateSignedTokenFromCredentialsF } private static List generateSignedTokensFromCredentialsString( - String credentials, ArrayList dataTokens, Integer timeToLive, String context + String credentials, ArrayList dataTokens, Integer timeToLive, String context, String overrideTokenUri ) throws SkyflowException { LogUtil.printInfoLog(InfoLogs.GENERATE_SIGNED_TOKENS_FROM_CREDENTIALS_STRING_TRIGGERED.getLog()); List responseToken; @@ -79,7 +83,7 @@ private static List generateSignedTokensFromCredentials throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidCredentials.getMessage()); } JsonObject serviceAccountCredentials = JsonParser.parseString(credentials).getAsJsonObject(); - responseToken = generateSignedTokensFromCredentials(serviceAccountCredentials, dataTokens, timeToLive, context); + responseToken = generateSignedTokensFromCredentials(serviceAccountCredentials, dataTokens, timeToLive, context, overrideTokenUri); } catch (JsonSyntaxException e) { LogUtil.printErrorLog(ErrorLogs.INVALID_CREDENTIALS_STRING_FORMAT.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), @@ -89,7 +93,7 @@ private static List generateSignedTokensFromCredentials } private static List generateSignedTokensFromCredentials( - JsonObject credentials, ArrayList dataTokens, Integer timeToLive, String context + JsonObject credentials, ArrayList dataTokens, Integer timeToLive, String context, String overrideTokenUri ) throws SkyflowException { List signedDataTokens = null; try { @@ -112,7 +116,7 @@ private static List generateSignedTokensFromCredentials } PrivateKey pvtKey = Utils.getPrivateKeyFromPem(privateKey.getAsString()); signedDataTokens = getSignedToken( - clientID.getAsString(), keyID.getAsString(), pvtKey, dataTokens, timeToLive, context); + clientID.getAsString(), keyID.getAsString(), pvtKey, dataTokens, timeToLive, context, overrideTokenUri); } catch (RuntimeException e) { LogUtil.printErrorLog(ErrorLogs.SIGNED_DATA_TOKENS_REJECTED.getLog()); throw new SkyflowException(e); @@ -122,7 +126,7 @@ private static List generateSignedTokensFromCredentials private static List getSignedToken( String clientID, String keyID, PrivateKey pvtKey, - ArrayList dataTokens, Integer timeToLive, String context + ArrayList dataTokens, Integer timeToLive, String context, String overrideTokenUri ) { final Date createdDate = new Date(); final Date expirationDate; @@ -133,6 +137,11 @@ private static List getSignedToken( expirationDate = new Date(createdDate.getTime() + 60000); // Valid for 60 seconds } + String finalTokenUri = null; + if (overrideTokenUri != null && !overrideTokenUri.isEmpty()) { + finalTokenUri = overrideTokenUri; + } + List list = new ArrayList<>(); for (String dataToken : dataTokens) { String eachSignedDataToken = Jwts.builder() @@ -142,6 +151,7 @@ private static List getSignedToken( .claim("sub", clientID) .claim("ctx", context) .claim("tok", dataToken) + .claim("aud", finalTokenUri) .expiration(expirationDate) .signWith(pvtKey, Jwts.SIG.RS256) .compact(); @@ -155,9 +165,9 @@ public synchronized List getSignedDataTokens() throws S LogUtil.printInfoLog(InfoLogs.GET_SIGNED_DATA_TOKENS_TRIGGERED.getLog()); List signedToken = new ArrayList<>(); if (this.credentialsFile != null && Objects.equals(this.credentialsType, "FILE")) { - signedToken = generateSignedTokenFromCredentialsFile(this.credentialsFile, this.dataTokens, this.timeToLive, this.ctx); + signedToken = generateSignedTokenFromCredentialsFile(this.credentialsFile, this.dataTokens, this.timeToLive, this.ctx, this.tokenUri); } else if (this.credentialsString != null && Objects.equals(this.credentialsType, "STRING")) { - signedToken = generateSignedTokensFromCredentialsString(this.credentialsString, this.dataTokens, this.timeToLive, this.ctx); + signedToken = generateSignedTokensFromCredentialsString(this.credentialsString, this.dataTokens, this.timeToLive, this.ctx, this.tokenUri); } LogUtil.printInfoLog(InfoLogs.GET_SIGNED_DATA_TOKEN_SUCCESS.getLog()); return signedToken; @@ -170,6 +180,7 @@ public static class SignedDataTokensBuilder { private String credentialsString; private String ctx; private String credentialsType; + private String tokenUri; private SignedDataTokensBuilder() { } @@ -205,6 +216,19 @@ public SignedDataTokensBuilder setTimeToLive(Integer timeToLive) { return this; } + public SignedDataTokensBuilder setTokenUri(String tokenUri) throws SkyflowException { + if (tokenUri != null && !tokenUri.isEmpty()) { + try { + new java.net.URL(tokenUri); + this.tokenUri = tokenUri; + } catch (MalformedURLException e) { + LogUtil.printErrorLog(ErrorLogs.INVALID_TOKEN_URI.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidTokenUri.getMessage()); + } + } + return this; + } + public SignedDataTokens build() { return new SignedDataTokens(this); } diff --git a/src/main/java/com/skyflow/utils/Utils.java b/src/main/java/com/skyflow/utils/Utils.java index 165c6a80..5d566d0f 100644 --- a/src/main/java/com/skyflow/utils/Utils.java +++ b/src/main/java/com/skyflow/utils/Utils.java @@ -49,19 +49,23 @@ public static String getVaultURL(String clusterId, Env env) { public static String generateBearerToken(Credentials credentials) throws SkyflowException { if (credentials.getPath() != null) { - return BearerToken.builder() + BearerToken.BearerTokenBuilder builder = BearerToken.builder() .setCredentials(new File(credentials.getPath())) .setRoles(credentials.getRoles()) - .setCtx(credentials.getContext()) - .build() - .getBearerToken(); + .setCtx(credentials.getContext()); + if (credentials.getTokenUri() != null) { + builder.setTokenUri(credentials.getTokenUri()); + } + return builder.build().getBearerToken(); } else if (credentials.getCredentialsString() != null) { - return BearerToken.builder() + BearerToken.BearerTokenBuilder builder = BearerToken.builder() .setCredentials(credentials.getCredentialsString()) .setRoles(credentials.getRoles()) - .setCtx(credentials.getContext()) - .build() - .getBearerToken(); + .setCtx(credentials.getContext()); + if (credentials.getTokenUri() != null) { + builder.setTokenUri(credentials.getTokenUri()); + } + return builder.build().getBearerToken(); } else { return credentials.getToken(); } diff --git a/src/main/java/com/skyflow/utils/validations/Validations.java b/src/main/java/com/skyflow/utils/validations/Validations.java index 0372749a..0ea68888 100644 --- a/src/main/java/com/skyflow/utils/validations/Validations.java +++ b/src/main/java/com/skyflow/utils/validations/Validations.java @@ -154,6 +154,7 @@ public static void validateCredentials(Credentials credentials) throws SkyflowEx String token = credentials.getToken(); String apiKey = credentials.getApiKey(); String context = credentials.getContext(); + String tokenUri = credentials.getTokenUri(); ArrayList roles = credentials.getRoles(); if (path != null) nonNullMembers++; @@ -212,6 +213,11 @@ public static void validateCredentials(Credentials credentials) throws SkyflowEx LogUtil.printErrorLog(ErrorLogs.EMPTY_OR_NULL_CONTEXT.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyContext.getMessage()); } + + if (tokenUri != null && isInvalidURL(tokenUri)) { + LogUtil.printErrorLog(ErrorLogs.INVALID_TOKEN_URI.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidTokenUri.getMessage()); + } } public static void validateDetokenizeRequest(DetokenizeRequest detokenizeRequest) throws SkyflowException { diff --git a/src/test/java/com/skyflow/SkyflowTests.java b/src/test/java/com/skyflow/SkyflowTests.java index 0b44c0b4..2dd18649 100644 --- a/src/test/java/com/skyflow/SkyflowTests.java +++ b/src/test/java/com/skyflow/SkyflowTests.java @@ -566,4 +566,203 @@ public void testDetectMethodWithInvalidVaultId() { Assert.assertEquals(ErrorMessage.VaultIdNotInConfigList.getMessage(), e.getMessage()); } } + + @Test + public void testAddingSkyflowCredentialsWithValidTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("https://example.com/token"); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testAddingSkyflowCredentialsWithNullTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri(null); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testAddingSkyflowCredentialsWithEmptyTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri(""); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testAddingSkyflowCredentialsWithInvalidTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("invalid_token_uri"); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testAddingSkyflowCredentialsWithMalformedTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("htp://invalid-url"); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testAddingSkyflowCredentialsWithHttpTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("http://localhost:8080/oauth/token"); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + // HTTP is not allowed, only HTTPS is allowed + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testAddingSkyflowCredentialsWithValidHttpsTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("https://custom.oauth.endpoint.com/token"); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testAddingSkyflowCredentialsWithTokenUriWithPort() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("https://example.com/token"); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testAddingSkyflowCredentialsWithTokenUriWithQueryParams() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("https://example.com/token?clientId=test"); + Skyflow.builder().addSkyflowCredentials(credentials).build(); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testUpdatingSkyflowCredentialsWithValidTokenUri() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setClusterId(clusterID); + + ConnectionConfig connectionConfig = new ConnectionConfig(); + connectionConfig.setConnectionId(connectionID); + connectionConfig.setConnectionUrl(connectionURL); + + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("https://example.com/token"); + Skyflow skyflowClient = Skyflow.builder().addVaultConfig(vaultConfig).addConnectionConfig(connectionConfig).build(); + skyflowClient.updateSkyflowCredentials(credentials); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testUpdatingSkyflowCredentialsWithInvalidTokenUri() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setClusterId(clusterID); + + ConnectionConfig connectionConfig = new ConnectionConfig(); + connectionConfig.setConnectionId(connectionID); + connectionConfig.setConnectionUrl(connectionURL); + + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("not_a_valid_url"); + Skyflow skyflowClient = Skyflow.builder().addVaultConfig(vaultConfig).addConnectionConfig(connectionConfig).build(); + skyflowClient.updateSkyflowCredentials(credentials); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testAddingVaultConfigWithCredentialsHavingValidTokenUri() { + try { + VaultConfig config = new VaultConfig(); + config.setVaultId(vaultID); + config.setClusterId(clusterID); + config.setEnv(Env.SANDBOX); + + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("https://example.com/token"); + config.setCredentials(credentials); + + Skyflow.builder().addVaultConfig(config).build(); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testAddingVaultConfigWithCredentialsHavingInvalidTokenUri() { + try { + VaultConfig config = new VaultConfig(); + config.setVaultId(vaultID); + config.setClusterId(clusterID); + config.setEnv(Env.SANDBOX); + + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setTokenUri("invalid_uri_format"); + config.setCredentials(credentials); + + Skyflow.builder().addVaultConfig(config).build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } } diff --git a/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java b/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java index 4bfb697c..1bb623e4 100644 --- a/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java +++ b/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java @@ -222,4 +222,148 @@ public void testInvalidTokenURIInCredentialsForCredentials() throws SkyflowExcep Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); } } + + @Test + public void testBearerTokenBuilderWithValidTokenUri() { + try { + roles.add(role); + File file = new File(credentialsFilePath); + BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://example.com/token") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testBearerTokenBuilderWithNullTokenUri() { + try { + roles.add(role); + File file = new File(credentialsFilePath); + BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri(null) + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testBearerTokenBuilderWithEmptyTokenUri() { + try { + roles.add(role); + File file = new File(credentialsFilePath); + BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testBearerTokenBuilderWithInvalidTokenUri() { + try { + File file = new File(credentialsFilePath); + BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("invalid_token_uri") + .build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testBearerTokenBuilderWithInvalidTokenUriFormat() { + try { + File file = new File(credentialsFilePath); + BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("htp://invalid-url") + .build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testBearerTokenBuilderWithValidHttpTokenUri() { + try { + roles.add(role); + File file = new File(credentialsFilePath); + BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("http://localhost:8080/oauth/token") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testBearerTokenBuilderWithCredentialsStringAndTokenUri() { + try { + BearerToken.builder() + .setCredentials(credentialsString) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://example.com/token") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testTokenUriOverridesCredentialsTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://custom-token-uri.com/test") + .build(); + Assert.assertNotNull(bearerToken); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testTokenUriWithSpecialCharacters() { + try { + File file = new File(credentialsFilePath); + BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://example.com/token?param=value") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } } diff --git a/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java b/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java index f431042d..ca1b7954 100644 --- a/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java +++ b/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java @@ -222,4 +222,180 @@ public void testSignedDataTokenResponse() { Assert.fail(INVALID_EXCEPTION_THROWN); } } + + @Test + public void testSignedDataTokensBuilderWithValidTokenUri() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://example.com/token") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testSignedDataTokensBuilderWithNullTokenUri() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri(null) + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testSignedDataTokensBuilderWithEmptyTokenUri() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testSignedDataTokensBuilderWithInvalidTokenUri() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("invalid_token_uri") + .build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testSignedDataTokensBuilderWithInvalidTokenUriFormat() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("htp://invalid-url") + .build(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testSignedDataTokensBuilderWithValidHttpTokenUri() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("http://localhost:8080/token") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testSignedDataTokensBuilderWithCredentialsStringAndTokenUri() { + try { + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(credentialsString) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://example.com/token") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testTokenUriOverridesCredentialsTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://custom-token-uri.com/test") + .build(); + Assert.assertNotNull(signedDataTokens); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testTokenUriWithSpecialCharacters() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://manage.skyflowapis.dev:8080/v1/auth/sa/oauth/token?param=value") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testSignedDataTokensBuilderWithMultipleTokenUriCalls() { + try { + File file = new File(credentialsFilePath); + dataTokens.add(dataToken); + SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://first-uri.com/oauth/token") + .setTokenUri("https://second-uri.com/oauth/token") + .build(); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } } From 9aa9d68e5cad1c52a3ab281e64da6d74bb845451 Mon Sep 17 00:00:00 2001 From: saileshwar-skyflow Date: Fri, 23 Jan 2026 12:58:04 +0530 Subject: [PATCH 2/3] SK-2505: add unit tests --- .../serviceaccount/util/BearerTokenTests.java | 201 ++++++++++++++++++ .../java/com/skyflow/utils/UtilsTests.java | 120 +++++++++++ 2 files changed, 321 insertions(+) diff --git a/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java b/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java index 1bb623e4..8dc86db5 100644 --- a/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java +++ b/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java @@ -366,4 +366,205 @@ public void testTokenUriWithSpecialCharacters() { Assert.fail(INVALID_EXCEPTION_THROWN); } } + + @Test + public void testBearerTokenWithOverrideTokenUriFromFile() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-token-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenWithoutOverrideTokenUriFromFile() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + private static final String MOCK_PRIVATE_KEY = "mock-private-key"; + private static final String MOCK_CLIENT_ID = "test_client_id"; + private static final String MOCK_KEY_ID = "test_key_id"; + private static final String MOCK_TOKEN_URI = "https://example.com/token"; + + private static String createMockCredentialsJson(String privateKey, String clientId, String keyId, String tokenUri) { + StringBuilder json = new StringBuilder("{"); + json.append("\"privateKey\": \"").append(privateKey).append("\","); + json.append("\"clientID\": \"").append(clientId).append("\","); + json.append("\"keyID\": \"").append(keyId).append("\""); + if (tokenUri != null) { + json.append(",\"tokenURI\": \"").append(tokenUri).append("\""); + } + json.append("}"); + return json.toString(); + } + + @Test + public void testBearerTokenWithOverrideTokenUriFromString() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-token-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenWithoutOverrideTokenUriFromString() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenWithOverrideTokenUriWhenCredentialsHaveTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-token-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenWhenTokenURIIsNullAndOverrideIsNull() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, null); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.MissingTokenUri.getMessage(), e.getMessage()); + } + } + + @Test + public void testBearerTokenWhenTokenURIIsNullButOverrideIsProvided() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, null); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenWhenBothTokenURIAndOverrideAreProvided() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenLineAudClaimWithOverrideTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenLineAudClaimWithCredentialsTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testBearerTokenFinalTokenUriSelection() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, "https://credentials-uri.com/token"); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } } diff --git a/src/test/java/com/skyflow/utils/UtilsTests.java b/src/test/java/com/skyflow/utils/UtilsTests.java index 4e910e15..9d056fc0 100644 --- a/src/test/java/com/skyflow/utils/UtilsTests.java +++ b/src/test/java/com/skyflow/utils/UtilsTests.java @@ -216,4 +216,124 @@ public void testGetMetricsWithException() { Assert.fail(INVALID_EXCEPTION_THROWN); } } + + @Test + public void testGenerateBearerTokenWithCredentialsFileAndValidTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setPath(filePath); + credentials.setContext(context); + credentials.setRoles(roles); + credentials.setTokenUri("https://example.com/token"); + Utils.generateBearerToken(credentials); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals( + Utils.parameterizedString(ErrorMessage.FileNotFound.getMessage(), filePath), + e.getMessage() + ); + } + } + + @Test + public void testGenerateBearerTokenWithCredentialsFileAndNullTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setPath(filePath); + credentials.setContext(context); + credentials.setRoles(roles); + credentials.setTokenUri(null); + Utils.generateBearerToken(credentials); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals( + Utils.parameterizedString(ErrorMessage.FileNotFound.getMessage(), filePath), + e.getMessage() + ); + } + } + + @Test + public void testGenerateBearerTokenWithCredentialsStringAndValidTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setCredentialsString(credentialsString); + credentials.setContext(context); + credentials.setRoles(roles); + credentials.setTokenUri("https://example.com/token"); + Utils.generateBearerToken(credentials); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.CredentialsStringInvalidJson.getMessage(), e.getMessage()); + } + } + + @Test + public void testGenerateBearerTokenWithCredentialsStringAndNullTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setCredentialsString(credentialsString); + credentials.setContext(context); + credentials.setRoles(roles); + credentials.setTokenUri(null); + Utils.generateBearerToken(credentials); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.CredentialsStringInvalidJson.getMessage(), e.getMessage()); + } + } + + @Test + public void testGenerateBearerTokenWithTokenAndValidTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setToken(token); + credentials.setContext(context); + credentials.setRoles(roles); + credentials.setTokenUri("https://example.com/token"); + String bearerToken = Utils.generateBearerToken(credentials); + Assert.assertEquals(token, bearerToken); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testGenerateBearerTokenWithCredentialsFileAndEmptyTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setPath(filePath); + credentials.setContext(context); + credentials.setRoles(roles); + credentials.setTokenUri(""); + Utils.generateBearerToken(credentials); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals( + Utils.parameterizedString(ErrorMessage.FileNotFound.getMessage(), filePath), + e.getMessage() + ); + } + } + + @Test + public void testGenerateBearerTokenWithCredentialsStringAndHttpTokenUri() { + try { + Credentials credentials = new Credentials(); + credentials.setCredentialsString(credentialsString); + credentials.setContext(context); + credentials.setRoles(roles); + credentials.setTokenUri("http://localhost:8080/oauth/token"); + Utils.generateBearerToken(credentials); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.CredentialsStringInvalidJson.getMessage(), e.getMessage()); + } + } } From d828aac62a0e22ee92d90982cbfd456657d5967e Mon Sep 17 00:00:00 2001 From: saileshwar-skyflow Date: Tue, 27 Jan 2026 12:42:09 +0530 Subject: [PATCH 3/3] SK-2505: increase tests coverage --- .../serviceaccount/util/SignedDataTokens.java | 1 - .../serviceaccount/util/BearerTokenTests.java | 138 ++++++++++++ .../util/SignedDataTokensTests.java | 208 ++++++++++++++++++ 3 files changed, 346 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java index f483cbf3..c32c0af3 100644 --- a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java +++ b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java @@ -9,7 +9,6 @@ import com.skyflow.errors.SkyflowException; import com.skyflow.logs.ErrorLogs; import com.skyflow.logs.InfoLogs; -import com.skyflow.serviceaccount.util.SignedDataTokens.SignedDataTokensBuilder; import com.skyflow.utils.Utils; import com.skyflow.utils.logger.LogUtil; import io.jsonwebtoken.Jwts; diff --git a/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java b/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java index 8dc86db5..5d0ccd6b 100644 --- a/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java +++ b/src/test/java/com/skyflow/serviceaccount/util/BearerTokenTests.java @@ -567,4 +567,142 @@ public void testBearerTokenFinalTokenUriSelection() { Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); } } + + @Test + public void testGetBearerTokenFromCredentialsFilePathCovered() { + + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetBearerTokenFromCredentialsFilePathWithOverrideTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetBearerTokenFromCredentialsStringPathCovered() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetBearerTokenFromCredentialsStringPathWithOverrideTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetBearerTokenWithApiClientInitialization() { + + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetBearerTokenWithApiClientInitializationAndOverrideTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setRoles(roles) + .setTokenUri("https://override-uri.com/token") + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetBearerTokenApiClientWithRoles() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + roles.add("admin"); + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .setRoles(roles) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetBearerTokenApiClientWithoutRoles() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + BearerToken bearerToken = BearerToken.builder() + .setCredentials(file) + .setCtx(context) + .build(); + bearerToken.getBearerToken(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } } diff --git a/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java b/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java index ca1b7954..2edab728 100644 --- a/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java +++ b/src/test/java/com/skyflow/serviceaccount/util/SignedDataTokensTests.java @@ -398,4 +398,212 @@ public void testSignedDataTokensBuilderWithMultipleTokenUriCalls() { Assert.fail(INVALID_EXCEPTION_THROWN); } } + + private static final String MOCK_PRIVATE_KEY = "mock-private-key"; + private static final String MOCK_CLIENT_ID = "test_client_id"; + private static final String MOCK_KEY_ID = "test_key_id"; + private static final String MOCK_TOKEN_URI = "https://example.com/token"; + + private static String createMockCredentialsJson(String privateKey, String clientId, String keyId, String tokenUri) { + StringBuilder json = new StringBuilder("{"); + json.append("\"privateKey\": \"").append(privateKey).append("\","); + json.append("\"clientID\": \"").append(clientId).append("\","); + json.append("\"keyID\": \"").append(keyId).append("\""); + if (tokenUri != null) { + json.append(",\"tokenURI\": \"").append(tokenUri).append("\""); + } + json.append("}"); + return json.toString(); + } + + @Test + public void testGetSignedDataTokensFromCredentialsFilePathCovered() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetSignedDataTokensFromCredentialsFilePathWithOverrideTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://override-uri.com/token") + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetSignedDataTokensFromCredentialsStringPathCovered() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetSignedDataTokensFromCredentialsStringPathWithOverrideTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://override-uri.com/token") + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGenerateSignedTokenFromCredentialsFileWithOverrideTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://override-uri.com/token") + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGenerateSignedTokenFromCredentialsFileWithoutOverrideTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGenerateSignedTokenFromCredentialsStringWithOverrideTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://override-uri.com/token") + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGenerateSignedTokenFromCredentialsStringWithoutOverrideTokenUri() { + String mockCredentialsJson = createMockCredentialsJson(MOCK_PRIVATE_KEY, MOCK_CLIENT_ID, MOCK_KEY_ID, MOCK_TOKEN_URI); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(mockCredentialsJson) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetSignedTokenWithPrivateKeyAndOverrideTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .setTokenUri("https://override-uri.com/token") + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } + + @Test + public void testGetSignedTokenWithPrivateKeyWithoutOverrideTokenUri() { + String filePath = "./src/test/resources/validCredentials.json"; + File file = new File(filePath); + try { + dataTokens.add(dataToken); + SignedDataTokens signedDataTokens = SignedDataTokens.builder() + .setCredentials(file) + .setCtx(context) + .setDataTokens(dataTokens) + .setTimeToLive(ttl) + .build(); + signedDataTokens.getSignedDataTokens(); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + } + } }