-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #435 from Adyen/feature/AD-294
AD-294 Implement Multiple Small Improvements in v12 Adyen Integration…
- Loading branch information
Showing
12 changed files
with
379 additions
and
9 deletions.
There are no files selected for viewing
55 changes: 55 additions & 0 deletions
55
.../acceleratoraddon/web/src/com/adyen/commerce/filters/SameSiteCookiePostProcessFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* ###### | ||
* ###### | ||
* ############ ####( ###### #####. ###### ############ ############ | ||
* ############# #####( ###### #####. ###### ############# ############# | ||
* ###### #####( ###### #####. ###### ##### ###### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ###### | ||
* ############# ############# ############# ############# ##### ###### | ||
* ############ ############ ############# ############ ##### ###### | ||
* ###### | ||
* ############# | ||
* ############ | ||
* | ||
* Adyen Hybris Extension | ||
* | ||
* Copyright (c) 2020 Adyen B.V. | ||
* This file is open source and available under the MIT license. | ||
* See the LICENSE file for more info. | ||
*/ | ||
|
||
package com.adyen.commerce.filters; | ||
|
||
import com.adyen.commerce.utils.SameSiteCookieAttributeAppenderUtils; | ||
import org.springframework.web.filter.GenericFilterBean; | ||
|
||
import javax.servlet.FilterChain; | ||
import javax.servlet.ServletException; | ||
import javax.servlet.ServletRequest; | ||
import javax.servlet.ServletResponse; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
|
||
/* | ||
* This class uses code written by Igor Zarvanskyi and published on https://clutcher.github.io/post/hybris/same_site_login_issue/ | ||
*/ | ||
public class SameSiteCookiePostProcessFilter extends GenericFilterBean { | ||
|
||
private SameSiteCookieAttributeAppenderUtils sameSiteCookieAttributeAppenderUtils; | ||
|
||
@Override | ||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { | ||
getSameSiteCookieAttributeAppenderUtils().addSameSiteAttribute((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); | ||
filterChain.doFilter(servletRequest, servletResponse); | ||
} | ||
|
||
protected SameSiteCookieAttributeAppenderUtils getSameSiteCookieAttributeAppenderUtils() { | ||
return sameSiteCookieAttributeAppenderUtils; | ||
} | ||
|
||
public void setSameSiteCookieAttributeAppenderUtils(SameSiteCookieAttributeAppenderUtils sameSiteCookieAttributeAppenderUtils) { | ||
this.sameSiteCookieAttributeAppenderUtils = sameSiteCookieAttributeAppenderUtils; | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
...ddon/web/src/com/adyen/commerce/interceptors/SameSiteCookieHandlerInterceptorAdapter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* ###### | ||
* ###### | ||
* ############ ####( ###### #####. ###### ############ ############ | ||
* ############# #####( ###### #####. ###### ############# ############# | ||
* ###### #####( ###### #####. ###### ##### ###### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ###### | ||
* ############# ############# ############# ############# ##### ###### | ||
* ############ ############ ############# ############ ##### ###### | ||
* ###### | ||
* ############# | ||
* ############ | ||
* | ||
* Adyen Hybris Extension | ||
* | ||
* Copyright (c) 2020 Adyen B.V. | ||
* This file is open source and available under the MIT license. | ||
* See the LICENSE file for more info. | ||
*/ | ||
|
||
package com.adyen.commerce.interceptors; | ||
|
||
import com.adyen.commerce.utils.SameSiteCookieAttributeAppenderUtils; | ||
import org.springframework.web.servlet.ModelAndView; | ||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
/* | ||
* This class uses code written by Igor Zarvanskyi and published on https://clutcher.github.io/post/hybris/same_site_login_issue/ | ||
*/ | ||
public class SameSiteCookieHandlerInterceptorAdapter extends HandlerInterceptorAdapter { | ||
|
||
private SameSiteCookieAttributeAppenderUtils sameSiteCookieAttributeAppenderUtils; | ||
|
||
@Override | ||
public void postHandle(HttpServletRequest servletRequest, HttpServletResponse servletResponse, Object handler, ModelAndView modelAndView) { | ||
getSameSiteCookieAttributeAppenderUtils().addSameSiteAttribute(servletRequest, servletResponse); | ||
} | ||
|
||
protected SameSiteCookieAttributeAppenderUtils getSameSiteCookieAttributeAppenderUtils() { | ||
return sameSiteCookieAttributeAppenderUtils; | ||
} | ||
|
||
public void setSameSiteCookieAttributeAppenderUtils(SameSiteCookieAttributeAppenderUtils sameSiteCookieAttributeAppenderUtils) { | ||
this.sameSiteCookieAttributeAppenderUtils = sameSiteCookieAttributeAppenderUtils; | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
...ratoraddon/web/src/com/adyen/commerce/security/AdyenGUIDAuthenticationSuccessHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* ###### | ||
* ###### | ||
* ############ ####( ###### #####. ###### ############ ############ | ||
* ############# #####( ###### #####. ###### ############# ############# | ||
* ###### #####( ###### #####. ###### ##### ###### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ###### | ||
* ############# ############# ############# ############# ##### ###### | ||
* ############ ############ ############# ############ ##### ###### | ||
* ###### | ||
* ############# | ||
* ############ | ||
* | ||
* Adyen Hybris Extension | ||
* | ||
* Copyright (c) 2020 Adyen B.V. | ||
* This file is open source and available under the MIT license. | ||
* See the LICENSE file for more info. | ||
*/ | ||
|
||
package com.adyen.commerce.security; | ||
|
||
import com.adyen.commerce.utils.SameSiteCookieAttributeAppenderUtils; | ||
import de.hybris.platform.acceleratorstorefrontcommons.security.GUIDCookieStrategy; | ||
import org.springframework.beans.factory.annotation.Required; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | ||
|
||
import javax.servlet.ServletException; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
|
||
/* | ||
* This class uses code written by Igor Zarvanskyi and published on https://clutcher.github.io/post/hybris/same_site_login_issue/ | ||
*/ | ||
public class AdyenGUIDAuthenticationSuccessHandler implements AuthenticationSuccessHandler | ||
{ | ||
private GUIDCookieStrategy guidCookieStrategy; | ||
private AuthenticationSuccessHandler authenticationSuccessHandler; | ||
private SameSiteCookieAttributeAppenderUtils sameSiteCookieAttributeAppenderUtils; | ||
|
||
@Override | ||
public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, | ||
final Authentication authentication) throws IOException, ServletException | ||
{ | ||
getGuidCookieStrategy().setCookie(request, response); | ||
|
||
// onAuthenticationSuccess will commit response, so we won't be able to change it, that's why we should execute filter before it. | ||
getSameSiteCookieAttributeAppenderUtils().addSameSiteAttribute(request, response); | ||
|
||
getAuthenticationSuccessHandler().onAuthenticationSuccess(request, response, authentication); | ||
} | ||
|
||
protected GUIDCookieStrategy getGuidCookieStrategy() | ||
{ | ||
return guidCookieStrategy; | ||
} | ||
|
||
/** | ||
* @param guidCookieStrategy the guidCookieStrategy to set | ||
*/ | ||
@Required | ||
public void setGuidCookieStrategy(final GUIDCookieStrategy guidCookieStrategy) | ||
{ | ||
this.guidCookieStrategy = guidCookieStrategy; | ||
} | ||
|
||
protected AuthenticationSuccessHandler getAuthenticationSuccessHandler() | ||
{ | ||
return authenticationSuccessHandler; | ||
} | ||
|
||
/** | ||
* @param authenticationSuccessHandler the authenticationSuccessHandler to set | ||
*/ | ||
@Required | ||
public void setAuthenticationSuccessHandler(final AuthenticationSuccessHandler authenticationSuccessHandler) | ||
{ | ||
this.authenticationSuccessHandler = authenticationSuccessHandler; | ||
} | ||
|
||
protected SameSiteCookieAttributeAppenderUtils getSameSiteCookieAttributeAppenderUtils() { | ||
return sameSiteCookieAttributeAppenderUtils; | ||
} | ||
|
||
public void setSameSiteCookieAttributeAppenderUtils(SameSiteCookieAttributeAppenderUtils sameSiteCookieAttributeAppenderUtils) { | ||
this.sameSiteCookieAttributeAppenderUtils = sameSiteCookieAttributeAppenderUtils; | ||
} | ||
} |
151 changes: 151 additions & 0 deletions
151
...celeratoraddon/web/src/com/adyen/commerce/utils/SameSiteCookieAttributeAppenderUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
/* | ||
* ###### | ||
* ###### | ||
* ############ ####( ###### #####. ###### ############ ############ | ||
* ############# #####( ###### #####. ###### ############# ############# | ||
* ###### #####( ###### #####. ###### ##### ###### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### | ||
* ###### ###### #####( ###### #####. ###### ##### ##### ###### | ||
* ############# ############# ############# ############# ##### ###### | ||
* ############ ############ ############# ############ ##### ###### | ||
* ###### | ||
* ############# | ||
* ############ | ||
* | ||
* Adyen Hybris Extension | ||
* | ||
* Copyright (c) 2020 Adyen B.V. | ||
* This file is open source and available under the MIT license. | ||
* See the LICENSE file for more info. | ||
*/ | ||
|
||
package com.adyen.commerce.utils; | ||
|
||
import com.google.common.net.HttpHeaders; | ||
import de.hybris.platform.servicelayer.config.ConfigurationService; | ||
import org.apache.commons.collections4.CollectionUtils; | ||
import org.apache.commons.configuration.Configuration; | ||
import org.apache.log4j.Logger; | ||
|
||
import javax.servlet.ServletResponse; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
/* | ||
* This class uses code written by Igor Zarvanskyi and published on https://clutcher.github.io/post/hybris/same_site_login_issue/ | ||
*/ | ||
public class SameSiteCookieAttributeAppenderUtils { | ||
|
||
private static final Logger LOG = Logger.getLogger(SameSiteCookieAttributeAppenderUtils.class); | ||
|
||
private ConfigurationService configurationService; | ||
|
||
private static final String PLATFORM_VERSION_PROPERTY = "build.version.api"; | ||
private static final String SAMESITE_COOKIE_HANDLER_ENABLED_PROPERTY = "adyen.samesitecookie.handler.enabled"; | ||
private static final int SAP_VERSION_WITH_SAMESITE_FIX = 2005; | ||
private static final List<String> COOKIES_WITH_FORCE_SAME_SITE_NONE = Arrays.asList("JSESSIONID", "acceleratorSecureGUID", "yacceleratorstorefrontRememberMe"); | ||
private static final Pattern CHROME_VERSION = Pattern.compile("Chrom[^ \\/]+\\/(\\d+)[\\.\\d]*"); | ||
|
||
public void addSameSiteAttribute(HttpServletRequest servletRequest, HttpServletResponse servletResponse) { | ||
// Do not modify cookies for SAP versions which already have SameSite cookies handler available | ||
if(isPlatformVersionWithSameSiteFix()) { | ||
return; | ||
} | ||
|
||
if (isSameSiteCookieHandlingEnabled() && isNotCommittedResponse(servletResponse)) { | ||
Collection<String> headers = servletResponse.getHeaders(HttpHeaders.SET_COOKIE); | ||
if (CollectionUtils.isNotEmpty(headers)) { | ||
String userAgent = servletRequest.getHeader(HttpHeaders.USER_AGENT); | ||
for (String sameSiteCookie : COOKIES_WITH_FORCE_SAME_SITE_NONE) { | ||
addSameSiteNone(sameSiteCookie, servletResponse, userAgent); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private void addSameSiteNone(String sameSiteCookie, HttpServletResponse servletResponse, String userAgent) { | ||
Collection<String> headers = servletResponse.getHeaders(HttpHeaders.SET_COOKIE); | ||
|
||
// Check if exists session set cookie header | ||
Optional<String> sessionCookieWithoutSameSite = headers.stream() | ||
.filter(cookie -> cookie.startsWith(sameSiteCookie) && !cookie.contains("SameSite")) | ||
.findAny(); | ||
|
||
if (sessionCookieWithoutSameSite.isPresent() && shouldSendSameSiteNone(userAgent)) { | ||
// Replace all set cookie headers with 1 new session + sameSite header | ||
servletResponse.setHeader(HttpHeaders.SET_COOKIE, sessionCookieWithoutSameSite.get() + ";Secure ;SameSite=None"); | ||
|
||
// Re-add all other set cookie headers | ||
headers.stream() | ||
.filter(cookie -> !cookie.startsWith(sameSiteCookie)) | ||
.forEach(cookie -> servletResponse.addHeader(HttpHeaders.SET_COOKIE, cookie)); | ||
} | ||
} | ||
|
||
private boolean isNotCommittedResponse(ServletResponse servletResponse) { | ||
return !servletResponse.isCommitted(); | ||
} | ||
|
||
private boolean isSameSiteCookieHandlingEnabled() { | ||
Configuration configuration = getConfigurationService().getConfiguration(); | ||
boolean isSameSiteCookieHandlingEnabled = false; | ||
if (configuration.containsKey(SAMESITE_COOKIE_HANDLER_ENABLED_PROPERTY)) { | ||
isSameSiteCookieHandlingEnabled = configuration.getBoolean(SAMESITE_COOKIE_HANDLER_ENABLED_PROPERTY); | ||
} | ||
return isSameSiteCookieHandlingEnabled; | ||
} | ||
|
||
private boolean isPlatformVersionWithSameSiteFix() { | ||
try { | ||
String platformVersion = getConfigurationService().getConfiguration().getString(PLATFORM_VERSION_PROPERTY); | ||
if(platformVersion != null) { | ||
String[] platformVersionSplit = platformVersion.split("\\."); | ||
//compare major version | ||
int majorVersion = Integer.parseInt(platformVersionSplit[0]); | ||
return majorVersion >= SAP_VERSION_WITH_SAMESITE_FIX; | ||
} | ||
} catch (Exception e) { | ||
LOG.debug(e); | ||
} | ||
|
||
LOG.debug("Could not parse platform version, SameSite cookie handling will be skipped"); | ||
return true; | ||
} | ||
|
||
public static boolean shouldSendSameSiteNone(String useragent) { | ||
return isChromiumBased(useragent) && isChromiumVersionAtLeast(80, useragent); | ||
} | ||
|
||
private static boolean isChromiumBased(String useragent) { | ||
return useragent.contains("Chrome") || useragent.contains("Chromium"); | ||
} | ||
|
||
private static boolean isChromiumVersionAtLeast(int major, String useragent) { | ||
Matcher matcher = CHROME_VERSION.matcher(useragent); | ||
if (matcher.find()) { | ||
try { | ||
String chromeVersion = matcher.group(1); | ||
return Integer.parseInt(chromeVersion) >= major; | ||
} catch (Exception e) { | ||
LOG.debug(e); | ||
} | ||
} | ||
|
||
LOG.debug("Could not parse Chrome browser version, SameSite cookie handling will be skipped"); | ||
return false; | ||
} | ||
|
||
public ConfigurationService getConfigurationService() { | ||
return configurationService; | ||
} | ||
|
||
public void setConfigurationService(ConfigurationService configurationService) { | ||
this.configurationService = configurationService; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.