in wrapper/src/main/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPlugin.java [118:219]
private Connection connectInternal(String driverProtocol, HostSpec hostSpec, Properties props,
JdbcCallable<Connection, SQLException> connectFunc) throws SQLException {
if (StringUtils.isNullOrEmpty(PropertyDefinition.USER.getString(props))) {
throw new SQLException(PropertyDefinition.USER.name + " is null or empty.");
}
String host = IamAuthUtils.getIamHost(IAM_HOST.getString(props), hostSpec);
int port = IamAuthUtils.getIamPort(
IAM_DEFAULT_PORT.getInteger(props),
hostSpec,
this.pluginService.getDialect().getDefaultPort());
final Region region = regionUtils.getRegion(host, props, IAM_REGION.name);
if (region == null) {
throw new SQLException(
Messages.get("IamAuthConnectionPlugin.unableToDetermineRegion", new Object[]{ IAM_REGION.name }));
}
final int tokenExpirationSec = IAM_EXPIRATION.getInteger(props);
final String cacheKey = IamAuthUtils.getCacheKey(
PropertyDefinition.USER.getString(props),
host,
port,
region);
final TokenInfo tokenInfo = IamAuthCacheHolder.tokenCache.get(cacheKey);
final boolean isCachedToken = tokenInfo != null && !tokenInfo.isExpired();
if (isCachedToken) {
LOGGER.finest(
() -> Messages.get(
"AuthenticationToken.useCachedToken",
new Object[] {tokenInfo.getToken()}));
PropertyDefinition.PASSWORD.set(props, tokenInfo.getToken());
} else {
final Instant tokenExpiry = Instant.now().plus(tokenExpirationSec, ChronoUnit.SECONDS);
this.fetchTokenCounter.inc();
final String token = IamAuthUtils.generateAuthenticationToken(
iamTokenUtility,
pluginService,
PropertyDefinition.USER.getString(props),
host,
port,
region,
AwsCredentialsManager.getProvider(hostSpec, props));
LOGGER.finest(
() -> Messages.get(
"AuthenticationToken.generatedNewToken",
new Object[] {token}));
PropertyDefinition.PASSWORD.set(props, token);
IamAuthCacheHolder.tokenCache.put(
cacheKey,
new TokenInfo(token, tokenExpiry));
}
try {
return connectFunc.call();
} catch (final SQLException exception) {
LOGGER.finest(
() -> Messages.get(
"IamAuthConnectionPlugin.connectException",
new Object[] {exception}));
if (!this.pluginService.isLoginException(exception, this.pluginService.getTargetDriverDialect())
|| !isCachedToken) {
throw exception;
}
// Login unsuccessful with cached token
// Try to generate a new token and try to connect again
final Instant tokenExpiry = Instant.now().plus(tokenExpirationSec, ChronoUnit.SECONDS);
this.fetchTokenCounter.inc();
final String token = IamAuthUtils.generateAuthenticationToken(
iamTokenUtility,
pluginService,
PropertyDefinition.USER.getString(props),
host,
port,
region,
AwsCredentialsManager.getProvider(hostSpec, props));
LOGGER.finest(
() -> Messages.get(
"AuthenticationToken.generatedNewToken",
new Object[] {token}));
PropertyDefinition.PASSWORD.set(props, token);
IamAuthCacheHolder.tokenCache.put(
cacheKey,
new TokenInfo(token, tokenExpiry));
return connectFunc.call();
} catch (final Exception exception) {
LOGGER.warning(
() -> Messages.get(
"IamAuthConnectionPlugin.unhandledException",
new Object[] {exception}));
throw new SQLException(exception);
}
}