Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2d36a01

Browse files
committedFeb 6, 2025·
Remove username as mandatory and IDP_HOST property
1 parent 8fae4ab commit 2d36a01

12 files changed

+58
-43
lines changed
 

‎src/main/java/net/snowflake/client/core/CredentialManager.java

+13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package net.snowflake.client.core;
66

7+
import com.amazonaws.util.StringUtils;
78
import com.google.common.base.Strings;
89
import java.net.URI;
910
import net.snowflake.client.jdbc.ErrorCode;
@@ -131,6 +132,10 @@ static void fillCachedOAuthRefreshToken(SFLoginInput loginInput) throws SFExcept
131132
synchronized void fillCachedCredential(
132133
SFLoginInput loginInput, String host, String username, CachedCredentialType credType)
133134
throws SFException {
135+
if (StringUtils.isNullOrEmpty(username)) {
136+
logger.debug("Missing username; Cannot read from credential cache");
137+
return;
138+
}
134139
if (secureStorageManager == null) {
135140
logMissingJnaJarForSecureLocalStorage();
136141
return;
@@ -240,6 +245,10 @@ static void writeOAuthRefreshToken(SFLoginInput loginInput) throws SFException {
240245
/** Store the temporary credential */
241246
synchronized void writeTemporaryCredential(
242247
String host, String user, String cred, CachedCredentialType credType) {
248+
if (StringUtils.isNullOrEmpty(user)) {
249+
logger.debug("Missing username; Cannot write to credential cache");
250+
return;
251+
}
243252
if (Strings.isNullOrEmpty(cred)) {
244253
logger.debug("No {} is given.", credType);
245254
return; // no credential
@@ -322,6 +331,10 @@ synchronized void deleteTemporaryCredential(
322331
logMissingJnaJarForSecureLocalStorage();
323332
return;
324333
}
334+
if (StringUtils.isNullOrEmpty(user)) {
335+
logger.debug("Missing username; Cannot delete from credential cache");
336+
return;
337+
}
325338

326339
try {
327340
secureStorageManager.deleteCredential(host, user, credType.getValue());

‎src/main/java/net/snowflake/client/core/SessionUtil.java

+30-18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import static net.snowflake.client.core.SFTrustManager.resetOCSPResponseCacherServerURL;
88
import static net.snowflake.client.jdbc.SnowflakeUtil.systemGetProperty;
99

10+
import com.amazonaws.util.StringUtils;
1011
import com.fasterxml.jackson.databind.JsonNode;
1112
import com.fasterxml.jackson.databind.ObjectMapper;
1213
import com.google.common.base.Strings;
@@ -31,7 +32,6 @@
3132
import net.snowflake.client.core.auth.oauth.AccessTokenProvider;
3233
import net.snowflake.client.core.auth.oauth.OAuthAccessTokenForRefreshTokenProvider;
3334
import net.snowflake.client.core.auth.oauth.OAuthAccessTokenProviderFactory;
34-
import net.snowflake.client.core.auth.oauth.OAuthUtil;
3535
import net.snowflake.client.core.auth.oauth.TokenResponseDTO;
3636
import net.snowflake.client.jdbc.ErrorCode;
3737
import net.snowflake.client.jdbc.SnowflakeDriver;
@@ -286,20 +286,16 @@ static SFLoginOutput openSession(
286286
final AuthenticatorType authenticator = getAuthenticator(loginInput);
287287
checkIfExperimentalAuthnEnabled(authenticator);
288288

289-
if (authenticator.equals(AuthenticatorType.OAUTH)
290-
|| authenticator.equals(AuthenticatorType.PROGRAMMATIC_ACCESS_TOKEN)) {
291-
// OAUTH and PAT needs either token or password
289+
if (isTokenOrPasswordRequired(authenticator)) {
292290
AssertUtil.assertTrue(
293291
loginInput.getToken() != null || loginInput.getPassword() != null,
294292
"missing token or password for opening session");
295-
} else {
296-
// OAuth and PAT do not require a username
293+
}
294+
if (isUsernameRequired(authenticator)) {
297295
AssertUtil.assertTrue(
298296
loginInput.getUserName() != null, "missing user name for opening session");
299297
}
300-
if (authenticator.equals(AuthenticatorType.EXTERNALBROWSER)
301-
|| authenticator.equals(AuthenticatorType.OAUTH_AUTHORIZATION_CODE)
302-
|| authenticator.equals(AuthenticatorType.OAUTH_CLIENT_CREDENTIALS)) {
298+
if (isEligibleForTokenCaching(authenticator)) {
303299
if ((Constants.getOS() == Constants.OS.MAC || Constants.getOS() == Constants.OS.WINDOWS)
304300
&& loginInput.isEnableClientStoreTemporaryCredential()) {
305301
// force to set the flag for Mac/Windows users
@@ -328,7 +324,7 @@ static SFLoginOutput openSession(
328324
}
329325
}
330326

331-
readCachedTokens(loginInput);
327+
readCachedTokensIfPossible(loginInput);
332328

333329
if (OAuthAccessTokenProviderFactory.isEligible(getAuthenticator(loginInput))) {
334330
obtainAuthAccessTokenAndUpdateInput(loginInput);
@@ -362,6 +358,24 @@ static void checkIfExperimentalAuthnEnabled(AuthenticatorType authenticator) thr
362358
}
363359
}
364360

361+
private static boolean isEligibleForTokenCaching(AuthenticatorType authenticator) {
362+
return authenticator.equals(AuthenticatorType.EXTERNALBROWSER)
363+
|| authenticator.equals(AuthenticatorType.OAUTH_AUTHORIZATION_CODE)
364+
|| authenticator.equals(AuthenticatorType.OAUTH_CLIENT_CREDENTIALS);
365+
}
366+
367+
private static boolean isTokenOrPasswordRequired(AuthenticatorType authenticator) {
368+
return authenticator.equals(AuthenticatorType.OAUTH)
369+
|| authenticator.equals(AuthenticatorType.PROGRAMMATIC_ACCESS_TOKEN);
370+
}
371+
372+
private static boolean isUsernameRequired(AuthenticatorType authenticator) {
373+
return !authenticator.equals(AuthenticatorType.OAUTH)
374+
&& !authenticator.equals(AuthenticatorType.PROGRAMMATIC_ACCESS_TOKEN)
375+
&& !authenticator.equals(AuthenticatorType.OAUTH_AUTHORIZATION_CODE)
376+
&& !authenticator.equals(AuthenticatorType.OAUTH_CLIENT_CREDENTIALS);
377+
}
378+
365379
private static void obtainAuthAccessTokenAndUpdateInput(SFLoginInput loginInput)
366380
throws SFException {
367381
if (loginInput.getOauthAccessToken() != null) { // Access Token was cached
@@ -410,11 +424,13 @@ private static void refreshOAuthAccessTokenAndUpdateInput(SFLoginInput loginInpu
410424
}
411425
}
412426

413-
private static void readCachedTokens(SFLoginInput loginInput) throws SFException {
427+
private static void readCachedTokensIfPossible(SFLoginInput loginInput) throws SFException {
414428
if (asBoolean(loginInput.getSessionParameters().get(CLIENT_STORE_TEMPORARY_CREDENTIAL))) {
415-
CredentialManager.fillCachedIdToken(loginInput);
416-
CredentialManager.fillCachedOAuthAccessToken(loginInput);
417-
CredentialManager.fillCachedOAuthRefreshToken(loginInput);
429+
if (!StringUtils.isNullOrEmpty(loginInput.getUserName())) {
430+
CredentialManager.fillCachedIdToken(loginInput);
431+
CredentialManager.fillCachedOAuthAccessToken(loginInput);
432+
CredentialManager.fillCachedOAuthRefreshToken(loginInput);
433+
}
418434
}
419435

420436
if (asBoolean(loginInput.getSessionParameters().get(CLIENT_REQUEST_MFA_TOKEN))) {
@@ -607,10 +623,6 @@ static SFLoginOutput newSession(
607623
if (authenticatorType == AuthenticatorType.OAUTH
608624
&& loginInput.getOriginalAuthenticator() != null) {
609625
data.put(ClientAuthnParameter.OAUTH_TYPE.name(), loginInput.getOriginalAuthenticator());
610-
URI idpUri =
611-
OAuthUtil.getTokenRequestUrl(
612-
loginInput.getOauthLoginInput(), loginInput.getServerUrl());
613-
data.put(ClientAuthnParameter.IDP_HOST.name(), idpUri.getHost());
614626
}
615627

616628
// map of client environment parameters, including connection parameters

‎src/main/java/net/snowflake/client/core/auth/ClientAuthnParameter.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,5 @@ public enum ClientAuthnParameter {
2121
SESSION_PARAMETERS,
2222
PROOF_KEY,
2323
TOKEN,
24-
OAUTH_TYPE,
25-
IDP_HOST
24+
OAUTH_TYPE
2625
}

‎src/main/java/net/snowflake/client/core/auth/oauth/OAuthAccessTokenProviderFactory.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ private void assertContainsClientCredentials(
115115
AssertUtil.assertTrue(
116116
loginInput.getOauthLoginInput().getClientId() != null,
117117
String.format(
118-
"passing clientId is required for %s authentication", authenticatorType.name()));
118+
"passing oauthClientId is required for %s authentication", authenticatorType.name()));
119119
AssertUtil.assertTrue(
120120
loginInput.getOauthLoginInput().getClientSecret() != null,
121121
String.format(
122-
"passing clientSecret is required for %s authentication", authenticatorType.name()));
122+
"passing oauthClientSecret is required for %s authentication", authenticatorType.name()));
123123
}
124124
}

‎src/main/java/net/snowflake/client/core/auth/oauth/OAuthUtil.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,18 @@
1010
import java.net.URI;
1111
import java.nio.charset.StandardCharsets;
1212
import net.snowflake.client.core.SFOauthLoginInput;
13-
import net.snowflake.client.core.SnowflakeJdbcInternalApi;
1413
import org.apache.http.client.methods.HttpPost;
1514
import org.apache.http.client.methods.HttpRequestBase;
1615
import org.apache.http.entity.StringEntity;
1716

18-
@SnowflakeJdbcInternalApi
19-
public class OAuthUtil {
17+
class OAuthUtil {
2018

2119
private static final String SNOWFLAKE_AUTHORIZE_ENDPOINT = "/oauth/authorize";
2220
private static final String SNOWFLAKE_TOKEN_REQUEST_ENDPOINT = "/oauth/token-request";
2321

2422
private static final String DEFAULT_SESSION_ROLE_SCOPE_PREFIX = "session:role:";
2523

26-
@SnowflakeJdbcInternalApi
27-
public static URI getTokenRequestUrl(SFOauthLoginInput oauthLoginInput, String serverUrl) {
24+
static URI getTokenRequestUrl(SFOauthLoginInput oauthLoginInput, String serverUrl) {
2825
URI uri =
2926
!StringUtils.isNullOrEmpty(oauthLoginInput.getTokenRequestUrl())
3027
? URI.create(oauthLoginInput.getTokenRequestUrl())

‎src/test/java/net/snowflake/client/core/auth/oauth/OAuthAccessTokenProviderFactoryTest.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public void shouldFailToCreateClientCredentialsAccessTokenProviderWithoutClientI
8484
AuthenticatorType.OAUTH_CLIENT_CREDENTIALS, loginInput));
8585
Assertions.assertTrue(
8686
e.getMessage()
87-
.contains("passing clientId is required for OAUTH_CLIENT_CREDENTIALS authentication."));
87+
.contains("passing oauthClientId is required for OAUTH_CLIENT_CREDENTIALS authentication."));
8888
}
8989

9090
@Test
@@ -99,7 +99,7 @@ public void shouldFailToCreateClientCredentialsAccessTokenProviderWithoutClientS
9999
Assertions.assertTrue(
100100
e.getMessage()
101101
.contains(
102-
"passing clientSecret is required for OAUTH_CLIENT_CREDENTIALS authentication."));
102+
"passing oauthClientSecret is required for OAUTH_CLIENT_CREDENTIALS authentication."));
103103
}
104104

105105
@Test
@@ -138,7 +138,7 @@ public void shouldFailToCreateAuthzCodeAccessTokenProviderWithoutClientId() {
138138
AuthenticatorType.OAUTH_AUTHORIZATION_CODE, loginInput));
139139
Assertions.assertTrue(
140140
e.getMessage()
141-
.contains("passing clientId is required for OAUTH_AUTHORIZATION_CODE authentication."));
141+
.contains("passing oauthClientId is required for OAUTH_AUTHORIZATION_CODE authentication."));
142142
}
143143

144144
@Test
@@ -153,7 +153,7 @@ public void shouldFailToCreateAuthzCodeAccessTokenProviderWithoutClientSecret()
153153
Assertions.assertTrue(
154154
e.getMessage()
155155
.contains(
156-
"passing clientSecret is required for OAUTH_AUTHORIZATION_CODE authentication."));
156+
"passing oauthClientSecret is required for OAUTH_AUTHORIZATION_CODE authentication."));
157157
}
158158

