KEYCLOAK-7523 better context path detection in PathBasedKeycloakConfigResolver
This commit is contained in:
parent
49407c2e4f
commit
fca6da3a5a
3 changed files with 186 additions and 7 deletions
|
@ -99,6 +99,12 @@
|
||||||
<version>${cxf.version}</version>
|
<version>${cxf.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@ -34,13 +35,35 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
||||||
String path = request.getURI();
|
String uri = request.getURI();
|
||||||
String[] urlTokens = path.split("/");
|
String relativePath = request.getRelativePath();
|
||||||
if (urlTokens.length < 4) {
|
String webContext = null;
|
||||||
throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
|
if (relativePath == null || !uri.contains(relativePath)) {
|
||||||
}
|
String[] urlTokens = uri.split("/");
|
||||||
|
if (urlTokens.length < 4) {
|
||||||
|
throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
|
||||||
|
}
|
||||||
|
|
||||||
String webContext = urlTokens[3];
|
webContext = urlTokens[3];
|
||||||
|
} else {
|
||||||
|
URI parsedURI = URI.create(uri);
|
||||||
|
String path = parsedURI.getPath();
|
||||||
|
path = path.substring(0, path.indexOf(relativePath));
|
||||||
|
while (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
webContext = path;
|
||||||
|
if ("".equals(webContext)) {
|
||||||
|
path = relativePath;
|
||||||
|
while (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
if (path.contains("/")) {
|
||||||
|
path = path.substring(0, path.indexOf("/"));
|
||||||
|
}
|
||||||
|
webContext = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
KeycloakDeployment deployment = cache.get(webContext);
|
KeycloakDeployment deployment = cache.get(webContext);
|
||||||
if (null == deployment) {
|
if (null == deployment) {
|
||||||
|
@ -54,7 +77,8 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
|
||||||
keycloakConfig = karafEtc;
|
keycloakConfig = karafEtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
String absolutePath = keycloakConfig + File.separator + webContext + "-keycloak.json";
|
String absolutePath = keycloakConfig + File.separator + webContext + ("".equals(webContext) ? "" : "-")
|
||||||
|
+ "keycloak.json";
|
||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
try {
|
try {
|
||||||
is = new FileInputStream(absolutePath);
|
is = new FileInputStream(absolutePath);
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* 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 org.keycloak.adapters.osgi;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OIDCHttpFacade;
|
||||||
|
import org.keycloak.adapters.spi.AuthenticationError;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
|
import org.keycloak.adapters.spi.LogoutError;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
public class PathBasedKeycloakConfigResolverTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void relativeURIsAndContexts() throws Exception {
|
||||||
|
PathBasedKeycloakConfigResolver resolver = new PathBasedKeycloakConfigResolver();
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "test")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/a/b/c")));
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "test")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/a/b")));
|
||||||
|
|
||||||
|
// means default context and actually we use first segment
|
||||||
|
assertNotNull(populate(resolver, "test")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/test/a/b/c")));
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "test/a")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/b/c")));
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "")
|
||||||
|
.resolve(new MockRequest("http://localhost/", "/")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private PathBasedKeycloakConfigResolver populate(PathBasedKeycloakConfigResolver resolver, String context)
|
||||||
|
throws Exception {
|
||||||
|
Field f = PathBasedKeycloakConfigResolver.class.getDeclaredField("cache");
|
||||||
|
f.setAccessible(true);
|
||||||
|
Map<String, KeycloakDeployment> cache = (Map<String, KeycloakDeployment>) f.get(resolver);
|
||||||
|
cache.clear();
|
||||||
|
cache.put(context, new KeycloakDeployment());
|
||||||
|
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MockRequest implements OIDCHttpFacade.Request {
|
||||||
|
|
||||||
|
private String uri;
|
||||||
|
private String relativePath;
|
||||||
|
|
||||||
|
public MockRequest(String uri, String relativePath) {
|
||||||
|
this.uri = uri;
|
||||||
|
this.relativePath = relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMethod() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getURI() {
|
||||||
|
return this.uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRelativePath() {
|
||||||
|
return this.relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSecure() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFirstParam(String param) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getQueryParamValue(String param) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpFacade.Cookie getCookie(String cookieName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHeader(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getHeaders(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream(boolean buffered) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteAddr() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setError(AuthenticationError error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setError(LogoutError error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue