Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BC0A211BF9 for ; Thu, 19 Jun 2014 16:30:59 +0000 (UTC) Received: (qmail 79402 invoked by uid 500); 19 Jun 2014 16:30:59 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 79248 invoked by uid 500); 19 Jun 2014 16:30:59 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 79051 invoked by uid 99); 19 Jun 2014 16:30:59 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 19 Jun 2014 16:30:59 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id F0CFB983F86; Thu, 19 Jun 2014 16:30:58 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: coheigea@apache.org To: commits@cxf.apache.org Date: Thu, 19 Jun 2014 16:31:00 -0000 Message-Id: <04df92086d5f4eb4ac8a66554a038052@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/4] [FEDIZ-7] - Largish refactor of Fediz code to accomadate other protocols http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java new file mode 100644 index 0000000..2eae858 --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java @@ -0,0 +1,397 @@ +/** + * 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.core.config; + +import java.io.BufferedInputStream; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.cxf.fediz.core.config.jaxb.CertificateStores; +import org.apache.cxf.fediz.core.config.jaxb.ContextConfig; +import org.apache.cxf.fediz.core.config.jaxb.FederationProtocolType; +import org.apache.cxf.fediz.core.config.jaxb.KeyManagersType; +import org.apache.cxf.fediz.core.config.jaxb.KeyStoreType; +import org.apache.cxf.fediz.core.config.jaxb.ProtocolType; +import org.apache.cxf.fediz.core.config.jaxb.SamlProtocolType; +import org.apache.cxf.fediz.core.config.jaxb.TrustManagersType; +import org.apache.cxf.fediz.core.config.jaxb.TrustedIssuerType; +import org.apache.cxf.fediz.core.config.jaxb.TrustedIssuers; +import org.apache.cxf.fediz.core.exception.IllegalConfigurationException; +import org.apache.wss4j.common.cache.ReplayCache; +import org.apache.wss4j.common.cache.ReplayCacheFactory; +import org.apache.wss4j.common.crypto.CertificateStore; +import org.apache.wss4j.common.crypto.Crypto; +import org.apache.wss4j.common.crypto.CryptoFactory; +import org.apache.wss4j.common.crypto.Merlin; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.util.Loader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FedizContext implements Closeable { + + public static final String CACHE_KEY_PREFIX = "fediz.replay.cache"; + + private static final Logger LOG = LoggerFactory.getLogger(FedizContext.class); + + private ContextConfig config; + + private boolean detectExpiredTokens = true; + private boolean detectReplayedTokens = true; + private String relativePath; + private ReplayCache replayCache; + private Protocol protocol; + private List certificateStores; + private KeyManager keyManager; + private KeyManager decryptionKeyManager; + private ClassLoader classloader; + + + public FedizContext(ContextConfig config) { + this.config = config; + + } + + public void init() { + //get validators initialized + getProtocol(); + } + + public List getAudienceUris() { + return config.getAudienceUris().getAudienceItem(); + } + + public List getTrustedIssuers() { + TrustedIssuers issuers = config.getTrustedIssuers(); + List trustManagers = issuers.getIssuer(); + List trustedIssuers = new ArrayList(); + for (TrustedIssuerType manager:trustManagers) { + trustedIssuers.add(new TrustedIssuer(manager)); + } + return trustedIssuers; + } + + public List getCertificateStores() { + if (certificateStores != null) { + return certificateStores; + } + certificateStores = new ArrayList(); + CertificateStores certStores = config.getCertificateStores(); + List trustManagers = certStores.getTrustManager(); + for (TrustManagersType manager:trustManagers) { + TrustManager tm = new TrustManager(manager); + + Crypto crypto = null; + try { + if (manager.getKeyStore().getType().equalsIgnoreCase("PEM")) { + X509Certificate[] certificates = new X509Certificate[1]; + certificates[0] = readX509Certificate(tm.getName()); + crypto = new CertificateStore(certificates); + } else { + Properties sigProperties = createCryptoProperties(manager); + crypto = CryptoFactory.getInstance(sigProperties); + } + tm.setCrypto(crypto); + certificateStores.add(tm); + } catch (WSSecurityException e) { + LOG.error("Failed to load keystore '" + tm.getName() + "'", e); + throw new IllegalConfigurationException("Failed to load keystore '" + tm.getName() + "'"); + } + } + return certificateStores; + } + + public BigInteger getMaximumClockSkew() { + if (config.getMaximumClockSkew() == null) { + return BigInteger.valueOf(5L); + } else { + return config.getMaximumClockSkew(); + } + } + + public void setMaximumClockSkew(BigInteger maximumClockSkew) { + config.setMaximumClockSkew(maximumClockSkew); + } + + // public TrustManager getServiceCertificate() { + // return new TrustManager(config.getServiceCertificate()); + // } + + public Protocol getProtocol() { + if (protocol != null) { + return protocol; + } + ProtocolType type = config.getProtocol(); + if (type instanceof FederationProtocolType) { + protocol = new FederationProtocol(type); + } else if (type instanceof SamlProtocolType) { + protocol = new SAMLProtocol(type); + } + + if (protocol != null) { + protocol.setClassloader(getClassloader()); + } + return protocol; + } + + public String getLogoutURL() { + return config.getLogoutURL(); + } + + public String getLogoutRedirectTo() { + return config.getLogoutRedirectTo(); + } + + + public KeyManager getSigningKey() { + //return new KeyManager(config.getSigningKey()); + + if (keyManager != null) { + return keyManager; + } + keyManager = new KeyManager(config.getSigningKey()); + Properties sigProperties = createCryptoProperties(config.getSigningKey()); + Crypto crypto; + try { + crypto = CryptoFactory.getInstance(sigProperties); + keyManager.setCrypto(crypto); + } catch (WSSecurityException e) { + keyManager = null; + LOG.error("Failed to load keystore '" + keyManager.getName() + "'", e); + throw new IllegalConfigurationException("Failed to load keystore '" + keyManager.getName() + "'"); + } + + return keyManager; + + } + + public KeyManager getDecryptionKey() { + if (decryptionKeyManager != null) { + return decryptionKeyManager; + } + decryptionKeyManager = new KeyManager(config.getTokenDecryptionKey()); + Properties decProperties = createCryptoProperties(config.getTokenDecryptionKey()); + Crypto crypto; + try { + crypto = CryptoFactory.getInstance(decProperties); + decryptionKeyManager.setCrypto(crypto); + } catch (WSSecurityException e) { + decryptionKeyManager = null; + LOG.error("Failed to load keystore '" + decryptionKeyManager.getName() + "'", e); + throw new IllegalConfigurationException("Failed to load keystore '" + decryptionKeyManager.getName() + "'"); + } + + return decryptionKeyManager; + + } + + public ReplayCache getTokenReplayCache() { + if (replayCache != null) { + return replayCache; + } + String replayCacheString = config.getTokenReplayCache(); + String cacheKey = CACHE_KEY_PREFIX + "-" + config.getName(); + ReplayCacheFactory replayCacheFactory = ReplayCacheFactory.newInstance(); + if (replayCacheString == null || "".equals(replayCacheString)) { + replayCache = replayCacheFactory.newReplayCache(cacheKey, "fediz-ehcache.xml"); + } else { + try { + Class replayCacheClass = Loader.loadClass(replayCacheString); + replayCache = (ReplayCache) replayCacheClass.newInstance(); + } catch (ClassNotFoundException e) { + replayCache = replayCacheFactory.newReplayCache(cacheKey, "fediz-ehcache.xml"); + } catch (InstantiationException e) { + replayCache = replayCacheFactory.newReplayCache(cacheKey, "fediz-ehcache.xml"); + } catch (IllegalAccessException e) { + replayCache = replayCacheFactory.newReplayCache(cacheKey, "fediz-ehcache.xml"); + } + } + return replayCache; + } + + public String getName() { + return config.getName(); + } + + + public boolean isDetectExpiredTokens() { + return detectExpiredTokens; + } + + public void setDetectExpiredTokens(boolean detectExpiredTokens) { + this.detectExpiredTokens = detectExpiredTokens; + } + + + public boolean isDetectReplayedTokens() { + return detectReplayedTokens; + } + + public void setDetectReplayedTokens(boolean detectReplayedTokens) { + this.detectReplayedTokens = detectReplayedTokens; + } + + public void setRelativePath(String relativePath) { + this.relativePath = relativePath; + } + + public String getRelativePath() { + return relativePath; + } + + @Override + public void close() throws IOException { + if (replayCache != null) { + replayCache.close(); + } + } + + private Properties createCryptoProperties(TrustManagersType tm) { + String trustStoreFile = null; + String trustStorePw = null; + KeyStoreType ks = tm.getKeyStore(); + if (ks.getFile() != null && !ks.getFile().isEmpty()) { + trustStoreFile = ks.getFile(); + trustStorePw = ks.getPassword(); + } else { + throw new IllegalStateException("No certificate store configured"); + } + File f = new File(trustStoreFile); + if (!f.exists() && getRelativePath() != null && !getRelativePath().isEmpty()) { + trustStoreFile = getRelativePath().concat(File.separator + trustStoreFile); + } + + if (trustStoreFile == null || trustStoreFile.isEmpty()) { + throw new IllegalConfigurationException("truststoreFile not configured"); + } + if (trustStorePw == null || trustStorePw.isEmpty()) { + throw new IllegalConfigurationException("trustStorePw not configured"); + } + Properties p = new Properties(); + p.put("org.apache.ws.security.crypto.provider", + "org.apache.ws.security.components.crypto.Merlin"); + p.put("org.apache.ws.security.crypto.merlin.keystore.type", "jks"); + p.put("org.apache.ws.security.crypto.merlin.keystore.password", + trustStorePw); + p.put("org.apache.ws.security.crypto.merlin.keystore.file", + trustStoreFile); + return p; + } + + private Properties createCryptoProperties(KeyManagersType km) { + String keyStoreFile = null; + String keyStorePw = null; + String keyType = "jks"; + KeyStoreType ks = km.getKeyStore(); + if (ks.getFile() != null && !ks.getFile().isEmpty()) { + keyStoreFile = ks.getFile(); + keyStorePw = ks.getPassword(); + } else { + throw new IllegalStateException("No certificate store configured"); + } + File f = new File(keyStoreFile); + if (!f.exists() && getRelativePath() != null && !getRelativePath().isEmpty()) { + keyStoreFile = getRelativePath().concat(File.separator + keyStoreFile); + } + + if (keyStoreFile == null || keyStoreFile.isEmpty()) { + throw new IllegalConfigurationException("truststoreFile not configured"); + } + if (keyStorePw == null || keyStorePw.isEmpty()) { + throw new IllegalConfigurationException("trustStorePw not configured"); + } + if (ks.getType() != null) { + keyType = ks.getType(); + } + + Properties p = new Properties(); + p.put("org.apache.ws.security.crypto.provider", + "org.apache.ws.security.components.crypto.Merlin"); + p.put("org.apache.ws.security.crypto.merlin.keystore.type", keyType); + p.put("org.apache.ws.security.crypto.merlin.keystore.password", + keyStorePw); + p.put("org.apache.ws.security.crypto.merlin.keystore.file", + keyStoreFile); + return p; + } + + private X509Certificate readX509Certificate(String filename) { + Certificate cert = null; + BufferedInputStream bis = null; + try { + ClassLoader cl = getClassloader(); + if (cl == null) { + cl = Thread.currentThread().getContextClassLoader(); + } + InputStream is = Merlin.loadInputStream(cl, filename); + + bis = new BufferedInputStream(is); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + if (bis.available() > 0) { + cert = cf.generateCertificate(bis); + if (!(cert instanceof X509Certificate)) { + LOG.error("Certificate " + filename + " is not of type X509Certificate"); + throw new IllegalConfigurationException("Certificate " + + filename + " is not of type X509Certificate"); + } + if (bis.available() > 0) { + LOG.warn("There are more certificates configured in " + filename + ". Only first is parsed"); + } + return (X509Certificate)cert; + } else { + LOG.error("No bytes can be read in certificate file " + filename); + throw new IllegalConfigurationException("No bytes can be read in certificate file " + filename); + } + } catch (IllegalConfigurationException ex) { + throw ex; + } catch (Exception ex) { + LOG.error("Failed to read certificate file " + filename, ex); + throw new IllegalConfigurationException("Failed to read certificate file " + filename, ex); + } finally { + try { + bis.close(); + } catch (IOException ex) { + LOG.error("Failed to close certificate file " + filename, ex); + } + } + } + + public ClassLoader getClassloader() { + return classloader; + } + + public void setClassloader(ClassLoader classloader) { + this.classloader = classloader; + } + + + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/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 75577c9..1683e6e 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 @@ -19,10 +19,21 @@ package org.apache.cxf.fediz.core.config; +import javax.security.auth.callback.CallbackHandler; + +import org.apache.cxf.fediz.core.config.jaxb.ArgumentType; +import org.apache.cxf.fediz.core.config.jaxb.CallbackType; import org.apache.cxf.fediz.core.config.jaxb.ProtocolType; +import org.apache.cxf.fediz.core.util.ClassLoaderUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class Protocol { + private static final Logger LOG = LoggerFactory.getLogger(Protocol.class); + private ProtocolType protocolType; + private ClassLoader classloader; + private Object issuer; public Protocol(ProtocolType protocolType) { super(); @@ -49,6 +60,72 @@ public abstract class Protocol { return protocolType.toString(); } + public ClassLoader getClassloader() { + return classloader; + } + + public void setClassloader(ClassLoader classloader) { + this.classloader = classloader; + } + public String getRoleDelimiter() { + return getProtocolType().getRoleDelimiter(); + } + + public void setRoleDelimiter(String value) { + getProtocolType().setRoleDelimiter(value); + } + + public String getRoleURI() { + return getProtocolType().getRoleURI(); + } + + public void setRoleURI(String value) { + getProtocolType().setRoleURI(value); + } + + public Object getIssuer() { + if (this.issuer != null) { + return this.issuer; + } + CallbackType cbt = getProtocolType().getIssuer(); + this.issuer = loadCallbackType(cbt, "Issuer"); + return this.issuer; + } + + public void setIssuer(Object value) { + final boolean isString = value instanceof String; + final boolean isCallbackHandler = value instanceof CallbackHandler; + if (isString || isCallbackHandler) { + this.issuer = value; + } else { + LOG.error("Unsupported 'Issuer' object"); + throw new IllegalArgumentException("Unsupported 'Issuer' object. Type must be " + + "java.lang.String or javax.security.auth.callback.CallbackHandler."); + } + } + + protected Object loadCallbackType(CallbackType cbt, String name) { + if (cbt == null) { + return null; + } + 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(); + } + } catch (Exception e) { + LOG.error("Failed to create instance of " + cbt.getValue(), e); + throw new IllegalStateException("Failed to create instance of " + cbt.getValue()); + } + } else { + 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/08af52b6/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java new file mode 100644 index 0000000..b334537 --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java @@ -0,0 +1,61 @@ +/** + * 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.core.config; + +import org.apache.cxf.fediz.core.config.jaxb.ProtocolType; + +public class SAMLProtocol extends Protocol { + + // private static final Logger LOG = LoggerFactory.getLogger(SAMLProtocol.class); + + public SAMLProtocol(ProtocolType protocolType) { + super(protocolType); + + /*FederationProtocolType fp = (FederationProtocolType)protocolType; + if (fp.getTokenValidators() != null && fp.getTokenValidators().getValidator() != null) { + for (String validatorClassname : fp.getTokenValidators().getValidator()) { + Object obj = null; + try { + if (super.getClassloader() == null) { + obj = ClassLoaderUtils.loadClass(validatorClassname, this.getClass()).newInstance(); + } else { + obj = super.getClassloader().loadClass(validatorClassname).newInstance(); + } + } catch (Exception ex) { + LOG.error("Failed to instantiate TokenValidator implementation class: '" + + validatorClassname + "'\n" + ex.getClass().getCanonicalName() + ": " + ex.getMessage()); + } + if (obj instanceof TokenValidator) { + validators.add((TokenValidator)obj); + } else if (obj != null) { + LOG.error("Invalid TokenValidator implementation class: '" + validatorClassname + "'"); + } + } + }*/ + + // add SAMLTokenValidator as the last one + // Fediz chooses the first validator in the list if its + // canHandleToken or canHandleTokenType method return true + //SAMLTokenValidator validator = new SAMLTokenValidator(); + //validators.add(validators.size(), validator); + } + + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/plugins/core/src/main/java/org/apache/cxf/fediz/core/metadata/MetadataWriter.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/metadata/MetadataWriter.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/metadata/MetadataWriter.java index 9ef969c..c3c97ed 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/metadata/MetadataWriter.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/metadata/MetadataWriter.java @@ -34,8 +34,8 @@ import javax.xml.stream.XMLStreamWriter; import org.w3c.dom.Document; import org.apache.cxf.fediz.core.config.Claim; -import org.apache.cxf.fediz.core.config.FederationContext; import org.apache.cxf.fediz.core.config.FederationProtocol; +import org.apache.cxf.fediz.core.config.FedizContext; import org.apache.cxf.fediz.core.config.Protocol; import org.apache.cxf.fediz.core.exception.ProcessingException; import org.apache.cxf.fediz.core.util.DOMUtils; @@ -61,7 +61,7 @@ public class MetadataWriter { } //CHECKSTYLE:OFF - public Document getMetaData(FederationContext config) throws ProcessingException { + public Document getMetaData(FedizContext config) throws ProcessingException { try { ByteArrayOutputStream bout = new ByteArrayOutputStream(4096); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/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 new file mode 100644 index 0000000..12f4669 --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java @@ -0,0 +1,681 @@ +/** + * 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.core.processor; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +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.w3c.dom.Document; +import org.w3c.dom.Element; +import org.apache.cxf.fediz.core.FederationConstants; +import org.apache.cxf.fediz.core.TokenValidator; +import org.apache.cxf.fediz.core.TokenValidatorRequest; +import org.apache.cxf.fediz.core.TokenValidatorResponse; +import org.apache.cxf.fediz.core.config.FederationProtocol; +import org.apache.cxf.fediz.core.config.FedizContext; +import org.apache.cxf.fediz.core.config.KeyManager; +import org.apache.cxf.fediz.core.exception.ProcessingException; +import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE; +import org.apache.cxf.fediz.core.metadata.MetadataWriter; +import org.apache.cxf.fediz.core.spi.FreshnessCallback; +import org.apache.cxf.fediz.core.spi.HomeRealmCallback; +import org.apache.cxf.fediz.core.spi.IDPCallback; +import org.apache.cxf.fediz.core.spi.RealmCallback; +import org.apache.cxf.fediz.core.spi.SignInQueryCallback; +import org.apache.cxf.fediz.core.spi.WAuthCallback; +import org.apache.cxf.fediz.core.spi.WReqCallback; +import org.apache.cxf.fediz.core.util.DOMUtils; +import org.apache.wss4j.common.ext.WSPasswordCallback; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.dom.WSConstants; +import org.apache.wss4j.dom.WSDataRef; +import org.apache.wss4j.dom.WSDocInfo; +import org.apache.wss4j.dom.WSSConfig; +import org.apache.wss4j.dom.WSSecurityEngine; +import org.apache.wss4j.dom.WSSecurityEngineResult; +import org.apache.wss4j.dom.handler.RequestData; +import org.apache.wss4j.dom.processor.EncryptedDataProcessor; +import org.apache.wss4j.dom.processor.Processor; +import org.apache.wss4j.dom.util.XmlSchemaDateFormat; +import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FederationProcessorImpl implements FedizProcessor { + + private static final Logger LOG = LoggerFactory.getLogger(FederationProcessorImpl.class); + + /** + * Default constructor + */ + public FederationProcessorImpl() { + super(); + } + + @Override + public FedizResponse processRequest(FedizRequest request, + FedizContext config) + throws ProcessingException { + + if (!(config.getProtocol() instanceof FederationProtocol)) { + LOG.error("Unsupported protocol"); + throw new IllegalStateException("Unsupported protocol"); + } + FedizResponse response = null; + if (FederationConstants.ACTION_SIGNIN.equals(request.getWa())) { + response = this.processSignInRequest(request, config); + } else { + LOG.error("Invalid action '" + request.getWa() + "'"); + throw new ProcessingException(TYPE.INVALID_REQUEST); + } + return response; + } + + + public Document getMetaData(FedizContext config) throws ProcessingException { + return new MetadataWriter().getMetaData(config); + } + + protected FedizResponse processSignInRequest( + FedizRequest request, FedizContext config) + throws ProcessingException { + + byte[] wresult = request.getWresult().getBytes(); + + Document doc = null; + Element el = null; + try { + doc = DOMUtils.readXml(new ByteArrayInputStream(wresult)); + el = doc.getDocumentElement(); + + } catch (Exception e) { + LOG.warn("Failed to parse wresult: " + e.getMessage()); + throw new ProcessingException(TYPE.INVALID_REQUEST); + } + + if ("RequestSecurityTokenResponseCollection".equals(el.getLocalName())) { + el = DOMUtils.getFirstElement(el); + } + if (!"RequestSecurityTokenResponse".equals(el.getLocalName())) { + LOG.warn("Unexpected root element of wresult: '" + el.getLocalName() + "'"); + throw new ProcessingException(TYPE.INVALID_REQUEST); + } + el = DOMUtils.getFirstElement(el); + Element rst = null; + Element lifetimeElem = null; + String tt = null; + + while (el != null) { + String ln = el.getLocalName(); + if (FederationConstants.WS_TRUST_13_NS.equals(el.getNamespaceURI()) + || FederationConstants.WS_TRUST_2005_02_NS.equals(el.getNamespaceURI())) { + if ("Lifetime".equals(ln)) { + lifetimeElem = el; + } else if ("RequestedSecurityToken".equals(ln)) { + rst = DOMUtils.getFirstElement(el); + } else if ("TokenType".equals(ln)) { + tt = DOMUtils.getContent(el); + } + } + el = DOMUtils.getNextElement(el); + } + if (LOG.isDebugEnabled()) { + LOG.debug("RST: " + ((rst != null) ? rst.toString() : "null")); + LOG.debug("Lifetime: " + + ((lifetimeElem != null) ? lifetimeElem.toString() + : "null")); + LOG.debug("Tokentype: " + ((tt != null) ? tt.toString() : "null")); + } + if (rst == null) { + LOG.warn("RequestedSecurityToken element not found in wresult"); + throw new ProcessingException(TYPE.BAD_REQUEST); + } + LifeTime lifeTime = null; + if (lifetimeElem != null) { + lifeTime = processLifeTime(lifetimeElem); + } + + if (config.isDetectExpiredTokens() && lifeTime != null) { + Date currentDate = new Date(); + if (currentDate.after(lifeTime.getExpires())) { + LOG.warn("RSTR Lifetime expired"); + throw new ProcessingException(TYPE.TOKEN_EXPIRED); + } + DateTime currentTime = new DateTime(); + DateTime validFrom = new DateTime(lifeTime.created); + currentTime = currentTime.plusSeconds(config.getMaximumClockSkew().intValue()); + if (validFrom.isAfter(currentTime)) { + LOG.debug("RSTR Lifetime not yet valid"); + throw new ProcessingException(TYPE.TOKEN_INVALID); + } + } + + // Check to see if RST is encrypted + if ("EncryptedData".equals(rst.getLocalName()) + && WSConstants.ENC_NS.equals(rst.getNamespaceURI())) { + Element decryptedRST = decryptEncryptedRST(rst, config); + if (decryptedRST != null) { + rst = decryptedRST; + } + } + + TokenValidatorResponse validatorResponse = null; + List validators = ((FederationProtocol)config.getProtocol()).getTokenValidators(); + for (TokenValidator validator : validators) { + boolean canHandle = false; + if (tt != null) { + canHandle = validator.canHandleTokenType(tt); + } else { + canHandle = validator.canHandleToken(rst); + } + if (canHandle) { + try { + TokenValidatorRequest validatorRequest = + new TokenValidatorRequest(rst, request.getCerts()); + validatorResponse = validator.validateAndProcessToken(validatorRequest, config); + } catch (ProcessingException ex) { + throw ex; + } catch (Exception ex) { + LOG.warn("Failed to validate token", ex); + throw new ProcessingException(TYPE.TOKEN_INVALID); + } + break; + } else { + LOG.warn("No security token validator found for '" + tt + "'"); + throw new ProcessingException(TYPE.BAD_REQUEST); + } + } + + // Check whether token already used for signin + if (validatorResponse.getUniqueTokenId() != null + && config.isDetectReplayedTokens()) { + // Check whether token has already been processed once, prevent + // replay attack + if (!config.getTokenReplayCache().contains(validatorResponse.getUniqueTokenId())) { + // not cached + Date expires = null; + if (lifeTime != null && lifeTime.getExpires() != null) { + expires = lifeTime.getExpires(); + } else { + expires = validatorResponse.getExpires(); + } + if (expires != null) { + Date currentTime = new Date(); + long ttl = expires.getTime() - currentTime.getTime(); + config.getTokenReplayCache().add(validatorResponse.getUniqueTokenId(), ttl / 1000L); + } else { + config.getTokenReplayCache().add(validatorResponse.getUniqueTokenId()); + } + } else { + LOG.error("Replay attack with token id: " + validatorResponse.getUniqueTokenId()); + throw new ProcessingException("Replay attack with token id: " + + validatorResponse.getUniqueTokenId(), TYPE.TOKEN_REPLAY); + } + } + + FedizResponse fedResponse = new FedizResponse( + validatorResponse.getUsername(), validatorResponse.getIssuer(), + validatorResponse.getRoles(), validatorResponse.getClaims(), + validatorResponse.getAudience(), + (lifeTime != null) ? lifeTime.getCreated() : null, + (lifeTime != null) ? lifeTime.getExpires() : null, rst, + validatorResponse.getUniqueTokenId()); + + return fedResponse; + } + + private Element decryptEncryptedRST( + Element encryptedRST, + FedizContext config + ) throws ProcessingException { + + KeyManager decryptionKeyManager = config.getDecryptionKey(); + if (decryptionKeyManager == null || decryptionKeyManager.getCrypto() == null) { + LOG.debug( + "We must have a decryption Crypto instance configured to decrypt encrypted tokens" + ); + throw new ProcessingException(TYPE.BAD_REQUEST); + } + String keyPassword = decryptionKeyManager.getKeyPassword(); + if (keyPassword == null) { + LOG.debug( + "We must have a decryption key password to decrypt encrypted tokens" + ); + throw new ProcessingException(TYPE.BAD_REQUEST); + } + + EncryptedDataProcessor proc = new EncryptedDataProcessor(); + WSDocInfo docInfo = new WSDocInfo(encryptedRST.getOwnerDocument()); + RequestData data = new RequestData(); + + // Disable WSS4J processing of the (decrypted) SAML Token + WSSConfig wssConfig = WSSConfig.getNewInstance(); + wssConfig.setProcessor(WSSecurityEngine.SAML_TOKEN, new NOOpProcessor()); + wssConfig.setProcessor(WSSecurityEngine.SAML2_TOKEN, new NOOpProcessor()); + data.setWssConfig(wssConfig); + + data.setDecCrypto(decryptionKeyManager.getCrypto()); + data.setCallbackHandler(new DecryptionCallbackHandler(keyPassword)); + try { + List result = + proc.handleToken(encryptedRST, data, docInfo); + if (result.size() > 0) { + @SuppressWarnings("unchecked") + List dataRefs = + (List)result.get(result.size() - 1).get(WSSecurityEngineResult.TAG_DATA_REF_URIS); + if (dataRefs != null && dataRefs.size() > 0) { + return dataRefs.get(0).getProtectedElement(); + } + } + } catch (WSSecurityException e) { + LOG.debug(e.getMessage(), e); + throw new ProcessingException(TYPE.TOKEN_INVALID); + } + return null; + } + + private LifeTime processLifeTime(Element lifetimeElem) throws ProcessingException { + try { + Element createdElem = DOMUtils.getFirstChildWithName(lifetimeElem, + WSConstants.WSU_NS, WSConstants.CREATED_LN); + DateFormat zulu = new XmlSchemaDateFormat(); + + Date created = zulu.parse(DOMUtils.getContent(createdElem)); + + Element expiresElem = DOMUtils.getFirstChildWithName(lifetimeElem, + WSConstants.WSU_NS, WSConstants.EXPIRES_LN); + Date expires = zulu.parse(DOMUtils.getContent(expiresElem)); + + return new LifeTime(created, expires); + + } catch (ParseException e) { + LOG.error("Failed to parse lifetime element in wresult: " + e.getMessage()); + throw new ProcessingException(TYPE.BAD_REQUEST); + } + } + + public class LifeTime { + + private Date created; + private Date expires; + + public LifeTime(Date created, Date expires) { + this.created = created; + this.expires = expires; + } + + public Date getCreated() { + return created; + } + + public Date getExpires() { + return expires; + } + + } + + @Override + public String createSignInRequest(HttpServletRequest request, FedizContext config) + throws ProcessingException { + + String redirectURL = null; + try { + if (!(config.getProtocol() instanceof FederationProtocol)) { + LOG.error("Unsupported protocol"); + throw new IllegalStateException("Unsupported protocol"); + } + + String issuerURL = resolveIssuer(request, config); + LOG.info("Issuer url: " + issuerURL); + if (issuerURL != null && issuerURL.length() > 0) { + redirectURL = issuerURL; + } + + String wAuth = resolveAuthenticationType(request, config); + LOG.info("WAuth: " + wAuth); + + String wReq = resolveRequest(request, config); + LOG.info("WReq: " + wReq); + + String homeRealm = resolveHomeRealm(request, config); + LOG.info("HomeRealm: " + homeRealm); + + String freshness = resolveFreshness(request, config); + LOG.info("Freshness: " + freshness); + + String signInQuery = resolveSignInQuery(request, config); + LOG.info("SignIn Query: " + signInQuery); + + + StringBuilder sb = new StringBuilder(); + sb.append(FederationConstants.PARAM_ACTION).append('=').append(FederationConstants.ACTION_SIGNIN); + + String reply = ((FederationProtocol)config.getProtocol()).getReply(); + if (reply == null || reply.length() == 0) { + reply = request.getRequestURL().toString(); + } else { + try { + new URL(reply); + } catch (MalformedURLException ex) { + if (reply.startsWith("/")) { + reply = extractFullContextPath(request).concat(reply.substring(1)); + } else { + reply = extractFullContextPath(request).concat(reply); + } + } + } + + LOG.debug("wreply=" + reply); + sb.append('&').append(FederationConstants.PARAM_REPLY).append('='); + sb.append(URLEncoder.encode(reply, "UTF-8")); + + String realm = resolveWTRealm(request, config); + LOG.debug("wtrealm=" + realm); + + //add wtrealm parameter + sb.append('&').append(FederationConstants.PARAM_TREALM).append('=') + .append(URLEncoder.encode(realm, "UTF-8")); + + // add authentication type parameter wauth if set + if (wAuth != null && wAuth.length() > 0) { + sb.append('&').append(FederationConstants.PARAM_AUTH_TYPE).append('=') + .append(URLEncoder.encode(wAuth, "UTF-8")); + } + + // add tokenRequest parameter wreq if set + if (wReq != null && wReq.length() > 0) { + sb.append('&').append(FederationConstants.PARAM_REQUEST).append('=') + .append(URLEncoder.encode(wReq, "UTF-8")); + } + + // add home realm parameter whr if set + if (homeRealm != null && homeRealm.length() > 0) { + sb.append('&').append(FederationConstants.PARAM_HOME_REALM).append('=') + .append(URLEncoder.encode(homeRealm, "UTF-8")); + } + + // add freshness parameter wfresh if set + if (freshness != null && freshness.length() > 0) { + sb.append('&').append(FederationConstants.PARAM_FRESHNESS).append('=') + .append(URLEncoder.encode(freshness, "UTF-8")); + } + + // add current time parameter wct + Date creationTime = new Date(); + XmlSchemaDateFormat fmt = new XmlSchemaDateFormat(); + String wct = fmt.format(creationTime); + sb.append('&').append(FederationConstants.PARAM_CURRENT_TIME).append('=') + .append(URLEncoder.encode(wct, "UTF-8")); + + // add signin query extensions + if (signInQuery != null && signInQuery.length() > 0) { + sb.append('&').append(signInQuery); + } + + redirectURL = redirectURL + "?" + sb.toString(); + } catch (Exception ex) { + LOG.error("Failed to create SignInRequest", ex); + throw new ProcessingException("Failed to create SignInRequest"); + } + return redirectURL; + } + + @Override + public String createSignOutRequest(HttpServletRequest request, FedizContext config) + throws ProcessingException { + + String redirectURL = null; + try { + if (!(config.getProtocol() instanceof FederationProtocol)) { + LOG.error("Unsupported protocol"); + throw new IllegalStateException("Unsupported protocol"); + } + + String issuerURL = resolveIssuer(request, config); + LOG.info("Issuer url: " + issuerURL); + if (issuerURL != null && issuerURL.length() > 0) { + redirectURL = issuerURL; + } + + StringBuilder sb = new StringBuilder(); + sb.append(FederationConstants.PARAM_ACTION).append('=').append(FederationConstants.ACTION_SIGNOUT); + + String logoutRedirectTo = config.getLogoutRedirectTo(); + if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) { + + if (logoutRedirectTo.startsWith("/")) { + logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo.substring(1)); + } else { + logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo); + } + + LOG.debug("wreply=" + logoutRedirectTo); + + sb.append('&').append(FederationConstants.PARAM_REPLY).append('='); + sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8")); + } + + redirectURL = redirectURL + "?" + sb.toString(); + } catch (Exception ex) { + LOG.error("Failed to create SignInRequest", ex); + throw new ProcessingException("Failed to create SignInRequest"); + } + return redirectURL; + } + + private String resolveSignInQuery(HttpServletRequest request, FedizContext config) + throws IOException, UnsupportedCallbackException, UnsupportedEncodingException { + Object signInQueryObj = ((FederationProtocol)config.getProtocol()).getSignInQuery(); + String signInQuery = null; + if (signInQueryObj != null) { + if (signInQueryObj instanceof String) { + signInQuery = (String)signInQueryObj; + } else if (signInQueryObj instanceof CallbackHandler) { + CallbackHandler frCB = (CallbackHandler)signInQueryObj; + SignInQueryCallback callback = new SignInQueryCallback(request); + frCB.handle(new Callback[] {callback}); + Map signInQueryMap = callback.getSignInQueryParamMap(); + StringBuilder sbQuery = new StringBuilder(); + for (String key : signInQueryMap.keySet()) { + if (sbQuery.length() > 0) { + sbQuery.append("&"); + } + sbQuery.append(key).append('='). + append(URLEncoder.encode(signInQueryMap.get(key), "UTF-8")); + } + signInQuery = sbQuery.toString(); + + } + } + return signInQuery; + } + + private String resolveFreshness(HttpServletRequest request, FedizContext config) throws IOException, + UnsupportedCallbackException { + Object freshnessObj = ((FederationProtocol)config.getProtocol()).getFreshness(); + String freshness = null; + if (freshnessObj != null) { + if (freshnessObj instanceof String) { + freshness = (String)freshnessObj; + } else if (freshnessObj instanceof CallbackHandler) { + CallbackHandler frCB = (CallbackHandler)freshnessObj; + FreshnessCallback callback = new FreshnessCallback(request); + frCB.handle(new Callback[] {callback}); + freshness = callback.getFreshness(); + } + } + return freshness; + } + + private String resolveHomeRealm(HttpServletRequest request, FedizContext config) throws IOException, + UnsupportedCallbackException { + Object homeRealmObj = ((FederationProtocol)config.getProtocol()).getHomeRealm(); + String homeRealm = null; + 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(); + } + } + return homeRealm; + } + + private String resolveAuthenticationType(HttpServletRequest request, FedizContext config) + throws IOException, UnsupportedCallbackException { + Object wAuthObj = ((FederationProtocol)config.getProtocol()).getAuthenticationType(); + String wAuth = null; + if (wAuthObj != null) { + if (wAuthObj instanceof String) { + wAuth = (String)wAuthObj; + } else if (wAuthObj instanceof CallbackHandler) { + CallbackHandler wauthCB = (CallbackHandler)wAuthObj; + WAuthCallback callback = new WAuthCallback(request); + wauthCB.handle(new Callback[] {callback}); + wAuth = callback.getWauth(); + } + } + return wAuth; + } + + private String resolveRequest(HttpServletRequest request, FedizContext config) + throws IOException, UnsupportedCallbackException { + Object wReqObj = ((FederationProtocol)config.getProtocol()).getRequest(); + String wReq = null; + if (wReqObj != null) { + if (wReqObj instanceof String) { + wReq = (String)wReqObj; + } else if (wReqObj instanceof CallbackHandler) { + CallbackHandler wauthCB = (CallbackHandler)wReqObj; + WReqCallback callback = new WReqCallback(request); + wauthCB.handle(new Callback[] {callback}); + wReq = callback.getWreq(); + } + } + return wReq; + } + + private String resolveIssuer(HttpServletRequest request, FedizContext config) throws IOException, + UnsupportedCallbackException { + Object issuerObj = ((FederationProtocol)config.getProtocol()).getIssuer(); + String issuerURL = null; + if (issuerObj instanceof String) { + issuerURL = (String)issuerObj; + } else if (issuerObj instanceof CallbackHandler) { + CallbackHandler issuerCB = (CallbackHandler)issuerObj; + IDPCallback callback = new IDPCallback(request); + issuerCB.handle(new Callback[] {callback}); + issuerURL = callback.getIssuerUrl().toString(); + } + return issuerURL; + } + + private String resolveWTRealm(HttpServletRequest request, FedizContext config) throws IOException, + UnsupportedCallbackException { + Object wtRealmObj = ((FederationProtocol)config.getProtocol()).getRealm(); + String wtRealm = null; + if (wtRealmObj != null) { + if (wtRealmObj instanceof String) { + wtRealm = (String)wtRealmObj; + } else if (wtRealmObj instanceof CallbackHandler) { + CallbackHandler hrCB = (CallbackHandler)wtRealmObj; + RealmCallback callback = new RealmCallback(request); + hrCB.handle(new Callback[] {callback}); + wtRealm = callback.getRealm(); + } + } else { + wtRealm = extractFullContextPath(request); //default value + } + return wtRealm; + } + + + private String extractFullContextPath(HttpServletRequest request) throws MalformedURLException { + String result = null; + String contextPath = request.getContextPath(); + String requestUrl = request.getRequestURL().toString(); + String requestPath = new URL(requestUrl).getPath(); + // Cut request path of request url and add context path if not ROOT + if (requestPath != null && requestPath.length() > 0) { + int lastIndex = requestUrl.lastIndexOf(requestPath); + result = requestUrl.substring(0, lastIndex); + } else { + result = requestUrl; + } + if (contextPath != null && contextPath.length() > 0) { + // contextPath contains starting slash + result = result + contextPath + "/"; + } else { + result = result + "/"; + } + return result; + } + + private static class DecryptionCallbackHandler implements CallbackHandler { + + private final String password; + + public DecryptionCallbackHandler(String password) { + this.password = password; + } + + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof WSPasswordCallback) { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; + pc.setPassword(password); + } else { + throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); + } + } + } + + } + + private static class NOOpProcessor implements Processor { + + @Override + public List handleToken(Element arg0, RequestData arg1, WSDocInfo arg2) + throws WSSecurityException { + return new ArrayList(); + } + + } + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java new file mode 100644 index 0000000..1081f05 --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java @@ -0,0 +1,38 @@ +/** + * 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.core.processor; + +import javax.servlet.http.HttpServletRequest; +import org.w3c.dom.Document; +import org.apache.cxf.fediz.core.config.FedizContext; +import org.apache.cxf.fediz.core.exception.ProcessingException; + + +public interface FedizProcessor { + + FedizResponse processRequest(FedizRequest request, FedizContext config) throws ProcessingException; + + String createSignInRequest(HttpServletRequest request, FedizContext config) throws ProcessingException; + + String createSignOutRequest(HttpServletRequest request, FedizContext config) throws ProcessingException; + + Document getMetaData(FedizContext config) throws ProcessingException; + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessorFactory.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessorFactory.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessorFactory.java new file mode 100644 index 0000000..c44a40b --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessorFactory.java @@ -0,0 +1,44 @@ +/** + * 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.core.processor; + +import org.apache.cxf.fediz.core.config.FederationProtocol; +import org.apache.cxf.fediz.core.config.Protocol; +// import org.apache.cxf.fediz.core.config.SAMLProtocol; + +/** + * A Factory to return FedizProcessor instances depending on the Protocol + */ +public final class FedizProcessorFactory { + + private FedizProcessorFactory() { + // complete + } + + public static FedizProcessor newFedizProcessor(Protocol protocol) { + if (protocol instanceof FederationProtocol) { + return new FederationProcessorImpl(); + } /*else if (protocol instanceof SAMLProtocol) { + return new SAMLProcessorImpl(); + }*/ + return null; + } + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java new file mode 100644 index 0000000..bf296e5 --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java @@ -0,0 +1,62 @@ +/** + * 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.core.processor; + +import java.io.Serializable; +import java.security.cert.Certificate; + +public class FedizRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String wa; + private String wresult; + private String wct; + private Certificate[] certs; + + + public String getWct() { + return wct; + } + public void setWct(String wct) { + this.wct = wct; + } + + public String getWa() { + return wa; + } + public void setWa(String wa) { + this.wa = wa; + } + public String getWresult() { + return wresult; + } + public void setWresult(String wresult) { + this.wresult = wresult; + } + public Certificate[] getCerts() { + return certs; + } + public void setCerts(Certificate[] certs) { + this.certs = certs; + } + + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/08af52b6/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizResponse.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizResponse.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizResponse.java new file mode 100644 index 0000000..b392ad2 --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizResponse.java @@ -0,0 +1,109 @@ +/** + * 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.core.processor; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.w3c.dom.Element; + +import org.apache.cxf.fediz.core.Claim; + +public class FedizResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private String audience; + private String username; + private List roles; + private String issuer; + private List claims; + private Element token; + private String uniqueTokenId; + + /** + * Created time + */ + private Date tokenCreated; + + /** + * Expiration time + */ + private Date tokenExpires; + + //CHECKSTYLE:OFF + public FedizResponse(String username, String issuer, List roles, List claims, String audience, Date created, Date expires, Element token, String uniqueTokenId) { + this.username = username; + this.issuer = issuer; + this.roles = roles; + this.claims = claims; + this.audience = audience; + this.tokenCreated = created; + this.tokenExpires = expires; + this.token = token; + this.uniqueTokenId = uniqueTokenId; + } + + public String getUniqueTokenId() { + return uniqueTokenId; + } + + public String getAudience() { + return audience; + } + + public String getUsername() { + return username; + } + + public List getRoles() { + if (roles == null) { + return null; + } + return Collections.unmodifiableList(roles); + } + + public String getIssuer() { + return issuer; + } + + public List getClaims() { + if (claims == null) { + return null; + } + return Collections.unmodifiableList(claims); + } + + public Date getTokenCreated() { + return tokenCreated; + } + + public Date getTokenExpires() { + return tokenExpires; + } + + public Element getToken() { + return token; + } + + +}