2021-08-20 10:58:07 -07:00
|
|
|
package controllers;
|
2021-08-20 07:42:18 -07:00
|
|
|
|
2021-11-22 16:33:14 -08:00
|
|
|
import client.AuthServiceClient;
|
|
|
|
import com.datahub.authentication.Authentication;
|
|
|
|
import com.linkedin.entity.client.EntityClient;
|
2022-08-23 09:54:34 -07:00
|
|
|
import java.net.URLEncoder;
|
2021-08-20 07:42:18 -07:00
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
import java.util.concurrent.CompletionStage;
|
2021-11-22 16:33:14 -08:00
|
|
|
import javax.annotation.Nonnull;
|
2021-08-20 07:42:18 -07:00
|
|
|
import javax.inject.Inject;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import org.pac4j.core.config.Config;
|
|
|
|
import org.pac4j.core.engine.CallbackLogic;
|
|
|
|
import org.pac4j.core.http.adapter.HttpActionAdapter;
|
|
|
|
import org.pac4j.play.CallbackController;
|
|
|
|
import org.pac4j.play.PlayWebContext;
|
|
|
|
import play.mvc.Result;
|
2021-08-20 10:58:07 -07:00
|
|
|
import auth.sso.oidc.OidcCallbackLogic;
|
|
|
|
import auth.sso.SsoManager;
|
|
|
|
import auth.sso.SsoProvider;
|
2021-08-20 07:42:18 -07:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A dedicated Controller for handling redirects to DataHub by 3rd-party Identity Providers after
|
|
|
|
* off-platform authentication.
|
|
|
|
*
|
|
|
|
* Handles a single "callback/{protocol}" route, where the protocol (ie. OIDC / SAML) determines
|
|
|
|
* the handling logic to invoke.
|
|
|
|
*/
|
|
|
|
@Slf4j
|
|
|
|
public class SsoCallbackController extends CallbackController {
|
|
|
|
|
2021-11-22 16:33:14 -08:00
|
|
|
private final SsoManager _ssoManager;
|
2021-08-20 07:42:18 -07:00
|
|
|
|
|
|
|
@Inject
|
2021-11-22 16:33:14 -08:00
|
|
|
public SsoCallbackController(
|
|
|
|
@Nonnull SsoManager ssoManager,
|
|
|
|
@Nonnull Authentication systemAuthentication,
|
|
|
|
@Nonnull EntityClient entityClient,
|
|
|
|
@Nonnull AuthServiceClient authClient) {
|
2021-08-20 07:42:18 -07:00
|
|
|
_ssoManager = ssoManager;
|
|
|
|
setDefaultUrl("/"); // By default, redirects to Home Page on log in.
|
2022-10-21 10:58:27 -07:00
|
|
|
setSaveInSession(false);
|
2021-11-22 16:33:14 -08:00
|
|
|
setCallbackLogic(new SsoCallbackLogic(ssoManager, systemAuthentication, entityClient, authClient));
|
2021-08-20 07:42:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public CompletionStage<Result> handleCallback(String protocol) {
|
|
|
|
if (shouldHandleCallback(protocol)) {
|
|
|
|
log.debug(String.format("Handling SSO callback. Protocol: %s", protocol));
|
2022-08-23 09:54:34 -07:00
|
|
|
return callback().handle((res, e) -> {
|
|
|
|
if (e != null) {
|
|
|
|
log.error("Caught exception while attempting to handle SSO callback! It's likely that SSO integration is mis-configured.", e);
|
|
|
|
return redirect(
|
|
|
|
String.format("/login?error_msg=%s",
|
|
|
|
URLEncoder.encode("Failed to sign in using Single Sign-On provider. Please contact your DataHub Administrator, "
|
|
|
|
+ "or refer to server logs for more information.")));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
});
|
2021-08-20 07:42:18 -07:00
|
|
|
}
|
|
|
|
return CompletableFuture.completedFuture(internalServerError(
|
|
|
|
String.format("Failed to perform SSO callback. SSO is not enabled for protocol: %s", protocol)));
|
|
|
|
}
|
|
|
|
|
2022-08-23 09:54:34 -07:00
|
|
|
|
2021-08-20 07:42:18 -07:00
|
|
|
/**
|
|
|
|
* Logic responsible for delegating to protocol-specific callback logic.
|
|
|
|
*/
|
|
|
|
public class SsoCallbackLogic implements CallbackLogic<Result, PlayWebContext> {
|
|
|
|
|
|
|
|
private final OidcCallbackLogic _oidcCallbackLogic;
|
|
|
|
|
2022-05-10 18:15:53 -05:00
|
|
|
SsoCallbackLogic(final SsoManager ssoManager, final Authentication systemAuthentication,
|
|
|
|
final EntityClient entityClient, final AuthServiceClient authClient) {
|
2021-11-22 16:33:14 -08:00
|
|
|
_oidcCallbackLogic = new OidcCallbackLogic(ssoManager, systemAuthentication, entityClient, authClient);
|
2021-08-20 07:42:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Result perform(PlayWebContext context, Config config,
|
|
|
|
HttpActionAdapter<Result, PlayWebContext> httpActionAdapter, String defaultUrl, Boolean saveInSession,
|
|
|
|
Boolean multiProfile, Boolean renewSession, String defaultClient) {
|
|
|
|
if (SsoProvider.SsoProtocol.OIDC.equals(_ssoManager.getSsoProvider().protocol())) {
|
|
|
|
return _oidcCallbackLogic.perform(context, config, httpActionAdapter, defaultUrl, saveInSession, multiProfile, renewSession, defaultClient);
|
|
|
|
}
|
|
|
|
// Should never occur.
|
|
|
|
throw new UnsupportedOperationException("Failed to find matching SSO Provider. Only one supported is OIDC.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean shouldHandleCallback(final String protocol) {
|
|
|
|
return _ssoManager.isSsoEnabled() && _ssoManager.getSsoProvider().protocol().getCommonName().equals(protocol);
|
|
|
|
}
|
|
|
|
}
|