Skip to content

Commit

Permalink
SNOW-877275 : Build the console login url (#1518)
Browse files Browse the repository at this point in the history
* Build the console login url

* Added URL builder instead of building URL string manually

* Fix formatting issue

* Added proof key and rename port parameter name

* Pass proofkey for second call to GS

* Fix coding style issue
  • Loading branch information
sfc-gh-igarish authored Dec 7, 2023
1 parent 241d393 commit 742c2f1
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 8 deletions.
11 changes: 11 additions & 0 deletions src/main/java/net/snowflake/client/core/SFLoginInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class SFLoginInput {
private String privateKeyFilePwd;
private String inFlightCtx; // Opaque string sent for Snowsight account activation

private boolean disableConsoleLogin = true;

// Additional headers to add for Snowsight.
Map<String, String> additionalHttpHeadersForSnowsight;

Expand All @@ -64,6 +66,15 @@ SFLoginInput setServerUrl(String serverUrl) {
return this;
}

public boolean getDisableConsoleLogin() {
return disableConsoleLogin;
}

SFLoginInput setDisableConsoleLogin(boolean disableConsoleLogin) {
this.disableConsoleLogin = disableConsoleLogin;
return this;
}

String getDatabaseName() {
return databaseName;
}
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/net/snowflake/client/core/SFSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,12 @@ public synchronized void open() throws SFException, SnowflakeSQLException {
.setApplication((String) connectionPropertiesMap.get(SFSessionProperty.APPLICATION))
.setServiceName(getServiceName())
.setOCSPMode(getOCSPMode())
.setHttpClientSettingsKey(httpClientSettingsKey);
.setHttpClientSettingsKey(httpClientSettingsKey)
.setDisableConsoleLogin(
connectionPropertiesMap.get(SFSessionProperty.DISABLE_CONSOLE_LOGIN) != null
? getBooleanValue(
connectionPropertiesMap.get(SFSessionProperty.DISABLE_CONSOLE_LOGIN))
: true);

// Enable or disable OOB telemetry based on connection parameter. Default is disabled.
// The value may still change later when session parameters from the server are read.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public enum SFSessionProperty {
MAX_HTTP_RETRIES("maxHttpRetries", false, Integer.class),

ENABLE_PUT_GET("enablePutGet", false, Boolean.class),
DISABLE_CONSOLE_LOGIN("disableConsoleLogin", false, Boolean.class),

PUT_GET_MAX_RETRIES("putGetMaxRetries", false, Integer.class),

Expand Down
1 change: 1 addition & 0 deletions src/main/java/net/snowflake/client/core/SessionUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class SessionUtil {
private static final String SF_PATH_LOGIN_REQUEST = "/session/v1/login-request";
private static final String SF_PATH_TOKEN_REQUEST = "/session/token-request";
public static final String SF_PATH_AUTHENTICATOR_REQUEST = "/session/authenticator-request";
public static final String SF_PATH_CONSOLE_LOGIN_REQUEST = "/console/login";

public static final String SF_QUERY_SESSION_DELETE = "delete";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.*;
import net.snowflake.client.jdbc.ErrorCode;
Expand Down Expand Up @@ -215,6 +216,34 @@ private String getSSOUrl(int port) throws SFException, SnowflakeSQLException {
}
}

private String getConsoleLoginUrl(int port) throws SFException {
try {
proofKey = generateProofKey();
String serverUrl = loginInput.getServerUrl();

URIBuilder consoleLoginUriBuilder = new URIBuilder(serverUrl);
consoleLoginUriBuilder.setPath(SessionUtil.SF_PATH_CONSOLE_LOGIN_REQUEST);
consoleLoginUriBuilder.addParameter("login_name", loginInput.getUserName());
consoleLoginUriBuilder.addParameter("browser_mode_redirect_port", Integer.toString(port));
consoleLoginUriBuilder.addParameter("proof_key", proofKey);

String consoleLoginUrl = consoleLoginUriBuilder.build().toURL().toString();

logger.debug("console login url: {}", consoleLoginUrl);

return consoleLoginUrl;
} catch (Exception ex) {
throw new SFException(ex, ErrorCode.INTERNAL_ERROR, ex.getMessage());
}
}

private String generateProofKey() {
SecureRandom secureRandom = new SecureRandom();
byte[] randomness = new byte[32];
secureRandom.nextBytes(randomness);
return Base64.getEncoder().encodeToString(randomness);
}

/**
* Authenticate
*
Expand All @@ -227,13 +256,26 @@ void authenticate() throws SFException, SnowflakeSQLException {
// main procedure
int port = this.getLocalPort(ssocket);
logger.debug("Listening localhost:{}", port);
String ssoUrl = getSSOUrl(port);
this.handlers.output(
"Initiating login request with your identity provider. A "
+ "browser window should have opened for you to complete the "
+ "login. If you can't see it, check existing browser windows, "
+ "or your OS settings. Press CTRL+C to abort and try again...");
this.handlers.openBrowser(ssoUrl);

if (loginInput.getDisableConsoleLogin()) {
// Access GS to get SSO URL
String ssoUrl = getSSOUrl(port);
this.handlers.output(
"Initiating login request with your identity provider. A "
+ "browser window should have opened for you to complete the "
+ "login. If you can't see it, check existing browser windows, "
+ "or your OS settings. Press CTRL+C to abort and try again...");
this.handlers.openBrowser(ssoUrl);
} else {
// Multiple SAML way to do authentication via console login
String consoleLoginUrl = getConsoleLoginUrl(port);
this.handlers.output(
"Initiating login request with your identity provider(s). A "
+ "browser window should have opened for you to complete the "
+ "login. If you can't see it, check existing browser windows, "
+ "or your OS settings. Press CTRL+C to abort and try again...");
this.handlers.openBrowser(consoleLoginUrl);
}

while (true) {
Socket socket = ssocket.accept(); // start accepting the request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ private SFLoginInput initMockLoginInput() {
.thenReturn(ClientAuthnDTO.AuthenticatorType.EXTERNALBROWSER.name());
when(loginInput.getAccountName()).thenReturn("testaccount");
when(loginInput.getUserName()).thenReturn("testuser");
when(loginInput.getDisableConsoleLogin()).thenReturn(true);
return loginInput;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ private SFLoginInput initMockLoginInput() {
.thenReturn(ClientAuthnDTO.AuthenticatorType.EXTERNALBROWSER.name());
when(loginInput.getAccountName()).thenReturn("testaccount");
when(loginInput.getUserName()).thenReturn("testuser");
when(loginInput.getDisableConsoleLogin()).thenReturn(true);
return loginInput;
}

Expand Down

0 comments on commit 742c2f1

Please sign in to comment.