159159
@Test

‎src/test/resources/wiremock/mappings/oauth/token_caching/caching_refreshed_access_token_and_new_refresh_token.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
"TOKEN": "expired-access-token-123",
3636
"LOGIN_NAME": "MOCK_USERNAME",
3737
"AUTHENTICATOR": "OAUTH",
38-
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS",
39-
"IDP_HOST": "localhost"
38+
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS"
4039
}
4140
},
4241
"ignoreExtraElements": true

‎src/test/resources/wiremock/mappings/oauth/token_caching/caching_tokens_after_connecting.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@
6969
"TOKEN": "access-token-123",
7070
"LOGIN_NAME": "MOCK_USERNAME",
7171
"AUTHENTICATOR": "OAUTH",
72-
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS",
73-
"IDP_HOST": "localhost"
72+
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS"
7473
}
7574
},
7675
"ignoreExtraElements" : true

‎src/test/resources/wiremock/mappings/oauth/token_caching/refreshing_expired_access_token.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
"TOKEN": "expired-access-token-123",
3636
"LOGIN_NAME": "MOCK_USERNAME",
3737
"AUTHENTICATOR": "OAUTH",
38-
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS",
39-
"IDP_HOST": "localhost"
38+
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS"
4039
}
4140
},
4241
"ignoreExtraElements": true

