You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by jb...@apache.org on 2016/01/07 11:39:21 UTC
[2/4] cxf-fediz git commit: [FEDIZ-143] Home Realm Discovery based on
OIDC login_hint
[FEDIZ-143] Home Realm Discovery based on OIDC login_hint
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/24af6222
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/24af6222
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/24af6222
Branch: refs/heads/master
Commit: 24af6222343223faffa2b00646a49e182604da6d
Parents: ecb9ce6
Author: Jan Bernhardt <jb...@talend.com>
Authored: Wed Jan 6 17:08:10 2016 +0100
Committer: Jan Bernhardt <jb...@talend.com>
Committed: Thu Jan 7 11:13:34 2016 +0100
----------------------------------------------------------------------
.../apache/cxf/fediz/core/config/Protocol.java | 30 ++++++---
.../core/processor/FederationProcessorImpl.java | 39 +++++++++---
.../service/oidc/HomeRealmCallbackHandler.java | 64 -------------------
.../handler/hrd/ClientIdHomeRealmDiscovery.java | 67 ++++++++++++++++++++
.../hrd/LoginHintHomeRealmDiscovery.java | 64 +++++++++++++++++++
5 files changed, 182 insertions(+), 82 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/24af6222/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java
index 7468e76..f72a574 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java
@@ -170,18 +170,28 @@ public abstract class Protocol {
if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
return new String(cbt.getValue());
} else if (cbt.getType().equals(ArgumentType.CLASS)) {
- try {
- if (getClassloader() == null) {
- return ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
- } else {
- return getClassloader().loadClass(cbt.getValue()).newInstance();
+ List<Object> handler = new ArrayList<Object>();
+ String[] cbtHandler = cbt.getValue().split(",");
+ for (String cbh : cbtHandler) {
+ try {
+ if (getClassloader() == null) {
+ handler.add(ClassLoaderUtils.loadClass(cbh, this.getClass()).newInstance());
+ } else {
+ handler.add(getClassloader().loadClass(cbh).newInstance());
+ }
+ } catch (Exception e) {
+ LOG.error("Failed to create instance of " + cbh, e);
+ //throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
}
- } catch (Exception e) {
- LOG.error("Failed to create instance of " + cbt.getValue(), e);
- throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
- }
+ }
+ if (handler.size() == 1) {
+ // Backward compatible return handler directly if only one is configured
+ return handler.get(0);
+ } else {
+ return handler;
+ }
} else {
- LOG.error("Only String and Class are supported for '" + name + "'");
+ LOG.error("Only String and Class are supported for '{}'", name);
throw new IllegalStateException("Only String and Class are supported for '" + name + "'");
}
}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/24af6222/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
index d74dfe6..be25b09 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
@@ -548,27 +548,50 @@ public class FederationProcessorImpl extends AbstractFedizProcessor {
return freshness;
}
- private String resolveHomeRealm(HttpServletRequest request, FedizContext config) throws IOException,
- UnsupportedCallbackException {
+ private String resolveHomeRealm(HttpServletRequest request, FedizContext config) {
// Check if whr parameter was provided in request
String homeRealm = request.getParameter(FederationConstants.PARAM_HOME_REALM);
-
- if (homeRealm == null || homeRealm.isEmpty()) {
+
+ if (homeRealm != null && !homeRealm.isEmpty()) {
+ LOG.debug("HomeRealm was defined as 'whr' request parameter and will be used for IDP redirect");
+ } else {
// Check if home realm is set in configuration
Object homeRealmObj = ((FederationProtocol)config.getProtocol()).getHomeRealm();
if (homeRealmObj != null) {
if (homeRealmObj instanceof String) {
homeRealm = (String)homeRealmObj;
} else if (homeRealmObj instanceof CallbackHandler) {
- CallbackHandler hrCB = (CallbackHandler)homeRealmObj;
- HomeRealmCallback callback = new HomeRealmCallback(request);
- hrCB.handle(new Callback[] {callback});
- homeRealm = callback.getHomeRealm();
+ homeRealm = resolveHomeRealm(homeRealmObj, request);
+ } else if (homeRealmObj instanceof List<?>) {
+ for (Object cbh : (List<?>)homeRealmObj) {
+ homeRealm = resolveHomeRealm(cbh, request);
+ if (homeRealm != null) {
+ LOG.debug("Home realm was found by {}", cbh.getClass());
+ break;
+ }
+ }
}
}
}
+ LOG.debug("Users home realm will be set to {}", homeRealm);
return homeRealm;
}
+
+ private String resolveHomeRealm(Object cbh, HttpServletRequest request) {
+ if (cbh instanceof CallbackHandler) {
+ CallbackHandler hrCBH = (CallbackHandler)cbh;
+ HomeRealmCallback callback = new HomeRealmCallback(request);
+ try {
+ hrCBH.handle(new Callback[] {callback});
+ } catch (IOException | UnsupportedCallbackException e) {
+ LOG.warn("Home Realm Callbackhandler caused an exception", e);
+ }
+ return callback.getHomeRealm();
+ } else {
+ LOG.warn("Callback Handler was not an instanceof CallbackHandler: {}", cbh);
+ return null;
+ }
+ }
private String resolveAuthenticationType(HttpServletRequest request, FedizContext config) throws IOException,
UnsupportedCallbackException {
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/24af6222/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/HomeRealmCallbackHandler.java
----------------------------------------------------------------------
diff --git a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/HomeRealmCallbackHandler.java b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/HomeRealmCallbackHandler.java
deleted file mode 100644
index 673d261..0000000
--- a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/HomeRealmCallbackHandler.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.cxf.fediz.service.oidc;
-
-import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.cxf.fediz.core.spi.HomeRealmCallback;
-import org.apache.cxf.rs.security.oauth2.common.Client;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-
-public class HomeRealmCallbackHandler implements CallbackHandler {
-
- private static final Logger LOG = LoggerFactory.getLogger(HomeRealmCallbackHandler.class);
-
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (int i = 0; i < callbacks.length; i++) {
- if (callbacks[i] instanceof HomeRealmCallback) {
- HomeRealmCallback callback = (HomeRealmCallback) callbacks[i];
-
- HttpServletRequest request = callback.getRequest();
- String clientId = request.getParameter("client_id");
-
- if (clientId != null) {
- ApplicationContext ctx = ApplicationContextProvider.getApplicationContext();
- OAuthDataManager dataManager = (OAuthDataManager)ctx.getBean("oauthProvider");
-
- Client client = dataManager.getClient(clientId);
- if (client instanceof FedizClient) {
- callback.setHomeRealm(((FedizClient)client).getHomeRealm());
- LOG.debug("Retrieved home realm {}", callback.getHomeRealm());
- }
- }
-
- } else {
- throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
- }
- }
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/24af6222/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/ClientIdHomeRealmDiscovery.java
----------------------------------------------------------------------
diff --git a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/ClientIdHomeRealmDiscovery.java b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/ClientIdHomeRealmDiscovery.java
new file mode 100644
index 0000000..28c7734
--- /dev/null
+++ b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/ClientIdHomeRealmDiscovery.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.oidc.handler.hrd;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.cxf.fediz.core.spi.HomeRealmCallback;
+import org.apache.cxf.fediz.service.oidc.ApplicationContextProvider;
+import org.apache.cxf.fediz.service.oidc.FedizClient;
+import org.apache.cxf.fediz.service.oidc.OAuthDataManager;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+
+public class ClientIdHomeRealmDiscovery implements CallbackHandler {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ClientIdHomeRealmDiscovery.class);
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof HomeRealmCallback) {
+ HomeRealmCallback callback = (HomeRealmCallback) callbacks[i];
+
+ HttpServletRequest request = callback.getRequest();
+ String clientId = request.getParameter("client_id");
+
+ if (clientId != null) {
+ ApplicationContext ctx = ApplicationContextProvider.getApplicationContext();
+ OAuthDataManager dataManager = (OAuthDataManager)ctx.getBean("oauthProvider");
+
+ Client client = dataManager.getClient(clientId);
+ if (client instanceof FedizClient) {
+ callback.setHomeRealm(((FedizClient)client).getHomeRealm());
+ LOG.debug("Retrieved home realm {}", callback.getHomeRealm());
+ }
+ }
+
+ } else {
+ LOG.warn("Callback is not an inctance of HomeRealmCallback: {}", callbacks[i]);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/24af6222/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/LoginHintHomeRealmDiscovery.java
----------------------------------------------------------------------
diff --git a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/LoginHintHomeRealmDiscovery.java b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/LoginHintHomeRealmDiscovery.java
new file mode 100644
index 0000000..9f91b63
--- /dev/null
+++ b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/handler/hrd/LoginHintHomeRealmDiscovery.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.oidc.handler.hrd;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.cxf.fediz.core.spi.HomeRealmCallback;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This callback handler uses the login_hint parameter defined in OpenID Connect to discover the users home realm.
+ *
+ * It is expected that the login_hint will contain the users email address and that the domain name from the mail
+ * address will be equal to the home realm identifier.
+ */
+public class LoginHintHomeRealmDiscovery implements CallbackHandler {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LoginHintHomeRealmDiscovery.class);
+
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof HomeRealmCallback) {
+ HomeRealmCallback callback = (HomeRealmCallback) callbacks[i];
+ String loginHint = (String)callback.getRequest().getParameter("login_hint");
+ if (loginHint == null || loginHint.length() == 0) {
+ LOG.debug("No login_hint found in request to set home realm");
+ } else {
+ String[] homeRealm = loginHint.split("@");
+ if (homeRealm.length == 2) {
+ LOG.debug("Home realm '{}' found in request", homeRealm[1]);
+ callback.setHomeRealm(homeRealm[1]);
+ } else {
+ LOG.warn("login_hint is not an email address: {}", loginHint);
+ }
+ }
+ } else {
+ LOG.warn("Callback is not an inctance of HomeRealmCallback: {}", callbacks[i]);
+ }
+ }
+ }
+
+}
\ No newline at end of file