diff --git a/gravitee-am-common/src/main/java/io/gravitee/am/common/utils/ConstantKeys.java b/gravitee-am-common/src/main/java/io/gravitee/am/common/utils/ConstantKeys.java index 1ece7a8d5df..7c17bc1b33b 100644 --- a/gravitee-am-common/src/main/java/io/gravitee/am/common/utils/ConstantKeys.java +++ b/gravitee-am-common/src/main/java/io/gravitee/am/common/utils/ConstantKeys.java @@ -276,4 +276,10 @@ public interface ConstantKeys { String PROTOCOL_VALUE_SAML_REDIRECT = "SAML/HTTP-Redirect"; String PROTOCOL_VALUE_SAML_POST = "SAML/HTTP-POST"; String IDP_CODE_VERIFIER = "idp_code_verifier"; + + // This const is used by the authorization endpoint to flag an ongoing authentication + String SESSION_KEY_AUTH_FLOW_STATE = "auth_state"; + // note: Create an enum if another value becomes useful + String SESSION_KEY_AUTH_FLOW_STATE_ONGOING = "ongoing"; + } diff --git a/gravitee-am-gateway/gravitee-am-gateway-core/src/main/java/io/gravitee/am/gateway/core/LegacySettingsKeys.java b/gravitee-am-gateway/gravitee-am-gateway-core/src/main/java/io/gravitee/am/gateway/core/LegacySettingsKeys.java new file mode 100644 index 00000000000..67a40f962ad --- /dev/null +++ b/gravitee-am-gateway/gravitee-am-gateway-core/src/main/java/io/gravitee/am/gateway/core/LegacySettingsKeys.java @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.gravitee.am.gateway.core; + + +import org.springframework.core.env.Environment; + +import static java.util.Objects.isNull; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +public enum LegacySettingsKeys { + + HANDLER_SKIP_BYPASS_DIRECT_REQUEST_HDL("legacy.handler.skipBypassDirectRequestHandler", Boolean.FALSE), + OIDC_FILTER_CUSTOM_PROMPT("legacy.openid.filterCustomPrompt", Boolean.FALSE), + OIDC_SCOPE_FULL_PROFILE("legacy.openid.openid_scope_full_profile", Boolean.FALSE), + OIDC_ALWAYS_ENHANCE_SCOPE("legacy.openid.always_enhance_scopes", Boolean.FALSE), + HANDLER_ALWAYS_APPLY_BODY_HDL("legacy.handler.alwaysApplyBodyHandler", Boolean.FALSE), + REGISTRATION_KEEP_PARAMS("legacy.registration.keepParams", Boolean.TRUE), + RESET_PWD_KEEP_PARAMS("legacy.resetPassword.keepParam", Boolean.TRUE), + OIDC_SANITIZE_PARAM_ENCODING("legacy.openid.sanitizeParametersEncoding", Boolean.TRUE); + + private String key; + private Boolean defaultValue; + + LegacySettingsKeys(String key, Boolean defaultValue) { + this.key = key; + this.defaultValue = defaultValue; + } + + public String getKey() { + return key; + } + + public Boolean getDefaultValue() { + return defaultValue; + } + + public boolean from(Environment environment) { + return isNull(environment) ? defaultValue : environment.getProperty(key, Boolean.class, defaultValue); + } +} diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProvider.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProvider.java index b22acbf168d..621d0ca0403 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProvider.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProvider.java @@ -19,6 +19,8 @@ import lombok.NoArgsConstructor; import org.springframework.core.env.Environment; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.OIDC_SANITIZE_PARAM_ENCODING; + @NoArgsConstructor(access = AccessLevel.PRIVATE) public class StaticEnvironmentProvider { @@ -33,7 +35,7 @@ public static void setEnvironment(Environment environment) { public static boolean sanitizeParametersEncoding() { if (sanitizeParametersEncoding == null) { - sanitizeParametersEncoding = getEnvironmentProperty("legacy.openid.sanitizeParametersEncoding", boolean.class, true); + sanitizeParametersEncoding = OIDC_SANITIZE_PARAM_ENCODING.from(env); } return sanitizeParametersEncoding; } diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/vertx/utils/RedirectHelper.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/vertx/utils/RedirectHelper.java new file mode 100644 index 00000000000..05f5c74fbb8 --- /dev/null +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/vertx/utils/RedirectHelper.java @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.gravitee.am.gateway.handler.common.vertx.utils; + + +import io.gravitee.am.common.utils.ConstantKeys; +import io.gravitee.am.service.utils.vertx.RequestUtils; +import io.gravitee.common.http.HttpHeaders; +import io.vertx.rxjava3.core.MultiMap; +import io.vertx.rxjava3.core.http.HttpServerResponse; +import io.vertx.rxjava3.ext.web.RoutingContext; + +import static io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest.CONTEXT_PATH; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +public class RedirectHelper { + + /** + * Compute the URL on which a user has to be redirected by looking into the + * user session, then the request and finally if no returnUrl is found, forge + * an URL to authorization endpoint. + * + * @param context + * @param queryParams + * @return + */ + public static String getReturnUrl(RoutingContext context, MultiMap queryParams) { + // look into the session + if (context.session().get(ConstantKeys.RETURN_URL_KEY) != null) { + return context.session().get(ConstantKeys.RETURN_URL_KEY); + } + // look into the request parameters + if (context.request().getParam(ConstantKeys.RETURN_URL_KEY) != null) { + return context.request().getParam(ConstantKeys.RETURN_URL_KEY); + } + // fallback to the OAuth 2.0 authorize endpoint + return UriBuilderRequest.resolveProxyRequest(context.request(), context.get(CONTEXT_PATH) + "/oauth/authorize", queryParams, true); + } + + public static void doRedirect(HttpServerResponse response, String url) { + response.putHeader(HttpHeaders.LOCATION, url) + .setStatusCode(302) + .end(); + } + + /** + * Retrieve the redirectUrl from the routing context using the {@link #getReturnUrl(RoutingContext, MultiMap)} method + * and apply the redirect (302 status) on the HttpResponse. + * + * @param context + */ + public static void doRedirect(RoutingContext context) { + final MultiMap queryParams = RequestUtils.getCleanedQueryParams(context.request()); + final String redirectUri = getReturnUrl(context, queryParams); + doRedirect(context.response(), redirectUri); + } +} diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/vertx/web/handler/impl/internal/AuthenticationFlowChainHandler.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/vertx/web/handler/impl/internal/AuthenticationFlowChainHandler.java index d77249e9ff1..986689ea5ff 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/vertx/web/handler/impl/internal/AuthenticationFlowChainHandler.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/main/java/io/gravitee/am/gateway/handler/common/vertx/web/handler/impl/internal/AuthenticationFlowChainHandler.java @@ -15,11 +15,14 @@ */ package io.gravitee.am.gateway.handler.common.vertx.web.handler.impl.internal; +import io.gravitee.am.common.utils.ConstantKeys; import io.vertx.core.Handler; import io.vertx.rxjava3.ext.web.RoutingContext; import java.util.List; +import static org.springframework.util.StringUtils.hasText; + /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team @@ -34,6 +37,10 @@ public AuthenticationFlowChainHandler(List steps) { @Override public void handle(RoutingContext routingContext) { + if (routingContext.session() != null && !hasText(routingContext.session().get(ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE))) { + routingContext.session().put(ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE, ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE_ONGOING); + } + new AuthenticationFlowChain(steps) .exitHandler(stepHandler -> stepHandler.handle(routingContext)) .handle(routingContext); diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/test/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProviderTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/test/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProviderTest.java index b77100e36ae..7f840222da7 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/test/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProviderTest.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-common/src/test/java/io/gravitee/am/gateway/handler/common/utils/StaticEnvironmentProviderTest.java @@ -20,6 +20,7 @@ import org.junit.Test; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.OIDC_SANITIZE_PARAM_ENCODING; import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.*; @@ -29,7 +30,7 @@ public class StaticEnvironmentProviderTest { @BeforeClass public static void setup() { - when(env.getProperty("legacy.openid.sanitizeParametersEncoding", boolean.class, true)) + when(env.getProperty(OIDC_SANITIZE_PARAM_ENCODING.getKey(), Boolean.class, OIDC_SANITIZE_PARAM_ENCODING.getDefaultValue())) .thenReturn(false) .thenReturn(true); StaticEnvironmentProvider.setEnvironment(env); @@ -41,6 +42,6 @@ public void sanitizeParametersEncoding_environment_returns_cached_value() { // Call method twice to test cached value is used assertFalse(StaticEnvironmentProvider.sanitizeParametersEncoding()); - verify(env).getProperty("legacy.openid.sanitizeParametersEncoding", boolean.class, true); + verify(env).getProperty(OIDC_SANITIZE_PARAM_ENCODING.getKey(), Boolean.class, OIDC_SANITIZE_PARAM_ENCODING.getDefaultValue()); } -} \ No newline at end of file +} diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/manager/session/SessionManager.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/manager/session/SessionManager.java new file mode 100644 index 00000000000..248a7743a9d --- /dev/null +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/manager/session/SessionManager.java @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.gravitee.am.gateway.handler.manager.session; + + +import io.gravitee.am.common.utils.ConstantKeys; +import io.vertx.rxjava3.ext.web.RoutingContext; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +public class SessionManager { + + + + public void cleanSessionAfterAuth(RoutingContext context) { + cleanSessionOnMfaChallenge(context); + if (context.session() != null) { + context.session().remove(ConstantKeys.TRANSACTION_ID_KEY); + context.session().remove(ConstantKeys.USER_CONSENT_COMPLETED_KEY); + context.session().remove(ConstantKeys.WEBAUTHN_CREDENTIAL_ID_CONTEXT_KEY); + context.session().remove(ConstantKeys.WEBAUTHN_CREDENTIAL_INTERNAL_ID_CONTEXT_KEY); + context.session().remove(ConstantKeys.PASSWORDLESS_AUTH_ACTION_KEY); + context.session().remove(ConstantKeys.MFA_FACTOR_ID_CONTEXT_KEY); + context.session().remove(ConstantKeys.MFA_ENROLLMENT_COMPLETED_KEY); + context.session().remove(ConstantKeys.MFA_CHALLENGE_COMPLETED_KEY); + context.session().remove(ConstantKeys.USER_LOGIN_COMPLETED_KEY); + context.session().remove(ConstantKeys.MFA_ENROLL_CONDITIONAL_SKIPPED_KEY); + + context.session().remove(ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE); + } + } + + public void cleanSessionOnMfaChallenge(RoutingContext context) { + if (context.session() != null) { + context.session().remove(ConstantKeys.PASSWORDLESS_CHALLENGE_KEY); + context.session().remove(ConstantKeys.PASSWORDLESS_CHALLENGE_USERNAME_KEY); + + context.session().remove(ConstantKeys.ENROLLED_FACTOR_ID_KEY); + context.session().remove(ConstantKeys.ENROLLED_FACTOR_SECURITY_VALUE_KEY); + context.session().remove(ConstantKeys.ENROLLED_FACTOR_PHONE_NUMBER); + context.session().remove(ConstantKeys.ENROLLED_FACTOR_EXTENSION_PHONE_NUMBER); + context.session().remove(ConstantKeys.ENROLLED_FACTOR_EMAIL_ADDRESS); + } + } +} diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/RootProvider.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/RootProvider.java index 27b3bbe40de..665492995bc 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/RootProvider.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/RootProvider.java @@ -72,6 +72,7 @@ import io.gravitee.am.gateway.handler.root.resources.endpoint.webauthn.WebAuthnRegisterPostEndpoint; import io.gravitee.am.gateway.handler.root.resources.endpoint.webauthn.WebAuthnRegisterSuccessEndpoint; import io.gravitee.am.gateway.handler.root.resources.endpoint.webauthn.WebAuthnResponseEndpoint; +import io.gravitee.am.gateway.handler.root.resources.handler.BypassDirectRequestHandler; import io.gravitee.am.gateway.handler.root.resources.handler.login.LoginAuthenticationHandler; import io.gravitee.am.gateway.handler.root.resources.handler.transactionid.TransactionIdHandler; import io.gravitee.am.gateway.handler.root.resources.handler.ConditionalBodyHandler; @@ -152,6 +153,7 @@ import org.springframework.core.env.Environment; import static io.gravitee.am.common.utils.ConstantKeys.DEFAULT_REMEMBER_ME_COOKIE_NAME; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.HANDLER_SKIP_BYPASS_DIRECT_REQUEST_HDL; import static io.vertx.core.http.HttpMethod.GET; /** @@ -367,6 +369,7 @@ protected void doStart() throws Exception { Handler loginPostWebAuthnHandler = new LoginPostWebAuthnHandler(webAuthnCookieService); Handler userRememberMeHandler = new UserRememberMeRequestHandler(jwtService, domain, rememberMeCookieName); Handler redirectUriValidationHandler = new RedirectUriValidationHandler(domain, userService); + Handler bypassHandler = new BypassDirectRequestHandler(HANDLER_SKIP_BYPASS_DIRECT_REQUEST_HDL.from(environment)); // Root policy chain handler rootRouter.route() @@ -382,6 +385,7 @@ protected void doStart() throws Exception { // Identifier First Login route rootRouter.get(PATH_IDENTIFIER_FIRST_LOGIN) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(new LoginAuthenticationHandler(identityProviderManager, jwtService, certificateManager)) .handler(policyChainHandler.create(ExtensionPoint.PRE_LOGIN_IDENTIFIER)) @@ -390,6 +394,7 @@ protected void doStart() throws Exception { rootRouter.post(PATH_IDENTIFIER_FIRST_LOGIN) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(botDetectionHandler) .handler(new LoginAuthenticationHandler(identityProviderManager, jwtService, certificateManager)) @@ -401,6 +406,7 @@ protected void doStart() throws Exception { // login route rootRouter.get(PATH_LOGIN) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(new LoginAuthenticationHandler(identityProviderManager, jwtService, certificateManager)) .handler(redirectUriValidationHandler) .handler(policyChainHandler.create(ExtensionPoint.PRE_LOGIN)) @@ -411,6 +417,7 @@ protected void doStart() throws Exception { rootRouter.post(PATH_LOGIN) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(botDetectionHandler) .handler(loginAttemptHandler) @@ -474,11 +481,13 @@ protected void doStart() throws Exception { Handler mfaChallengeUserHandler = new MFAChallengeUserHandler(userService); rootRouter.route(PATH_MFA_ENROLL) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(localeHandler) .handler(new MFAEnrollEndpoint(factorManager, thymeleafTemplateEngine, userService, domain, applicationContext, ruleEngine)); rootRouter.route(PATH_MFA_CHALLENGE) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(rememberDeviceSettingsHandler) .handler(localeHandler) @@ -488,12 +497,14 @@ protected void doStart() throws Exception { .failureHandler(new MFAChallengeFailureHandler(authenticationFlowContextService)); rootRouter.route(PATH_MFA_CHALLENGE_ALTERNATIVES) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(localeHandler) .handler(mfaChallengeUserHandler) .handler(new MFAChallengeAlternativesEndpoint(thymeleafTemplateEngine, factorManager, domain)); rootRouter.route(PATH_MFA_RECOVERY_CODE) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(localeHandler) .handler(new MFARecoveryCodeEndpoint(thymeleafTemplateEngine, domain, userService, factorManager, applicationContext)); @@ -503,6 +514,7 @@ protected void doStart() throws Exception { Handler webAuthnRememberDeviceHandler = new WebAuthnRememberDeviceHandler(webAuthnCookieService, domain); rootRouter.get(PATH_WEBAUTHN_REGISTER) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(webAuthnAccessHandler) .handler(localeHandler) @@ -510,6 +522,7 @@ protected void doStart() throws Exception { .handler(new WebAuthnRegisterEndpoint(thymeleafTemplateEngine, domain, factorManager)); rootRouter.post(PATH_WEBAUTHN_REGISTER) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(webAuthnAccessHandler) .handler(new WebAuthnRegisterHandler(userService, factorManager, domain, webAuthn, credentialService)) @@ -525,6 +538,7 @@ protected void doStart() throws Exception { .handler(new WebAuthnRegisterSuccessEndpoint(thymeleafTemplateEngine, credentialService, domain)); rootRouter.get(PATH_WEBAUTHN_LOGIN) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(webAuthnAccessHandler) .handler(new LoginAuthenticationHandler(identityProviderManager, jwtService, certificateManager)) @@ -533,6 +547,7 @@ protected void doStart() throws Exception { .handler(new WebAuthnLoginEndpoint(thymeleafTemplateEngine, domain, deviceIdentifierManager, userActivityService)); rootRouter.post(PATH_WEBAUTHN_LOGIN) .handler(clientRequestParseHandler) + .handler(bypassHandler) .handler(redirectUriValidationHandler) .handler(webAuthnAccessHandler) .handler(new WebAuthnLoginHandler(userService, factorManager, domain, webAuthn, credentialService, userAuthenticationManager)) diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/AbstractEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/AbstractEndpoint.java index 14ab4a66a29..17a9f24f704 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/AbstractEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/AbstractEndpoint.java @@ -15,8 +15,6 @@ */ package io.gravitee.am.gateway.handler.root.resources.endpoint; -import io.gravitee.am.common.utils.ConstantKeys; -import io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest; import io.gravitee.am.gateway.handler.manager.form.FormManager; import io.gravitee.am.model.oidc.Client; import io.gravitee.am.service.UserActivityService; @@ -24,7 +22,6 @@ import io.gravitee.common.http.HttpHeaders; import io.gravitee.common.http.MediaType; import io.reactivex.rxjava3.core.Single; -import io.vertx.rxjava3.core.MultiMap; import io.vertx.rxjava3.core.buffer.Buffer; import io.vertx.rxjava3.core.http.HttpServerRequest; import io.vertx.rxjava3.ext.web.RoutingContext; @@ -40,7 +37,6 @@ import static io.gravitee.am.common.utils.ConstantKeys.USER_ACTIVITY_RETENTION_TIME; import static io.gravitee.am.common.utils.ConstantKeys.USER_CONSENT_IP_LOCATION; import static io.gravitee.am.common.utils.ConstantKeys.USER_CONSENT_USER_AGENT; -import static io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest.CONTEXT_PATH; import static java.lang.Boolean.TRUE; /** @@ -92,20 +88,6 @@ protected Single renderPage(Map data, Client client) { return templateEngine.render(data, getTemplateFileName(client)); } - protected final String getReturnUrl(RoutingContext context, MultiMap queryParams) { - // look into the session - if (context.session().get(ConstantKeys.RETURN_URL_KEY) != null) { - return context.session().get(ConstantKeys.RETURN_URL_KEY); - } - // look into the request parameters - if (context.request().getParam(ConstantKeys.RETURN_URL_KEY) != null) { - return context.request().getParam(ConstantKeys.RETURN_URL_KEY); - } - // fallback to the OAuth 2.0 authorize endpoint - return UriBuilderRequest.resolveProxyRequest(context.request(), context.get(CONTEXT_PATH) + "/oauth/authorize", queryParams, true); - } - - protected void addUserActivityTemplateVariables(RoutingContext routingContext, UserActivityService userActivityService) { routingContext.put(USER_ACTIVITY_ENABLED, userActivityService.canSaveUserActivity()); if (userActivityService.canSaveUserActivity()) { diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginCallbackEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginCallbackEndpoint.java index b53b54ba6c5..cd5c6f9deb3 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginCallbackEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginCallbackEndpoint.java @@ -48,6 +48,7 @@ import static io.gravitee.am.common.utils.ConstantKeys.PARAM_CONTEXT_KEY; import static io.gravitee.am.common.utils.ConstantKeys.STATUS_SIGNED_IN; import static io.gravitee.am.common.web.UriBuilder.encodeURIComponent; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.getReturnUrl; 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; diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginPostEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginPostEndpoint.java index 1bdbc319f36..bbdc52c0c64 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginPostEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/login/LoginPostEndpoint.java @@ -17,14 +17,12 @@ import io.gravitee.am.common.utils.ConstantKeys; import io.gravitee.am.gateway.handler.root.resources.endpoint.AbstractEndpoint; -import io.gravitee.am.service.utils.vertx.RequestUtils; -import io.gravitee.common.http.HttpHeaders; import io.vertx.core.Handler; -import io.vertx.rxjava3.core.MultiMap; -import io.vertx.rxjava3.core.http.HttpServerResponse; import io.vertx.rxjava3.ext.web.RoutingContext; import io.vertx.rxjava3.ext.web.Session; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.doRedirect; + /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team @@ -34,20 +32,12 @@ public class LoginPostEndpoint extends AbstractEndpoint implements Handler enrolledFactor.getStatus() == FactorStatus.ACTIVATED); } - private void redirectToAuthorize(RoutingContext routingContext) { - final MultiMap queryParams = RequestUtils.getCleanedQueryParams(routingContext.request()); - final String returnURL = getReturnUrl(routingContext, queryParams); - doRedirect(routingContext.response(), returnURL); - } - private EnrolledFactor getSecurityFactor(MultiMap params, io.gravitee.am.model.Factor factor) { EnrolledFactor enrolledFactor = new EnrolledFactor(); switch (factor.getFactorType()) { @@ -394,10 +387,6 @@ public String getTemplateSuffix() { return Template.MFA_ENROLL.template(); } - private void doRedirect(HttpServerResponse response, String url) { - response.putHeader(HttpHeaders.LOCATION, url).setStatusCode(302).end(); - } - @Getter @Setter private static class Factor { diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/mfa/MFARecoveryCodeEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/mfa/MFARecoveryCodeEndpoint.java index cc0d0bfce73..d517992a108 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/mfa/MFARecoveryCodeEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/mfa/MFARecoveryCodeEndpoint.java @@ -55,6 +55,7 @@ import static io.gravitee.am.common.factor.FactorSecurityType.RECOVERY_CODE; import static io.gravitee.am.factor.api.FactorContext.KEY_USER; import static io.gravitee.am.gateway.handler.common.utils.ThymeleafDataHelper.generateData; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.doRedirect; import static io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest.CONTEXT_PATH; /** @@ -112,7 +113,7 @@ private void update(RoutingContext routingContext) { final EnrolledFactor factorToUpdate = recoveryFactor.get(); factorToUpdate.setStatus(FactorStatus.ACTIVATED); - userService.updateFactor(endUser.getId(), factorToUpdate, new DefaultUser(endUser)) + userService.upsertFactor(endUser.getId(), factorToUpdate, new DefaultUser(endUser)) .ignoreElement() .subscribe( () -> { @@ -171,15 +172,6 @@ private Optional getEnrolledRecoveryCodeFactorSecurity(U .findFirst(); } - private void doRedirect(RoutingContext routingContext) { - final MultiMap queryParams = RequestUtils.getCleanedQueryParams(routingContext.request()); - final String returnUrl = getReturnUrl(routingContext, queryParams); - routingContext.response() - .putHeader(io.vertx.core.http.HttpHeaders.LOCATION, returnUrl) - .setStatusCode(302) - .end(); - } - private Optional getRecoveryFactor(io.gravitee.am.model.User user) { if (user.getFactors() == null) { return Optional.empty(); diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpoint.java index 8961ea9f5f0..0c9769de3cd 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpoint.java @@ -36,6 +36,8 @@ import org.springframework.core.env.Environment; import static io.gravitee.am.common.utils.ConstantKeys.CLAIM_QUERY_PARAM; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.RESET_PWD_KEEP_PARAMS; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.getReturnUrl; /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) @@ -43,7 +45,6 @@ */ public class ResetPasswordSubmissionEndpoint extends UserRequestHandler { - public static final String GATEWAY_ENDPOINT_RESET_PWD_KEEP_PARAMS = "legacy.resetPassword.keepParams"; private static final Logger logger = LoggerFactory.getLogger(ResetPasswordSubmissionEndpoint.class); private final UserService userService; @@ -51,7 +52,7 @@ public class ResetPasswordSubmissionEndpoint extends UserRequestHandler { public ResetPasswordSubmissionEndpoint(UserService userService, Environment environment) { this.userService = userService; - this.keepParams = environment.getProperty(GATEWAY_ENDPOINT_RESET_PWD_KEEP_PARAMS, boolean.class, true); + this.keepParams = RESET_PWD_KEEP_PARAMS.from(environment); } @Override diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpoint.java index 434bce17e6d..6980969b08b 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpoint.java @@ -33,13 +33,14 @@ import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.REGISTRATION_KEEP_PARAMS; + /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team */ public class RegisterConfirmationSubmissionEndpoint extends UserRequestHandler { - public static final String GATEWAY_ENDPOINT_REGISTRATION_KEEP_PARAMS = "legacy.registration.keepParams"; private static final Logger logger = LoggerFactory.getLogger(RegisterConfirmationSubmissionEndpoint.class); private final UserService userService; @@ -47,7 +48,7 @@ public class RegisterConfirmationSubmissionEndpoint extends UserRequestHandler { public RegisterConfirmationSubmissionEndpoint(UserService userService, Environment environment) { this.userService = userService; - this.keepParams = environment.getProperty(GATEWAY_ENDPOINT_REGISTRATION_KEEP_PARAMS, boolean.class, true); + this.keepParams = REGISTRATION_KEEP_PARAMS.from(environment); } @Override diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpoint.java index 332685d72dd..3f73c4ed7fd 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpoint.java @@ -27,17 +27,18 @@ import io.vertx.rxjava3.ext.web.RoutingContext; import org.springframework.core.env.Environment; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.REGISTRATION_KEEP_PARAMS; + /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team */ public class RegisterSubmissionEndpoint implements Handler { - public static final String GATEWAY_ENDPOINT_REGISTRATION_KEEP_PARAMS = "legacy.registration.keepParams"; private final boolean keepParams; public RegisterSubmissionEndpoint(Environment environment) { - this.keepParams = environment.getProperty(GATEWAY_ENDPOINT_REGISTRATION_KEEP_PARAMS, boolean.class, true); + this.keepParams = REGISTRATION_KEEP_PARAMS.from(environment); } @Override diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnLoginPostEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnLoginPostEndpoint.java index 1b6df3ab1f7..f8cec165411 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnLoginPostEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnLoginPostEndpoint.java @@ -17,14 +17,14 @@ import io.gravitee.am.common.utils.ConstantKeys; import io.gravitee.am.gateway.handler.root.resources.endpoint.AbstractEndpoint; -import io.gravitee.am.service.utils.vertx.RequestUtils; import io.gravitee.common.http.HttpHeaders; import io.gravitee.common.http.MediaType; import io.vertx.core.Handler; import io.vertx.core.json.Json; -import io.vertx.rxjava3.core.MultiMap; import io.vertx.rxjava3.ext.web.RoutingContext; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.doRedirect; + /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team @@ -55,11 +55,6 @@ private void authenticateV0(RoutingContext ctx) { private void authenticateV1(RoutingContext ctx) { // at this stage the user has been authenticated // redirect the user to the original request - final MultiMap queryParams = RequestUtils.getCleanedQueryParams(ctx.request()); - final String redirectUri = getReturnUrl(ctx, queryParams); - - ctx.response().putHeader(io.vertx.core.http.HttpHeaders.LOCATION, redirectUri) - .setStatusCode(302) - .end(); + doRedirect(ctx); } } diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterEndpoint.java index e070382e10e..6621255d60f 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterEndpoint.java @@ -38,6 +38,7 @@ import java.util.HashMap; import static io.gravitee.am.gateway.handler.common.utils.ThymeleafDataHelper.generateData; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.getReturnUrl; /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterPostEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterPostEndpoint.java index 3bf560fa3a4..8a63224bbf1 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterPostEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterPostEndpoint.java @@ -31,6 +31,8 @@ import io.vertx.rxjava3.core.http.HttpServerRequest; import io.vertx.rxjava3.ext.web.RoutingContext; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.getReturnUrl; + /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterSuccessEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterSuccessEndpoint.java index 1c198ebdd80..fd983f438c9 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterSuccessEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnRegisterSuccessEndpoint.java @@ -42,6 +42,7 @@ import java.util.Optional; import static io.gravitee.am.gateway.handler.common.utils.ThymeleafDataHelper.generateData; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.doRedirect; /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) @@ -135,12 +136,7 @@ private void save(RoutingContext routingContext) { .subscribe(__ -> { // at this stage the registration has been done // redirect the user to the original request - final MultiMap queryParams = RequestUtils.getCleanedQueryParams(routingContext.request()); - final String redirectUri = getReturnUrl(routingContext, queryParams); - routingContext.response() - .putHeader(HttpHeaders.LOCATION, redirectUri) - .setStatusCode(302) - .end(); + doRedirect(routingContext); }, error -> { logger.error("An error has occurred when updating the webauthn credential {}", credentialId, error); diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnResponseEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnResponseEndpoint.java index 1e80ce08caf..f3f081791cc 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnResponseEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/endpoint/webauthn/WebAuthnResponseEndpoint.java @@ -16,11 +16,11 @@ package io.gravitee.am.gateway.handler.root.resources.endpoint.webauthn; import io.gravitee.am.gateway.handler.root.resources.endpoint.AbstractEndpoint; -import io.gravitee.am.service.utils.vertx.RequestUtils; import io.vertx.core.Handler; -import io.vertx.rxjava3.core.MultiMap; import io.vertx.rxjava3.ext.web.RoutingContext; +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.doRedirect; + /** * The callback route to verify attestations and assertions. Usually this route is
/webauthn/response
* @@ -36,11 +36,6 @@ public class WebAuthnResponseEndpoint extends AbstractEndpoint implements Handle public void handle(RoutingContext ctx) { // at this stage the user has been authenticated // redirect the user to the original request - final MultiMap queryParams = RequestUtils.getCleanedQueryParams(ctx.request()); - final String redirectUri = getReturnUrl(ctx, queryParams); - - ctx.response().putHeader(io.vertx.core.http.HttpHeaders.LOCATION, redirectUri) - .setStatusCode(302) - .end(); + doRedirect(ctx); } } diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/BypassDirectRequestHandler.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/BypassDirectRequestHandler.java new file mode 100644 index 00000000000..733a976d8cd --- /dev/null +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/BypassDirectRequestHandler.java @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.gravitee.am.gateway.handler.root.resources.handler; + + +import io.gravitee.am.common.utils.ConstantKeys; +import io.vertx.core.Handler; +import io.vertx.rxjava3.ext.web.RoutingContext; +import lombok.extern.slf4j.Slf4j; + +import static io.gravitee.am.gateway.handler.common.vertx.utils.RedirectHelper.doRedirect; +import static org.springframework.util.StringUtils.hasText; + +/** + * This handler is used to evaluate if an authentication step is coming from a regular flow + * or has been accessed directly by the user (hit the login page instead of the authorization endpoint) + * + * If the step is not coming from regular flow, the user is redirected to the authorization endpoint + * in order to evaluate the user session and go to the right action (login, mfa challenge, redirect to the app, etc ...) + * + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +@Slf4j +public class BypassDirectRequestHandler implements Handler { + + private final boolean skipHandlerExecution; + + public BypassDirectRequestHandler(boolean skip) { + this.skipHandlerExecution = skip; + } + + @Override + public void handle(RoutingContext routingContext) { + if (needAuthFlowStateEvaluation(routingContext)) { + routingContext.session().put(ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE, ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE_ONGOING); + doRedirect(routingContext); + } else { + // ongoing SESSION_KEY_AUTH_FLOW_STATE present into the session + // continue + routingContext.next(); + } + } + + /** + * SESSION_KEY_AUTH_FLOW_STATE is used by the authorization endpoint to flag an ongoing authentication + * If this flag is missing, a redirect to the authorization endpoint is triggered to route the user to the right step + * + * @param routingContext + * @return true if a redirect to the authorization endpoint is required, false otherwise + */ + private boolean needAuthFlowStateEvaluation(RoutingContext routingContext) { + return !skipHandlerExecution && (routingContext.session() == null || + !hasText(routingContext.session().get(ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE)) || + !ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE_ONGOING.equalsIgnoreCase(routingContext.session().get(ConstantKeys.SESSION_KEY_AUTH_FLOW_STATE))); + } +} diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/ConditionalBodyHandler.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/ConditionalBodyHandler.java index d6c82cee95e..80d9dfba284 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/ConditionalBodyHandler.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/main/java/io/gravitee/am/gateway/handler/root/resources/handler/ConditionalBodyHandler.java @@ -21,6 +21,8 @@ import io.vertx.rxjava3.ext.web.handler.BodyHandler; import org.springframework.core.env.Environment; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.HANDLER_ALWAYS_APPLY_BODY_HDL; + /** * @author Eric LELEU (eric.leleu at graviteesource.com) * @author GraviteeSource Team @@ -35,7 +37,7 @@ public ConditionalBodyHandler(Environment env) { ConditionalBodyHandler(Environment env, Handler bodyHandler) { this.delegatedBodyHandler = bodyHandler; - this.alwaysApplyBodyHandler = env.getProperty("legacy.handler.alwaysApplyBodyHandler", Boolean.class, false); + this.alwaysApplyBodyHandler = HANDLER_ALWAYS_APPLY_BODY_HDL.from(env); } @Override diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpointTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpointTest.java index 4205e9f2a66..7a74b622a4d 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpointTest.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/password/ResetPasswordSubmissionEndpointTest.java @@ -37,6 +37,7 @@ import java.util.Collections; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.RESET_PWD_KEEP_PARAMS; import static io.vertx.core.http.HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED; import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; import static org.mockito.ArgumentMatchers.any; @@ -59,7 +60,7 @@ public class ResetPasswordSubmissionEndpointTest extends RxWebTestBase { @Override public void setUp() throws Exception { super.setUp(); - when(environment.getProperty(eq(ResetPasswordSubmissionEndpoint.GATEWAY_ENDPOINT_RESET_PWD_KEEP_PARAMS), any(), eq(true))).thenReturn(true); + when(environment.getProperty(eq(RESET_PWD_KEEP_PARAMS.getKey()), any(), eq(RESET_PWD_KEEP_PARAMS.getDefaultValue()))).thenReturn(true); ResetPasswordSubmissionEndpoint resetPasswordSubmissionEndpoint = new ResetPasswordSubmissionEndpoint(userService, environment); router.route(HttpMethod.POST, "/resetPassword") diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpointTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpointTest.java index 2bd0b50ac92..1ec840fb328 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpointTest.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterConfirmationSubmissionEndpointTest.java @@ -34,6 +34,7 @@ import java.util.Collections; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.REGISTRATION_KEEP_PARAMS; import static io.vertx.core.http.HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED; import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; import static org.mockito.ArgumentMatchers.any; @@ -55,7 +56,7 @@ public class RegisterConfirmationSubmissionEndpointTest extends RxWebTestBase { @Override public void setUp() throws Exception { super.setUp(); - when(environment.getProperty(eq(RegisterSubmissionEndpoint.GATEWAY_ENDPOINT_REGISTRATION_KEEP_PARAMS), any(), eq(true))).thenReturn(true); + when(environment.getProperty(eq(REGISTRATION_KEEP_PARAMS.getKey()), any(), eq(REGISTRATION_KEEP_PARAMS.getDefaultValue()))).thenReturn(true); RegisterConfirmationSubmissionEndpoint registerConfirmationSubmissionEndpoint = new RegisterConfirmationSubmissionEndpoint(userService, environment); router.route(HttpMethod.POST, "/confirmRegistration") .handler(BodyHandler.create()) diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpointTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpointTest.java index b0f726245ce..e02ad8d0ca4 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpointTest.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-core/src/test/java/io/gravitee/am/gateway/handler/root/resources/endpoint/user/register/RegisterSubmissionEndpointTest.java @@ -37,6 +37,7 @@ import java.util.Collections; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.REGISTRATION_KEEP_PARAMS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -60,7 +61,7 @@ public class RegisterSubmissionEndpointTest extends RxWebTestBase { @Override public void setUp() throws Exception { super.setUp(); - when(environment.getProperty(eq(RegisterSubmissionEndpoint.GATEWAY_ENDPOINT_REGISTRATION_KEEP_PARAMS), any(), eq(true))).thenReturn(true); + when(environment.getProperty(eq(REGISTRATION_KEEP_PARAMS.getKey()), any(), eq(REGISTRATION_KEEP_PARAMS.getDefaultValue()))).thenReturn(true); router.route(HttpMethod.POST, "/register") .handler(BodyHandler.create()) .handler(new RegisterProcessHandler(userService, domain)) diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/OAuth2Provider.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/OAuth2Provider.java index 3df08da9e38..e546d053ae3 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/OAuth2Provider.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/OAuth2Provider.java @@ -68,6 +68,7 @@ import io.gravitee.am.gateway.handler.oidc.service.jwe.JWEService; import io.gravitee.am.gateway.handler.oidc.service.jwk.JWKService; import io.gravitee.am.gateway.handler.oidc.service.request.RequestObjectService; +import io.gravitee.am.gateway.handler.root.resources.handler.BypassDirectRequestHandler; import io.gravitee.am.gateway.handler.root.resources.handler.LocaleHandler; import io.gravitee.am.gateway.handler.root.resources.handler.common.RedirectUriValidationHandler; import io.gravitee.am.gateway.handler.root.resources.handler.transactionid.TransactionIdHandler; @@ -92,6 +93,10 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.env.Environment; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.HANDLER_SKIP_BYPASS_DIRECT_REQUEST_HDL; + +//import static io.gravitee.am.gateway.core.LegacySettingsKeys.HANDLER_SKIP_BYPASS_DIRECT_REQUEST_HDL; + /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team @@ -281,7 +286,9 @@ private void initRouter() { // Authorization consent endpoint Handler userConsentPrepareContextHandler = new UserConsentPrepareContextHandler(); + final var bypassDirectrequestHandler = new BypassDirectRequestHandler(HANDLER_SKIP_BYPASS_DIRECT_REQUEST_HDL.from(environment)); oauth2Router.route(HttpMethod.GET, "/consent") + .handler(bypassDirectrequestHandler) .handler(new AuthorizationRequestParseClientHandler(clientSyncService)) .handler(new AuthorizationRequestParseProviderConfigurationHandler(openIDDiscoveryService)) .handler(authenticationFlowContextHandler) @@ -293,6 +300,7 @@ private void initRouter() { .handler(localeHandler) .handler(new UserConsentEndpoint(userConsentService, thymeleafTemplateEngine, domain)); oauth2Router.route(HttpMethod.POST, "/consent") + .handler(bypassDirectrequestHandler) .handler(new AuthorizationRequestParseClientHandler(clientSyncService)) .handler(new AuthorizationRequestParseProviderConfigurationHandler(openIDDiscoveryService)) .handler(authenticationFlowContextHandler) diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/endpoint/authorization/AuthorizationEndpoint.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/endpoint/authorization/AuthorizationEndpoint.java index 945e5c755d6..229bab0e203 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/endpoint/authorization/AuthorizationEndpoint.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/endpoint/authorization/AuthorizationEndpoint.java @@ -17,6 +17,7 @@ import io.gravitee.am.common.oauth2.ResponseMode; import io.gravitee.am.common.utils.ConstantKeys; +import io.gravitee.am.gateway.handler.manager.session.SessionManager; import io.gravitee.am.gateway.handler.oauth2.exception.AccessDeniedException; import io.gravitee.am.gateway.handler.oauth2.exception.ServerErrorException; import io.gravitee.am.gateway.handler.oauth2.service.par.PushedAuthorizationRequestService; @@ -55,11 +56,13 @@ public class AuthorizationEndpoint implements Handler { private final Flow flow; private final ThymeleafTemplateEngine engine; private final PushedAuthorizationRequestService parService; + private final SessionManager sessionManager; public AuthorizationEndpoint(Flow flow, ThymeleafTemplateEngine engine, PushedAuthorizationRequestService parService) { this.flow = flow; this.engine = engine; this.parService = parService; + this.sessionManager = new SessionManager(); } @Override @@ -142,17 +145,6 @@ private void doRedirect(RoutingContext context, AuthorizationRequest request, Au } private void cleanSession(RoutingContext context) { - context.session().remove(ConstantKeys.TRANSACTION_ID_KEY); - context.session().remove(ConstantKeys.USER_CONSENT_COMPLETED_KEY); - context.session().remove(ConstantKeys.WEBAUTHN_CREDENTIAL_ID_CONTEXT_KEY); - context.session().remove(ConstantKeys.WEBAUTHN_CREDENTIAL_INTERNAL_ID_CONTEXT_KEY); - context.session().remove(ConstantKeys.PASSWORDLESS_AUTH_ACTION_KEY); - context.session().remove(ConstantKeys.MFA_FACTOR_ID_CONTEXT_KEY); - context.session().remove(ConstantKeys.PASSWORDLESS_CHALLENGE_KEY); - context.session().remove(ConstantKeys.PASSWORDLESS_CHALLENGE_USERNAME_KEY); - context.session().remove(ConstantKeys.MFA_ENROLLMENT_COMPLETED_KEY); - context.session().remove(ConstantKeys.MFA_CHALLENGE_COMPLETED_KEY); - context.session().remove(ConstantKeys.USER_LOGIN_COMPLETED_KEY); - context.session().remove(ConstantKeys.MFA_ENROLL_CONDITIONAL_SKIPPED_KEY); + sessionManager.cleanSessionAfterAuth(context); } } diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/handler/authorization/AuthorizationRequestFailureHandler.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/handler/authorization/AuthorizationRequestFailureHandler.java index 188e05ea58f..ebb3192ae99 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/handler/authorization/AuthorizationRequestFailureHandler.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oauth2/resources/handler/authorization/AuthorizationRequestFailureHandler.java @@ -26,6 +26,7 @@ import io.gravitee.am.gateway.handler.common.jwt.JWTService; import io.gravitee.am.gateway.handler.common.utils.HashUtil; import io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest; +import io.gravitee.am.gateway.handler.manager.session.SessionManager; import io.gravitee.am.gateway.handler.oauth2.exception.JWTOAuth2Exception; import io.gravitee.am.gateway.handler.oauth2.resources.request.AuthorizationRequestFactory; import io.gravitee.am.gateway.handler.oauth2.service.request.AuthorizationRequest; @@ -85,6 +86,7 @@ public class AuthorizationRequestFailureHandler implements Handler create(OAuth2Request oAuth2Request, Client client, User user, ExecutionContext executionContext) { // use or create execution context diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/resources/endpoint/UserInfoEndpointHandlerTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/resources/endpoint/UserInfoEndpointHandlerTest.java index 4dfab40fd5c..3e468f89378 100644 --- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/resources/endpoint/UserInfoEndpointHandlerTest.java +++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/resources/endpoint/UserInfoEndpointHandlerTest.java @@ -60,6 +60,7 @@ import java.util.List; import java.util.Map; +import static io.gravitee.am.gateway.core.LegacySettingsKeys.OIDC_SCOPE_FULL_PROFILE; import static org.mockito.Mockito.any; import static org.mockito.Mockito.when; @@ -93,8 +94,7 @@ public class UserInfoEndpointHandlerTest extends RxWebTestBase { @Override public void setUp() throws Exception { super.setUp(); - - when(env.getProperty("legacy.openid.openid_scope_full_profile", boolean.class, false)).thenReturn(false); + when(env.getProperty(OIDC_SCOPE_FULL_PROFILE.getKey(), Boolean.class, OIDC_SCOPE_FULL_PROFILE.getDefaultValue())).thenReturn(false); userInfoEndpoint = new UserInfoEndpoint(userEnhancer, jwtService, jweService, openIDDiscoveryService, env, subjectManager); router.route(HttpMethod.GET, "/userinfo")