Backchannel logout url with curly brackets
closes #30023 Signed-off-by: raff897 <85362193+raff897@users.noreply.github.com>
This commit is contained in:
parent
0cd0d03c08
commit
6d6131cade
2 changed files with 69 additions and 1 deletions
|
@ -35,6 +35,9 @@ import org.keycloak.services.util.ResolveRelative;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -235,13 +238,21 @@ public class DefaultClientValidationProvider implements ClientValidationProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void checkUri(FieldMessages field, String url, ValidationContext<ClientModel> context, boolean checkValidUrl, boolean checkFragment) {
|
private void checkUri(FieldMessages field, String url, ValidationContext<ClientModel> context, boolean checkValidUrl, boolean checkFragment) {
|
||||||
if (url == null || url.isEmpty()) {
|
if (url == null || url.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
URI uri = new URI(url);
|
String urlToCheck=url;
|
||||||
|
if(field==FieldMessages.BACKCHANNEL_LOGOUT_URL){
|
||||||
|
if(checkCurlyBracketsBalanced(url))
|
||||||
|
// This allow user to set parametrized backchannel logout url in this format : http://{example}/{example2}
|
||||||
|
urlToCheck=url.replace("{","%7B").replace("}","%7D");
|
||||||
|
else throw new MalformedURLException();
|
||||||
|
}
|
||||||
|
URI uri = new URI(urlToCheck);
|
||||||
|
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
if (uri.getScheme() != null && (uri.getScheme().equals("data") || uri.getScheme().equals("javascript"))) {
|
if (uri.getScheme() != null && (uri.getScheme().equals("data") || uri.getScheme().equals("javascript"))) {
|
||||||
|
@ -262,11 +273,42 @@ public class DefaultClientValidationProvider implements ClientValidationProvider
|
||||||
uri.toURL(); // throws an exception
|
uri.toURL(); // throws an exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (MalformedURLException | IllegalArgumentException | URISyntaxException e) {
|
catch (MalformedURLException | IllegalArgumentException | URISyntaxException e) {
|
||||||
context.addError(field.getFieldId(), field.getInvalid(), field.getInvalidKey());
|
context.addError(field.getFieldId(), field.getInvalid(), field.getInvalidKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if url has curly brackets in correct position ('{' before '}')
|
||||||
|
* @param url to check
|
||||||
|
* @return true if curly brackets are balanced, else false
|
||||||
|
*/
|
||||||
|
public static boolean checkCurlyBracketsBalanced(String url)
|
||||||
|
{
|
||||||
|
Deque<Character> stack
|
||||||
|
= new ArrayDeque<>();
|
||||||
|
|
||||||
|
for(char singleLetter:url.toCharArray()){
|
||||||
|
if (singleLetter == '{')
|
||||||
|
{
|
||||||
|
// Push the element in the stack
|
||||||
|
stack.push(singleLetter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(stack.isEmpty() && (singleLetter=='}')) return false;
|
||||||
|
char check;
|
||||||
|
if(singleLetter=='}'){
|
||||||
|
check=stack.pop();
|
||||||
|
if(check!='{') return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return stack.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private void checkUriLogo(FieldMessages field, String url, ValidationContext<ClientModel> context) {
|
private void checkUriLogo(FieldMessages field, String url, ValidationContext<ClientModel> context) {
|
||||||
if (url == null || url.isEmpty()) {
|
if (url == null || url.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.keycloak.testsuite.client;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.validation.DefaultClientValidationProvider;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class DefaultClientValidationTest {
|
||||||
|
@Test
|
||||||
|
public void that_checkCurlyBracketsBalanced_worksCorrectly() {
|
||||||
|
String urlWithCurlyBrackets1="http://{test}/prova123";
|
||||||
|
String urlWithCurlyBrackets2="http://{test}/{prova123}";
|
||||||
|
String urlWithCurlyBrackets3="http://{{test}/{prova123}}";
|
||||||
|
assertTrue(DefaultClientValidationProvider.checkCurlyBracketsBalanced(urlWithCurlyBrackets1));
|
||||||
|
assertTrue(DefaultClientValidationProvider.checkCurlyBracketsBalanced(urlWithCurlyBrackets2));
|
||||||
|
assertTrue(DefaultClientValidationProvider.checkCurlyBracketsBalanced(urlWithCurlyBrackets3));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void that_checkCurlyBracketsBalanced_notWorksCorrectly() {
|
||||||
|
String urlWithImproperlyCurlyBrackets="http://}test}/prova123";
|
||||||
|
String urlWithImproperlyCurlyBrackets1="http://{test}/prova123}";
|
||||||
|
assertFalse(DefaultClientValidationProvider.checkCurlyBracketsBalanced(urlWithImproperlyCurlyBrackets));
|
||||||
|
assertFalse(DefaultClientValidationProvider.checkCurlyBracketsBalanced(urlWithImproperlyCurlyBrackets1));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue