| | |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | | import java.util.Set; |
| | | import java.util.TreeSet; |
| | | import java.util.regex.Pattern; |
| | | |
| | | import org.keycloak.OAuth2Constants; |
| | | import org.keycloak.common.util.KeycloakUriBuilder; |
| | | import org.keycloak.common.util.MultivaluedHashMap; |
| | | import org.keycloak.common.util.UriUtils; |
| | | import org.keycloak.models.ClientModel; |
| | | import org.keycloak.models.Constants; |
| | |
| | | |
| | | public static final Set<String> LOOPBACK_INTERFACES = new HashSet<>(Arrays.asList("localhost", "127.0.0.1", "[::1]")); |
| | | |
| | | private static final Set<String> FORBIDDEN_OIDC_PARAMS = Set.of( |
| | | OAuth2Constants.CODE, |
| | | OAuth2Constants.ID_TOKEN, |
| | | OAuth2Constants.ACCESS_TOKEN, |
| | | OAuth2Constants.TOKEN_TYPE, |
| | | OAuth2Constants.EXPIRES_IN, |
| | | OAuth2Constants.STATE, |
| | | OAuth2Constants.ISSUER, |
| | | OAuth2Constants.ERROR, |
| | | OAuth2Constants.ERROR_DESCRIPTION, |
| | | OAuth2Constants.SESSION_STATE, |
| | | OAuth2Constants.RESPONSE, |
| | | Constants.KC_ACTION, |
| | | Constants.KC_ACTION_STATUS |
| | | ); |
| | | |
| | | private static final Logger logger = Logger.getLogger(RedirectUtils.class); |
| | | |
| | | public static String verifyRedirectUri(KeycloakSession session, String redirectUri, ClientModel client) { |
| | |
| | | return null; |
| | | } |
| | | |
| | | // Check for HTTP Parameter Pollution - forbidden OIDC response parameters in redirect URI |
| | | if (containsForbiddenOidcParameters(originalRedirect)){ |
| | | return null; |
| | | } |
| | | |
| | | // check if the passed URI allows wildcards |
| | | boolean allowWildcards = areWildcardsAllowed(originalRedirect); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private static boolean containsForbiddenOidcParameters(URI originalRedirect) { |
| | | String query = originalRedirect.getRawQuery(); |
| | | if (query != null && !query.isEmpty()) { |
| | | MultivaluedHashMap<String, String> params =UriUtils.decodeQueryString(query); |
| | | for (String paramName : params.keySet()) { |
| | | if (FORBIDDEN_OIDC_PARAMS.contains(paramName.toLowerCase(Locale.ROOT))) { |
| | | logger.warnf("Redirect URI rejected: contains forbidden OIDC parameter '%s' in query string: scheme=%s, host=%s, path=%s", |
| | | paramName, |
| | | originalRedirect.getScheme(), |
| | | originalRedirect.getHost(), |
| | | originalRedirect.getPath()); |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private static URI toUri(String redirectUri) { |
| | | URI uri = null; |
| | | if (redirectUri != null) { |