mirror of
https://github.com/datahub-project/datahub.git
synced 2025-10-13 09:54:10 +00:00
93 lines
3.4 KiB
Java
93 lines
3.4 KiB
Java
package auth.sso.oidc.custom;
|
|
|
|
import auth.sso.oidc.OidcConfigs;
|
|
import com.nimbusds.oauth2.sdk.ParseException;
|
|
import com.nimbusds.oauth2.sdk.token.AccessToken;
|
|
import java.io.IOException;
|
|
import java.net.URI;
|
|
import org.pac4j.core.profile.UserProfile;
|
|
import org.pac4j.oidc.client.OidcClient;
|
|
import org.pac4j.oidc.config.OidcConfiguration;
|
|
import org.pac4j.oidc.exceptions.UserInfoErrorResponseException;
|
|
import org.pac4j.oidc.profile.creator.OidcProfileCreator;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
/**
|
|
* Custom OIDC Profile Creator that adds retry logic to the userinfo endpoint call. This addresses
|
|
* the "Invalid Http response" errors that can occur when the userinfo endpoint is temporarily
|
|
* unavailable or slow to respond.
|
|
*/
|
|
public class CustomOidcProfileCreator extends OidcProfileCreator {
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(CustomOidcProfileCreator.class);
|
|
private final OidcConfigs oidcConfigs;
|
|
|
|
public CustomOidcProfileCreator(
|
|
OidcConfiguration configuration, OidcClient client, OidcConfigs oidcConfigs) {
|
|
super(configuration, client);
|
|
this.oidcConfigs = oidcConfigs;
|
|
}
|
|
|
|
@Override
|
|
public void callUserInfoEndpoint(
|
|
URI userInfoEndpointUri, AccessToken accessToken, UserProfile profile)
|
|
throws IOException, ParseException, java.text.ParseException, UserInfoErrorResponseException {
|
|
// Wrap the parent's callUserInfoEndpoint method with retry logic
|
|
callUserInfoEndpointWithRetry(userInfoEndpointUri, accessToken, profile);
|
|
}
|
|
|
|
/**
|
|
* Calls the userinfo endpoint with retry logic and exponential backoff. This wraps the parent's
|
|
* callUserInfoEndpoint method with retry logic.
|
|
*/
|
|
private void callUserInfoEndpointWithRetry(
|
|
URI userInfoEndpointUri, AccessToken accessToken, UserProfile profile)
|
|
throws IOException, ParseException, java.text.ParseException, UserInfoErrorResponseException {
|
|
int maxAttempts;
|
|
try {
|
|
maxAttempts = Integer.parseInt(oidcConfigs.getHttpRetryAttempts());
|
|
} catch (NumberFormatException e) {
|
|
logger.warn(
|
|
"Invalid retry attempts configuration: {}, defaulting to 1",
|
|
oidcConfigs.getHttpRetryAttempts());
|
|
maxAttempts = 1;
|
|
}
|
|
|
|
long initialDelay;
|
|
try {
|
|
initialDelay = Long.parseLong(oidcConfigs.getHttpRetryDelay());
|
|
} catch (NumberFormatException e) {
|
|
logger.warn(
|
|
"Invalid retry delay configuration: {}, defaulting to 1000ms",
|
|
oidcConfigs.getHttpRetryDelay());
|
|
initialDelay = 1000;
|
|
}
|
|
|
|
// Ensure at least one attempt
|
|
if (maxAttempts <= 0) {
|
|
maxAttempts = 1;
|
|
}
|
|
|
|
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
try {
|
|
// Call the parent's method directly
|
|
super.callUserInfoEndpoint(userInfoEndpointUri, accessToken, profile);
|
|
return; // Success, exit the retry loop
|
|
} catch (IOException | ParseException | UserInfoErrorResponseException e) {
|
|
if (attempt == maxAttempts) {
|
|
throw e; // Rethrow on final attempt
|
|
}
|
|
try {
|
|
// Exponential backoff
|
|
Thread.sleep(initialDelay * (long) Math.pow(2, attempt - 1));
|
|
} catch (InterruptedException ie) {
|
|
Thread.currentThread().interrupt();
|
|
throw new RuntimeException("UserInfo request retry interrupted", ie);
|
|
}
|
|
logger.warn("UserInfo request retry attempt {} of {} failed", attempt, maxAttempts, e);
|
|
}
|
|
}
|
|
}
|
|
}
|