keycloak-aplcache
Changes
examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java 21(+16 -5)
Details
diff --git a/core/src/main/java/org/keycloak/AbstractOAuthClient.java b/core/src/main/java/org/keycloak/AbstractOAuthClient.java
index 600dab0..00fa0ed 100755
--- a/core/src/main/java/org/keycloak/AbstractOAuthClient.java
+++ b/core/src/main/java/org/keycloak/AbstractOAuthClient.java
@@ -1,5 +1,6 @@
package org.keycloak;
+import org.keycloak.enums.RelativeUrlsUsed;
import org.keycloak.util.KeycloakUriBuilder;
import java.util.Map;
@@ -19,7 +20,7 @@ public class AbstractOAuthClient {
protected String authUrl;
protected String codeUrl;
protected String refreshUrl;
- protected boolean relativeUrls;
+ protected RelativeUrlsUsed relativeUrlsUsed;
protected String scope;
protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
protected String stateCookiePath;
@@ -101,12 +102,12 @@ public class AbstractOAuthClient {
this.publicClient = publicClient;
}
- public boolean isRelativeUrls() {
- return relativeUrls;
+ public RelativeUrlsUsed getRelativeUrlsUsed() {
+ return relativeUrlsUsed;
}
- public void setRelativeUrls(boolean relativeUrls) {
- this.relativeUrls = relativeUrls;
+ public void setRelativeUrlsUsed(RelativeUrlsUsed relativeUrlsUsed) {
+ this.relativeUrlsUsed = relativeUrlsUsed;
}
protected String stripOauthParametersFromRedirect(String uri) {
diff --git a/core/src/main/java/org/keycloak/enums/RelativeUrlsUsed.java b/core/src/main/java/org/keycloak/enums/RelativeUrlsUsed.java
new file mode 100644
index 0000000..333986a
--- /dev/null
+++ b/core/src/main/java/org/keycloak/enums/RelativeUrlsUsed.java
@@ -0,0 +1,36 @@
+package org.keycloak.enums;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public enum RelativeUrlsUsed {
+
+ /**
+ * Always use relative URI and resolve them later based on browser HTTP request
+ */
+ ALL_REQUESTS,
+
+ /**
+ * Use relative Uris just for browser requests and resolve those based on browser HTTP requests.
+ * Backend request (like refresh token request, codeToToken request etc) will use the URI based on current hostname
+ */
+ BROWSER_ONLY,
+
+ /**
+ * Relative Uri not used. Configuration contains absolute URI
+ */
+ NEVER;
+
+ public boolean useRelative(boolean browserReq) {
+ switch (this) {
+ case ALL_REQUESTS:
+ return true;
+ case NEVER:
+ return false;
+ case BROWSER_ONLY:
+ return browserReq;
+ default:
+ return true;
+ }
+ }
+}
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
index 39552b2..acb4243 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
@@ -16,7 +16,8 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder;
"expose-token", "bearer-only",
"connection-pool-size",
"allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
- "client-keystore", "client-keystore-password", "client-key-password"
+ "client-keystore", "client-keystore-password", "client-key-password",
+ "use-hostname-for-local-requests", "local-requests-scheme", "local-requests-port"
})
public class AdapterConfig extends BaseAdapterConfig {
@@ -36,6 +37,12 @@ public class AdapterConfig extends BaseAdapterConfig {
protected String clientKeyPassword;
@JsonProperty("connection-pool-size")
protected int connectionPoolSize = 20;
+ @JsonProperty("use-hostname-for-local-requests")
+ protected boolean useHostnameForLocalRequests;
+ @JsonProperty("local-requests-scheme")
+ protected String localRequestsScheme = "http";
+ @JsonProperty("local-requests-port")
+ protected int localRequestsPort = 8080;
public boolean isAllowAnyHostname() {
return allowAnyHostname;
@@ -101,4 +108,27 @@ public class AdapterConfig extends BaseAdapterConfig {
this.connectionPoolSize = connectionPoolSize;
}
+ public boolean isUseHostnameForLocalRequests() {
+ return useHostnameForLocalRequests;
+ }
+
+ public void setUseHostnameForLocalRequests(boolean useHostnameForLocalRequests) {
+ this.useHostnameForLocalRequests = useHostnameForLocalRequests;
+ }
+
+ public String getLocalRequestsScheme() {
+ return localRequestsScheme;
+ }
+
+ public void setLocalRequestsScheme(String localRequestsScheme) {
+ this.localRequestsScheme = localRequestsScheme;
+ }
+
+ public int getLocalRequestsPort() {
+ return localRequestsPort;
+ }
+
+ public void setLocalRequestsPort(int localRequestsPort) {
+ this.localRequestsPort = localRequestsPort;
+ }
}
diff --git a/core/src/main/java/org/keycloak/util/UriUtils.java b/core/src/main/java/org/keycloak/util/UriUtils.java
index 873283f..5f13756 100644
--- a/core/src/main/java/org/keycloak/util/UriUtils.java
+++ b/core/src/main/java/org/keycloak/util/UriUtils.java
@@ -1,6 +1,8 @@
package org.keycloak.util;
+import java.net.InetAddress;
import java.net.URI;
+import java.net.UnknownHostException;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -16,4 +18,28 @@ public class UriUtils {
return u.substring(0, u.indexOf('/', 8));
}
+ /**
+ * Get origin based on current hostname
+ *
+ * @param scheme
+ * @param port
+ * @return Address like "http://myHost:8080"
+ */
+ public static String getLocalOrigin(String scheme, Integer port) {
+ String hostname = getHostName();
+ StringBuilder sb = new StringBuilder(scheme + "://" + hostname);
+ if (port != null && port != -1) {
+ sb.append(":").append(port);
+ }
+ return sb.toString();
+ }
+
+ public static String getHostName() {
+ try {
+ return InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException uhe) {
+ throw new IllegalStateException(uhe);
+ }
+ }
+
}
diff --git a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
index d9377c9..a12bcee 100755
--- a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
+++ b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
@@ -5,9 +5,11 @@ import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.keycloak.adapters.ServerRequest;
+import org.keycloak.enums.RelativeUrlsUsed;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.servlet.ServletOAuthClient;
import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.UriUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -58,7 +60,6 @@ public class ProductDatabaseClient {
// and obtain the ServletOAuthClient. I actually suggest downloading the ServletOAuthClient code
// and take a look how it works. You can also take a look at third-party-cdi example
ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
- String token = null;
try {
return oAuthClient.getBearerToken(request);
} catch (IOException e) {
@@ -78,7 +79,7 @@ public class ProductDatabaseClient {
ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
HttpClient client = oAuthClient.getClient();
- HttpGet get = new HttpGet(getBaseUrl(request) + "/database/products");
+ HttpGet get = new HttpGet(getBaseUrl(oAuthClient, request) + "/database/products");
get.addHeader("Authorization", "Bearer " + accessToken);
try {
HttpResponse response = client.execute(get);
@@ -97,9 +98,19 @@ public class ProductDatabaseClient {
}
}
- public static String getBaseUrl(HttpServletRequest request) {
- String url = request.getRequestURL().toString();
- return url.substring(0, url.indexOf('/', 8));
+ public static String getBaseUrl(ServletOAuthClient oAuthClient, HttpServletRequest request) {
+ switch (oAuthClient.getRelativeUrlsUsed()) {
+ case ALL_REQUESTS:
+ // Resolve baseURI from the request
+ return UriUtils.getOrigin(request.getRequestURL().toString());
+ case BROWSER_ONLY:
+ // Resolve baseURI from the codeURL (This is already non-relative and based on our hostname)
+ return UriUtils.getOrigin(oAuthClient.getCodeUrl());
+ case NEVER:
+ return "";
+ default:
+ return "";
+ }
}
}
diff --git a/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json
index 559df05..14bbd79 100755
--- a/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json
@@ -5,5 +5,6 @@
"ssl-required" : "external",
"credentials" : {
"secret": "password"
- }
+ },
+ "use-hostname-for-local-requests": false
}
\ No newline at end of file
diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
index 34e8035..9413d61 100755
--- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
+++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
@@ -40,7 +40,7 @@ public class ServletOAuthClient extends AbstractOAuthClient {
}
private AccessTokenResponse resolveBearerToken(HttpServletRequest request, String redirectUri, String code) throws IOException, ServerRequest.HttpFailure {
- return ServerRequest.invokeAccessCodeToToken(client, publicClient, code, getUrl(request, codeUrl), redirectUri, clientId, credentials);
+ return ServerRequest.invokeAccessCodeToToken(client, publicClient, code, getUrl(request, codeUrl, false), redirectUri, clientId, credentials);
}
/**
@@ -74,7 +74,7 @@ public class ServletOAuthClient extends AbstractOAuthClient {
public void redirect(String redirectUri, HttpServletRequest request, HttpServletResponse response) throws IOException {
String state = getStateCode();
- KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(getUrl(request, authUrl))
+ KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(getUrl(request, authUrl, true))
.queryParam(OAuth2Constants.CLIENT_ID, clientId)
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
.queryParam(OAuth2Constants.STATE, state);
@@ -146,7 +146,7 @@ public class ServletOAuthClient extends AbstractOAuthClient {
}
public AccessTokenResponse refreshToken(HttpServletRequest request, String refreshToken) throws IOException, ServerRequest.HttpFailure {
- return ServerRequest.invokeRefresh(client, publicClient, refreshToken, getUrl(request, refreshUrl), clientId, credentials);
+ return ServerRequest.invokeRefresh(client, publicClient, refreshToken, getUrl(request, refreshUrl, false), clientId, credentials);
}
public static IDToken extractIdToken(String idToken) {
@@ -159,8 +159,8 @@ public class ServletOAuthClient extends AbstractOAuthClient {
}
}
- private String getUrl(HttpServletRequest request, String url) {
- if (relativeUrls) {
+ private String getUrl(HttpServletRequest request, String url, boolean isBrowserRequest) {
+ if (relativeUrlsUsed.useRelative(isBrowserRequest)) {
String baseUrl = request.getRequestURL().toString();
baseUrl = baseUrl.substring(0, baseUrl.indexOf('/', 8));
return baseUrl + url;
diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java
index 52d9710..e1ccd5d 100755
--- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java
+++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java
@@ -3,9 +3,11 @@ package org.keycloak.servlet;
import org.apache.http.client.HttpClient;
import org.keycloak.ServiceUrlConstants;
import org.keycloak.adapters.HttpClientBuilder;
+import org.keycloak.enums.RelativeUrlsUsed;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.KeycloakUriBuilder;
+import org.keycloak.util.UriUtils;
import java.io.IOException;
import java.io.InputStream;
@@ -21,7 +23,7 @@ public class ServletOAuthClientBuilder {
return build(adapterConfig);
}
- private static AdapterConfig getAdapterConfig(InputStream is) {
+ public static AdapterConfig getAdapterConfig(InputStream is) {
try {
return JsonSerialization.readValue(is, AdapterConfig.class);
} catch (IOException e) {
@@ -50,13 +52,31 @@ public class ServletOAuthClientBuilder {
throw new RuntimeException("You must specify auth-url");
}
KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrl());
- oauthClient.setRelativeUrls(serverBuilder.clone().getHost() == null);
+ RelativeUrlsUsed useRelative = relativeUrls(serverBuilder, adapterConfig);
+ oauthClient.setRelativeUrlsUsed(useRelative);
String authUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGIN_PATH).build(adapterConfig.getRealm()).toString();
- String tokenUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_ACCESS_CODE_PATH).build(adapterConfig.getRealm()).toString();
- String refreshUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_REFRESH_PATH).build(adapterConfig.getRealm()).toString();
+
+ KeycloakUriBuilder tokenUrlBuilder = serverBuilder.clone();
+ KeycloakUriBuilder refreshUrlBuilder = serverBuilder.clone();
+
+ if (useRelative == RelativeUrlsUsed.BROWSER_ONLY) {
+ // Use absolute URI for refreshToken and codeToToken requests
+ tokenUrlBuilder.scheme(adapterConfig.getLocalRequestsScheme()).host(UriUtils.getHostName()).port(adapterConfig.getLocalRequestsPort());
+ refreshUrlBuilder.scheme(adapterConfig.getLocalRequestsScheme()).host(UriUtils.getHostName()).port(adapterConfig.getLocalRequestsPort());
+ }
+ String tokenUrl = tokenUrlBuilder.path(ServiceUrlConstants.TOKEN_SERVICE_ACCESS_CODE_PATH).build(adapterConfig.getRealm()).toString();
+ String refreshUrl = refreshUrlBuilder.path(ServiceUrlConstants.TOKEN_SERVICE_REFRESH_PATH).build(adapterConfig.getRealm()).toString();
oauthClient.setAuthUrl(authUrl);
oauthClient.setCodeUrl(tokenUrl);
oauthClient.setRefreshUrl(refreshUrl);
}
+
+ private static RelativeUrlsUsed relativeUrls(KeycloakUriBuilder serverBuilder, AdapterConfig adapterConfig) {
+ if (serverBuilder.clone().getHost() == null) {
+ return (adapterConfig.isUseHostnameForLocalRequests()) ? RelativeUrlsUsed.BROWSER_ONLY : RelativeUrlsUsed.ALL_REQUESTS;
+ } else {
+ return RelativeUrlsUsed.NEVER;
+ }
+ }
}