‎src/test/resources/wiremock/mappings/oauth/token_caching/restarting_full_flow_on_expiration_and_no_refresh_token.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,7 @@
124124
"TOKEN": "newly-obtained-access-token-123",
125125
"LOGIN_NAME": "MOCK_USERNAME",
126126
"AUTHENTICATOR": "OAUTH",
127-
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS",
128-
"IDP_HOST": "localhost"
127+
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS"
129128
}
130129
},
131130
"ignoreExtraElements": true

‎src/test/resources/wiremock/mappings/oauth/token_caching/restarting_full_flow_on_refresh_token_error.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
"TOKEN": "expired-access-token-123",
3636
"LOGIN_NAME": "MOCK_USERNAME",
3737
"AUTHENTICATOR": "OAUTH",
38-
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS",
39-
"IDP_HOST": "localhost"
38+
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS"
4039
}
4140
},
4241
"ignoreExtraElements": true

‎src/test/resources/wiremock/mappings/oauth/token_caching/reusing_cached_access_token_to_authenticate.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
"TOKEN": "reused-access-token-123",
3636
"LOGIN_NAME": "MOCK_USERNAME",
3737
"AUTHENTICATOR": "OAUTH",
38-
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS",
39-
"IDP_HOST": "localhost"
38+
"OAUTH_TYPE": "OAUTH_CLIENT_CREDENTIALS"
4039
}
4140
},
4241
"ignoreExtraElements" : true

0 commit comments

Comments
 (0)
Please sign in to comment.