From 1ae7fbaf0b10e2cedec00151f4b007cce1eeaff7 Mon Sep 17 00:00:00 2001 From: Dawid Heyman Date: Thu, 28 Nov 2024 23:12:48 +0100 Subject: [PATCH] SNOW-1825471: Port and remove snowflake-common auth related codebase --- .../snowflake/client/core/ClientAuthnDTO.java | 69 +++++++++++++++++++ .../client/core/ClientAuthnParameter.java | 19 +++++ .../net/snowflake/client/core/SFSession.java | 1 - .../snowflake/client/core/SessionUtil.java | 15 ++-- .../core/SessionUtilExternalBrowser.java | 5 +- .../core/SessionUtilExternalBrowserTest.java | 1 - .../client/core/SessionUtilLatestIT.java | 1 - .../client/jdbc/ConnectionLatestIT.java | 7 +- .../client/jdbc/SSOConnectionTest.java | 3 +- .../client/jdbc/SnowflakeDriverIT.java | 2 +- 10 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 src/main/java/net/snowflake/client/core/ClientAuthnDTO.java create mode 100644 src/main/java/net/snowflake/client/core/ClientAuthnParameter.java diff --git a/src/main/java/net/snowflake/client/core/ClientAuthnDTO.java b/src/main/java/net/snowflake/client/core/ClientAuthnDTO.java new file mode 100644 index 000000000..4c4635adc --- /dev/null +++ b/src/main/java/net/snowflake/client/core/ClientAuthnDTO.java @@ -0,0 +1,69 @@ +package net.snowflake.client.core; +/* + * Copyright (c) 2024 Snowflake Computing Inc. All right reserved. + */ + +import javax.annotation.Nullable; +import java.util.Map; + +@SnowflakeJdbcInternalApi +public class ClientAuthnDTO { + + public enum AuthenticatorType { + /* + * regular login username+password via Snowflake, may or may not have MFA + */ + SNOWFLAKE, + + /* + * federated authentication, OKTA as IDP + */ + OKTA, + + /* + * Web browser based authenticator for SAML 2.0 compliant + * service/application + */ + EXTERNALBROWSER, + + /* + * OAUTH 2.0 flow + */ + OAUTH, + + /* + * Snowflake local authentication using jwt token as a user credential + */ + SNOWFLAKE_JWT, + + /* + * Internal authenticator to enable id_token for web browser based authenticator + */ + ID_TOKEN, + + /* + * Authenticator to enable token for regular login with mfa + */ + USERNAME_PASSWORD_MFA, + + /* + * Authenticator to support PAT + */ + PROGRAMMATIC_ACCESS_TOKEN, + } + + // contains all the required data for current authn step + public final Map data; + + /* + * current state + * tokenized string with all current parameters and the authn step + */ + public final String inFlightCtx; + + /** Required by Jackson */ + public ClientAuthnDTO(Map data, @Nullable String inFlightCtx) { + this.data = data; + this.inFlightCtx = inFlightCtx; + } +} diff --git a/src/main/java/net/snowflake/client/core/ClientAuthnParameter.java b/src/main/java/net/snowflake/client/core/ClientAuthnParameter.java new file mode 100644 index 000000000..31ec2edce --- /dev/null +++ b/src/main/java/net/snowflake/client/core/ClientAuthnParameter.java @@ -0,0 +1,19 @@ +package net.snowflake.client.core; + +@SnowflakeJdbcInternalApi +public enum ClientAuthnParameter { + LOGIN_NAME, + PASSWORD, + RAW_SAML_RESPONSE, + ACCOUNT_NAME, + CLIENT_APP_ID, + CLIENT_APP_VERSION, + EXT_AUTHN_DUO_METHOD, + PASSCODE, + CLIENT_ENVIRONMENT, + AUTHENTICATOR, + BROWSER_MODE_REDIRECT_PORT, + SESSION_PARAMETERS, + PROOF_KEY, + TOKEN +} diff --git a/src/main/java/net/snowflake/client/core/SFSession.java b/src/main/java/net/snowflake/client/core/SFSession.java index c3708ea7e..7a396ced2 100644 --- a/src/main/java/net/snowflake/client/core/SFSession.java +++ b/src/main/java/net/snowflake/client/core/SFSession.java @@ -49,7 +49,6 @@ import net.snowflake.client.log.SFLoggerFactory; import net.snowflake.client.log.SFLoggerUtil; import net.snowflake.client.util.Stopwatch; -import net.snowflake.common.core.ClientAuthnDTO; import net.snowflake.common.core.SqlState; import org.apache.http.HttpHeaders; import org.apache.http.client.methods.HttpGet; diff --git a/src/main/java/net/snowflake/client/core/SessionUtil.java b/src/main/java/net/snowflake/client/core/SessionUtil.java index de0eb3a87..5bf56f33e 100644 --- a/src/main/java/net/snowflake/client/core/SessionUtil.java +++ b/src/main/java/net/snowflake/client/core/SessionUtil.java @@ -38,8 +38,6 @@ import net.snowflake.client.log.SFLoggerFactory; import net.snowflake.client.util.SecretDetector; import net.snowflake.client.util.Stopwatch; -import net.snowflake.common.core.ClientAuthnDTO; -import net.snowflake.common.core.ClientAuthnParameter; import net.snowflake.common.core.SqlState; import org.apache.http.HttpHeaders; import org.apache.http.client.config.RequestConfig; @@ -453,9 +451,6 @@ private static SFLoginOutput newSession( HttpPost postRequest = null; try { - ClientAuthnDTO authnData = new ClientAuthnDTO(); - authnData.setInFlightCtx(loginInput.getInFlightCtx()); - Map data = new HashMap<>(); data.put(ClientAuthnParameter.CLIENT_APP_ID.name(), loginInput.getAppId()); @@ -621,8 +616,7 @@ private static SFLoginOutput newSession( } data.put(ClientAuthnParameter.CLIENT_APP_VERSION.name(), loginInput.getAppVersion()); - - authnData.setData(data); + ClientAuthnDTO authnData = new ClientAuthnDTO(data, loginInput.getInFlightCtx()); String json = mapper.writeValueAsString(authnData); postRequest = new HttpPost(loginURI); @@ -691,8 +685,8 @@ private static SFLoginOutput newSession( // If we need to retry, we need to get a new Okta token tokenOrSamlResponse = getSamlResponseUsingOkta(loginInput); data.put(ClientAuthnParameter.RAW_SAML_RESPONSE.name(), tokenOrSamlResponse); - authnData.setData(data); - String updatedJson = mapper.writeValueAsString(authnData); + ClientAuthnDTO updatedAuthnData = new ClientAuthnDTO(data, loginInput.getInFlightCtx()); + String updatedJson = mapper.writeValueAsString(updatedAuthnData); StringEntity updatedInput = new StringEntity(updatedJson, StandardCharsets.UTF_8); updatedInput.setContentType("application/json"); @@ -1378,8 +1372,7 @@ private static JsonNode federatedFlowStep1(SFLoginInput loginInput) throws Snowf data.put(ClientAuthnParameter.CLIENT_APP_ID.name(), loginInput.getAppId()); data.put(ClientAuthnParameter.CLIENT_APP_VERSION.name(), loginInput.getAppVersion()); - ClientAuthnDTO authnData = new ClientAuthnDTO(); - authnData.setData(data); + ClientAuthnDTO authnData = new ClientAuthnDTO(data, null); String json = mapper.writeValueAsString(authnData); // attach the login info json body to the post request diff --git a/src/main/java/net/snowflake/client/core/SessionUtilExternalBrowser.java b/src/main/java/net/snowflake/client/core/SessionUtilExternalBrowser.java index 8d6008e38..0679cc478 100644 --- a/src/main/java/net/snowflake/client/core/SessionUtilExternalBrowser.java +++ b/src/main/java/net/snowflake/client/core/SessionUtilExternalBrowser.java @@ -32,8 +32,6 @@ import net.snowflake.client.jdbc.SnowflakeSQLException; import net.snowflake.client.log.SFLogger; import net.snowflake.client.log.SFLoggerFactory; -import net.snowflake.common.core.ClientAuthnDTO; -import net.snowflake.common.core.ClientAuthnParameter; import net.snowflake.common.core.SqlState; import org.apache.http.NameValuePair; import org.apache.http.client.methods.HttpPost; @@ -175,7 +173,6 @@ private String getSSOUrl(int port) throws SFException, SnowflakeSQLException { HttpPost postRequest = this.handlers.build(fedUrlUri); - ClientAuthnDTO authnData = new ClientAuthnDTO(); Map data = new HashMap<>(); data.put(ClientAuthnParameter.AUTHENTICATOR.name(), authenticator); @@ -185,7 +182,7 @@ private String getSSOUrl(int port) throws SFException, SnowflakeSQLException { data.put(ClientAuthnParameter.CLIENT_APP_ID.name(), loginInput.getAppId()); data.put(ClientAuthnParameter.CLIENT_APP_VERSION.name(), loginInput.getAppVersion()); - authnData.setData(data); + ClientAuthnDTO authnData = new ClientAuthnDTO(data, null); String json = mapper.writeValueAsString(authnData); // attach the login info json body to the post request diff --git a/src/test/java/net/snowflake/client/core/SessionUtilExternalBrowserTest.java b/src/test/java/net/snowflake/client/core/SessionUtilExternalBrowserTest.java index 02f6193d6..4f7bd0023 100644 --- a/src/test/java/net/snowflake/client/core/SessionUtilExternalBrowserTest.java +++ b/src/test/java/net/snowflake/client/core/SessionUtilExternalBrowserTest.java @@ -28,7 +28,6 @@ import net.snowflake.client.jdbc.SnowflakeBasicDataSource; import net.snowflake.client.jdbc.SnowflakeSQLException; import net.snowflake.client.jdbc.SnowflakeSQLLoggedException; -import net.snowflake.common.core.ClientAuthnDTO; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.hamcrest.MatcherAssert; diff --git a/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java b/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java index 57dde2a7b..5124318b6 100644 --- a/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java +++ b/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java @@ -25,7 +25,6 @@ import net.snowflake.client.jdbc.BaseJDBCTest; import net.snowflake.client.jdbc.ErrorCode; import net.snowflake.client.jdbc.SnowflakeSQLException; -import net.snowflake.common.core.ClientAuthnDTO; import net.snowflake.common.core.SqlState; import org.apache.commons.io.IOUtils; import org.apache.http.Header; diff --git a/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java b/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java index 68cd101bf..5dcfb3130 100644 --- a/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java +++ b/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java @@ -55,6 +55,8 @@ import net.snowflake.client.annotations.DontRunOnGithubActions; import net.snowflake.client.annotations.RunOnAWS; import net.snowflake.client.category.TestTags; +import net.snowflake.client.core.ClientAuthnDTO; +import net.snowflake.client.core.ClientAuthnParameter; import net.snowflake.client.core.HttpClientSettingsKey; import net.snowflake.client.core.HttpUtil; import net.snowflake.client.core.ObjectMapperFactory; @@ -66,8 +68,6 @@ import net.snowflake.client.jdbc.telemetryOOB.TelemetryService; import net.snowflake.client.log.SFLogger; import net.snowflake.client.log.SFLoggerFactory; -import net.snowflake.common.core.ClientAuthnDTO; -import net.snowflake.common.core.ClientAuthnParameter; import net.snowflake.common.core.SqlState; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; @@ -1252,8 +1252,7 @@ public void testAuthenticatorEndpointWithDashInAccountName() throws Exception { Map data = Collections.singletonMap(ClientAuthnParameter.ACCOUNT_NAME.name(), "snowhouse-local"); - ClientAuthnDTO authnData = new ClientAuthnDTO(); - authnData.setData(data); + ClientAuthnDTO authnData = new ClientAuthnDTO(data, null); ObjectMapper mapper = ObjectMapperFactory.getObjectMapper(); String json = mapper.writeValueAsString(authnData); diff --git a/src/test/java/net/snowflake/client/jdbc/SSOConnectionTest.java b/src/test/java/net/snowflake/client/jdbc/SSOConnectionTest.java index 6fbadd92f..e965fde1c 100644 --- a/src/test/java/net/snowflake/client/jdbc/SSOConnectionTest.java +++ b/src/test/java/net/snowflake/client/jdbc/SSOConnectionTest.java @@ -29,13 +29,14 @@ import java.sql.DriverManager; import java.util.ArrayList; import java.util.Properties; + +import net.snowflake.client.core.ClientAuthnDTO; import net.snowflake.client.core.HttpClientSettingsKey; import net.snowflake.client.core.HttpUtil; import net.snowflake.client.core.SFException; import net.snowflake.client.core.SFLoginInput; import net.snowflake.client.core.SessionUtil; import net.snowflake.client.core.SessionUtilExternalBrowser; -import net.snowflake.common.core.ClientAuthnDTO; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.HttpPost; import org.junit.jupiter.api.Test; diff --git a/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverIT.java b/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverIT.java index b245f8c0b..d56198716 100644 --- a/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverIT.java +++ b/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverIT.java @@ -54,7 +54,7 @@ import net.snowflake.client.annotations.DontRunOnGithubActions; import net.snowflake.client.annotations.DontRunOnTestaccount; import net.snowflake.client.category.TestTags; -import net.snowflake.common.core.ClientAuthnDTO; +import net.snowflake.client.core.ClientAuthnDTO; import net.snowflake.common.core.SqlState; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.AfterAll;