Skip to content

Commit

Permalink
fix: keep the SAML protocol info into the session on callbak failure
Browse files Browse the repository at this point in the history
fixes AM-1072

gravitee-io/issues#9393

(cherry picked from commit 322d950)

# Conflicts:
#	gravitee-am-common/src/main/java/io/gravitee/am/common/utils/ConstantKeys.java
#	gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/login/LoginCallbackFailureHandler.java
  • Loading branch information
leleueri authored and mergify[bot] committed Dec 6, 2023
1 parent 34f8b90 commit 3c320b8
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ public interface ConstantKeys {
Claims.auth_time,
Claims.updated_at
);
<<<<<<< HEAD
String REGISTRATION_VERIFY_SUCCESS = "registration_verify_success";

String POLICY_CHAIN_ERROR_KEY_MFA_CHALLENGE_ERROR = "GATEWAY_POLICY_MFA_CHALLENGE_ERROR";
Expand All @@ -253,4 +254,10 @@ public interface ConstantKeys {

String CONTINUE_CALLBACK_PROCESSING = "continueCallbackProcess";

=======

String PROTOCOL_KEY = "protocol";
String PROTOCOL_VALUE_SAML_REDIRECT = "SAML/HTTP-Redirect";
String PROTOCOL_VALUE_SAML_POST = "SAML/HTTP-POST";
>>>>>>> 322d9507ad (fix: keep the SAML protocol info into the session on callbak failure)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@
import io.gravitee.am.identityprovider.api.social.CloseSessionMode;
import io.gravitee.am.identityprovider.api.social.SocialAuthenticationProvider;
import io.gravitee.am.model.Domain;
<<<<<<< HEAD
import io.gravitee.am.model.User;
=======
>>>>>>> 322d9507ad (fix: keep the SAML protocol info into the session on callbak failure)
import io.gravitee.am.model.login.LoginSettings;
import io.gravitee.am.model.oidc.Client;
import io.gravitee.am.service.AuthenticationFlowContextService;
import io.gravitee.am.service.exception.AbstractManagementException;
import io.gravitee.common.http.HttpStatusCode;
<<<<<<< HEAD
import io.reactivex.rxjava3.core.Maybe;
=======
>>>>>>> 322d9507ad (fix: keep the SAML protocol info into the session on callbak failure)
import io.vertx.rxjava3.core.MultiMap;
import io.vertx.rxjava3.ext.web.RoutingContext;
import org.slf4j.Logger;
Expand All @@ -60,11 +66,16 @@
import static io.gravitee.am.common.utils.ConstantKeys.ISSUING_REASON_CLOSE_IDP_SESSION;
import static io.gravitee.am.common.utils.ConstantKeys.OIDC_PROVIDER_ID_TOKEN_KEY;
import static io.gravitee.am.common.utils.ConstantKeys.PARAM_CONTEXT_KEY;
<<<<<<< HEAD
import static io.gravitee.am.common.utils.ConstantKeys.STATUS_FAILURE;
import static io.gravitee.am.common.web.UriBuilder.encodeURIComponent;
import static io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest.CONTEXT_PATH;
import static io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest.LOGGER;
import static io.gravitee.am.gateway.handler.root.RootProvider.PATH_LOGIN_CALLBACK;
=======
import static io.gravitee.am.common.utils.ConstantKeys.PROTOCOL_KEY;
import static io.gravitee.am.common.utils.ConstantKeys.RETURN_URL_KEY;
>>>>>>> 322d9507ad (fix: keep the SAML protocol info into the session on callbak failure)
import static io.gravitee.am.service.utils.ResponseTypeUtils.isHybridFlow;
import static io.gravitee.am.service.utils.ResponseTypeUtils.isImplicitFlow;

Expand Down Expand Up @@ -126,6 +137,7 @@ private void redirect(RoutingContext context, Throwable throwable) {
Authentication authentication;
// logout user if exists
if (context.user() != null) {
<<<<<<< HEAD
// prepare the authentication object to be able to
// log out from IDP after the AM session clean up
final User endUser = ((io.gravitee.am.gateway.handler.common.vertx.web.auth.user.User) context.user().getDelegate()).getUser();
Expand All @@ -140,6 +152,24 @@ private void redirect(RoutingContext context, Throwable throwable) {
context.session().destroy();
} else {
authentication = new EndUserAuthentication(null, null, new SimpleAuthenticationContext(new VertxHttpServerRequest(context.request().getDelegate())));
=======
final String protocol = context.session().get(ConstantKeys.PROTOCOL_KEY);
if (ConstantKeys.PROTOCOL_VALUE_SAML_REDIRECT.equals(protocol)) {
final var returnUrl = context.session().get(ConstantKeys.RETURN_URL_KEY);
clearSession(context, true);
context.session().put(RETURN_URL_KEY, returnUrl);
context.session().put(PROTOCOL_KEY, protocol);
} else if (ConstantKeys.PROTOCOL_VALUE_SAML_POST.equals(protocol)) {
final var returnUrl = context.session().get(RETURN_URL_KEY);
final var transactionId = context.session().get(ConstantKeys.TRANSACTION_ID_KEY);
clearSession(context, false);
context.session().put(ConstantKeys.TRANSACTION_ID_KEY, transactionId);
context.session().put(RETURN_URL_KEY, returnUrl);
context.session().put(PROTOCOL_KEY, protocol);
} else {
clearSession(context, true);
}
>>>>>>> 322d9507ad (fix: keep the SAML protocol info into the session on callbak failure)
}

// redirect the user to either the login page or the SP redirect uri if hide login option is enabled
Expand Down Expand Up @@ -182,13 +212,27 @@ private void redirect(RoutingContext context, Throwable throwable) {
}
}

private void clearSession(RoutingContext context, boolean clearAuthFlow) {
if (clearAuthFlow) {
// clear AuthenticationFlowContext. data of this context have a TTL so we can fire and forget in case on error.
authenticationFlowContextService.clearContext(context.session().get(ConstantKeys.TRANSACTION_ID_KEY))
.doOnError((error) -> logger.info("Deletion of some authentication flow data fails '{}'", error.getMessage()))
.subscribe();
}
context.clearUser();
context.session().destroy();
}

private void redirectToSP(MultiMap originalParams,
Client client,
RoutingContext context,
Authentication authentication,
Throwable throwable) throws URISyntaxException {
// Get the SP redirect_uri
final String spRedirectUri = (originalParams != null && originalParams.get(Parameters.REDIRECT_URI) != null) ?

final String protocol = context.session() != null ? context.session().get(ConstantKeys.PROTOCOL_KEY) : null;
final String samlEndpoint = ConstantKeys.PROTOCOL_VALUE_SAML_REDIRECT.equals(protocol) || ConstantKeys.PROTOCOL_VALUE_SAML_POST.equals(protocol) ? context.session().get(RETURN_URL_KEY) : null;
final String spRedirectUri = samlEndpoint != null ? samlEndpoint : (originalParams != null && originalParams.get(Parameters.REDIRECT_URI) != null) ?
originalParams.get(Parameters.REDIRECT_URI) :
client.getRedirectUris().get(0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import java.util.*;

import static io.gravitee.am.common.utils.ConstantKeys.PARAM_CONTEXT_KEY;
import static io.gravitee.am.common.utils.ConstantKeys.PROTOCOL_KEY;
import static io.gravitee.am.common.utils.ConstantKeys.RETURN_URL_KEY;
import static io.gravitee.am.service.utils.ResponseTypeUtils.isHybridFlow;
import static io.gravitee.am.service.utils.ResponseTypeUtils.isImplicitFlow;
import static java.util.Objects.nonNull;
Expand Down Expand Up @@ -191,13 +193,33 @@ private void doRedirect(HttpServerResponse response, String url) {

private void logoutUser(RoutingContext context){
if (context.user() != null) {
final String protocol = context.session().get(ConstantKeys.PROTOCOL_KEY);
if (ConstantKeys.PROTOCOL_VALUE_SAML_REDIRECT.equals(protocol)) {
final var returnUrl = context.session().get(ConstantKeys.RETURN_URL_KEY);
clearSession(context, true);
context.session().put(RETURN_URL_KEY, returnUrl);
context.session().put(PROTOCOL_KEY, protocol);
} else if (ConstantKeys.PROTOCOL_VALUE_SAML_POST.equals(protocol)) {
final var returnUrl = context.session().get(RETURN_URL_KEY);
final var transactionId = context.session().get(ConstantKeys.TRANSACTION_ID_KEY);
clearSession(context, false);
context.session().put(ConstantKeys.TRANSACTION_ID_KEY, transactionId);
context.session().put(RETURN_URL_KEY, returnUrl);
context.session().put(PROTOCOL_KEY, protocol);
} else {
clearSession(context, true);
}
}
}

private void clearSession(RoutingContext context, boolean clearAuthFlow) {
if (clearAuthFlow) {
// clear AuthenticationFlowContext. data of this context have a TTL so we can fire and forget in case on error.
authenticationFlowContextService.clearContext(context.session().get(ConstantKeys.TRANSACTION_ID_KEY))
.doOnError((error) -> LOGGER.info("Deletion of some authentication flow data fails '{}'", error.getMessage()))
.subscribe();

context.clearUser();
context.session().destroy();
}
context.clearUser();
context.session().destroy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ private Maybe<Client> validateSignatureWithHMAC(JWT jwt) {
SignedJWT signedJWT = (SignedJWT) jwt;



return this.clientSyncService.findByClientId(clientId)
.switchIfEmpty(Maybe.error(new InvalidClientException("Missing or invalid client")))
.flatMap(client -> {
Expand Down

0 comments on commit 3c320b8

Please sign in to comment.