From 24bbfdbff181d276912e50fb77f1e8ac15c1d74d Mon Sep 17 00:00:00 2001
From: Andriy Vyedyeneyev <andriy.vyedyeneyev@allianz.at>
Date: Mon, 15 Feb 2016 22:16:13 +0100
Subject: [PATCH] Add support to Bearer Token Authorization

---
 .../security/credential/BearerTokenCredential.java | 25 +++++++++
 .../AuthorizationHeaderCredentialExtractor.java    | 65 ++++++++--------------
 ...cAuthenticationCredentialExtractorStrategy.java | 38 +++++++++++++
 ...rAuthenticationCredentialExtractorStrategy.java | 32 +++++++++++
 .../extractor/CredentialExtractorStrategy.java     | 11 ++++
 ...tAuthenticationCredentialExtractorStrategy.java | 49 ++++++++++++++++
 ...redential.extractor.CredentialExtractorStrategy |  3 +
 7 files changed, 181 insertions(+), 42 deletions(-)
 create mode 100644 core/security/base/src/main/java/org/switchyard/security/credential/BearerTokenCredential.java
 create mode 100644 core/security/base/src/main/java/org/switchyard/security/credential/extractor/BasicAuthenticationCredentialExtractorStrategy.java
 create mode 100644 core/security/base/src/main/java/org/switchyard/security/credential/extractor/BearerAuthenticationCredentialExtractorStrategy.java
 create mode 100644 core/security/base/src/main/java/org/switchyard/security/credential/extractor/CredentialExtractorStrategy.java
 create mode 100644 core/security/base/src/main/java/org/switchyard/security/credential/extractor/DigestAuthenticationCredentialExtractorStrategy.java
 create mode 100644 core/security/base/src/main/resources/META-INF/services/org.switchyard.security.credential.extractor.CredentialExtractorStrategy

diff --git a/core/security/base/src/main/java/org/switchyard/security/credential/BearerTokenCredential.java b/core/security/base/src/main/java/org/switchyard/security/credential/BearerTokenCredential.java
new file mode 100644
index 0000000..00b8118
--- /dev/null
+++ b/core/security/base/src/main/java/org/switchyard/security/credential/BearerTokenCredential.java
@@ -0,0 +1,25 @@
+package org.switchyard.security.credential;
+
+/**
+ * holder of Bearer token
+ * 
+ * @author Andriy Vyedyeneyev
+ *
+ */
+public class BearerTokenCredential implements Credential {
+
+	/**
+	 * serial 
+	 */
+	private static final long serialVersionUID = 8814812676001122029L;
+	private String token;
+
+	public BearerTokenCredential(String token) {
+		this.token = token;
+	}
+
+	public String getToken() {
+		return token;
+	}
+
+}
diff --git a/core/security/base/src/main/java/org/switchyard/security/credential/extractor/AuthorizationHeaderCredentialExtractor.java b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/AuthorizationHeaderCredentialExtractor.java
index c825e61..5058b6a 100644
--- a/core/security/base/src/main/java/org/switchyard/security/credential/extractor/AuthorizationHeaderCredentialExtractor.java
+++ b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/AuthorizationHeaderCredentialExtractor.java
@@ -14,18 +14,24 @@
 package org.switchyard.security.credential.extractor;
 
 import java.nio.charset.Charset;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 import java.util.Set;
 
 import org.switchyard.common.codec.Base64;
 import org.switchyard.common.lang.Strings;
 import org.switchyard.security.BaseSecurityLogger;
+import org.switchyard.security.credential.BearerTokenCredential;
 import org.switchyard.security.credential.Credential;
 import org.switchyard.security.credential.NameCredential;
 import org.switchyard.security.credential.PasswordCredential;
+import org.switchyard.security.credential.extractor.CredentialExtractorStrategy;
+
 
 /**
  * AuthorizationHeaderCredentialExtractor.
@@ -81,48 +87,23 @@ public class AuthorizationHeaderCredentialExtractor implements CredentialExtract
      */
     @Override
     public Set<Credential> extract(String source) {
-        Set<Credential> credentials = new HashSet<Credential>();
-        if (source != null) {
-            if (source.startsWith("Basic ")) {
-                String encoded = source.substring(6, source.length());
-                String decoded = Base64.decodeToString(encoded, _charset);
-                if (decoded.indexOf(':') != -1) {
-                    String[] split = decoded.split(":", 2);
-                    String name = split.length > 0 ? split[0] : null;
-                    if (name != null) {
-                        credentials.add(new NameCredential(name));
-                    }
-                    String password = split.length > 1 ? split[1] : null;
-                    if (password != null) {
-                        credentials.add(new PasswordCredential(password));
-                    }
-                }
-            } else if (source.startsWith("Digest ")) {
-                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-                // https://issues.jboss.org/browse/SWITCHYARD-1082
-                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-                Map<String,String> map = new HashMap<String,String>();
-                String everything = source.substring(6, source.length()).trim();
-                List<String> list = Strings.splitTrimToNull(everything, ",\n");
-                for (String pair : list) {
-                    String[] split = pair.split("=", 2);
-                    String key = split.length > 0 ? split[0] : null;
-                    String value = split.length > 1 ? split[1] : null;
-                    if (key != null && value != null) {
-                        if (value.startsWith("\"") && value.endsWith("\"")) {
-                            value = value.substring(1, value.length() - 1);
-                        }
-                        map.put(key, value);
-                    }
-                }
-                String username = map.get("username");
-                if (username != null) {
-                    credentials.add(new NameCredential(username));
-                }
-                // TODO: complete per SWITCHYARD-1082
-            }
-        }
-        return credentials;
+    	if(source!=null) {
+	    	ServiceLoader<CredentialExtractorStrategy> extractorServiceLoader  = ServiceLoader.load(CredentialExtractorStrategy.class);
+	    	
+	    	Iterator<CredentialExtractorStrategy> iterator = extractorServiceLoader.iterator();
+	    	
+	    	while(iterator.hasNext()) {
+	    		CredentialExtractorStrategy extractorStrategy = iterator.next();
+	    		
+	    		Set<Credential> credentials = extractorStrategy.process(source, _charset);
+	    		
+	    		if(credentials!=null && credentials.isEmpty() == false) {
+	    			return credentials;
+	    		}
+	    	}
+    	}
+    	
+    	return Collections.emptySet();
     }
 
 }
diff --git a/core/security/base/src/main/java/org/switchyard/security/credential/extractor/BasicAuthenticationCredentialExtractorStrategy.java b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/BasicAuthenticationCredentialExtractorStrategy.java
new file mode 100644
index 0000000..ec63a05
--- /dev/null
+++ b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/BasicAuthenticationCredentialExtractorStrategy.java
@@ -0,0 +1,38 @@
+package org.switchyard.security.credential.extractor;
+
+import java.nio.charset.Charset;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.switchyard.common.codec.Base64;
+import org.switchyard.security.credential.Credential;
+import org.switchyard.security.credential.NameCredential;
+import org.switchyard.security.credential.PasswordCredential;
+
+public class BasicAuthenticationCredentialExtractorStrategy implements
+		CredentialExtractorStrategy {
+
+	@Override
+	public Set<Credential> process(String source, Charset charset) {
+		Set<Credential> credentials = new HashSet<Credential>();
+
+		if (source.startsWith("Basic ")) {
+            String encoded = source.substring(6, source.length());
+            String decoded = Base64.decodeToString(encoded, charset);
+            if (decoded.indexOf(':') != -1) {
+                String[] split = decoded.split(":", 2);
+                String name = split.length > 0 ? split[0] : null;
+                if (name != null) {
+                    credentials.add(new NameCredential(name));
+                }
+                String password = split.length > 1 ? split[1] : null;
+                if (password != null) {
+                    credentials.add(new PasswordCredential(password));
+                }
+            }
+        }
+
+		return credentials;
+	}
+
+}
diff --git a/core/security/base/src/main/java/org/switchyard/security/credential/extractor/BearerAuthenticationCredentialExtractorStrategy.java b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/BearerAuthenticationCredentialExtractorStrategy.java
new file mode 100644
index 0000000..2cdf8fd
--- /dev/null
+++ b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/BearerAuthenticationCredentialExtractorStrategy.java
@@ -0,0 +1,32 @@
+package org.switchyard.security.credential.extractor;
+
+import java.nio.charset.Charset;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.switchyard.common.codec.Base64;
+import org.switchyard.security.credential.BearerTokenCredential;
+import org.switchyard.security.credential.Credential;
+
+/**
+ * Bearer token extractor strategy.
+ * 
+ * @author Andriy Vyedyeneyev
+ *
+ */
+public class BearerAuthenticationCredentialExtractorStrategy implements
+		CredentialExtractorStrategy {
+
+	@Override
+	public Set<Credential> process(String source, Charset charset) {
+		Set<Credential> credentials = new HashSet<Credential>();
+
+		if (source.startsWith("Bearer ")) {
+			String token = source.substring(7, source.length());
+			credentials.add(new BearerTokenCredential(token));
+		}
+
+		return credentials;
+	}
+
+}
diff --git a/core/security/base/src/main/java/org/switchyard/security/credential/extractor/CredentialExtractorStrategy.java b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/CredentialExtractorStrategy.java
new file mode 100644
index 0000000..f474973
--- /dev/null
+++ b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/CredentialExtractorStrategy.java
@@ -0,0 +1,11 @@
+package org.switchyard.security.credential.extractor;
+
+import java.nio.charset.Charset;
+import java.util.Set;
+
+import org.switchyard.security.credential.Credential;
+
+public interface CredentialExtractorStrategy {
+
+	Set<Credential> process(String source, Charset charset);
+}
diff --git a/core/security/base/src/main/java/org/switchyard/security/credential/extractor/DigestAuthenticationCredentialExtractorStrategy.java b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/DigestAuthenticationCredentialExtractorStrategy.java
new file mode 100644
index 0000000..b6cc35c
--- /dev/null
+++ b/core/security/base/src/main/java/org/switchyard/security/credential/extractor/DigestAuthenticationCredentialExtractorStrategy.java
@@ -0,0 +1,49 @@
+package org.switchyard.security.credential.extractor;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.switchyard.common.lang.Strings;
+import org.switchyard.security.credential.Credential;
+import org.switchyard.security.credential.NameCredential;
+
+public class DigestAuthenticationCredentialExtractorStrategy implements
+		CredentialExtractorStrategy {
+
+	@Override
+	public Set<Credential> process(String source, Charset charset) {
+		Set<Credential> credentials = new HashSet<Credential>();
+
+		if (source.startsWith("Digest ")) {
+            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            // https://issues.jboss.org/browse/SWITCHYARD-1082
+            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            Map<String,String> map = new HashMap<String,String>();
+            String everything = source.substring(6, source.length()).trim();
+            List<String> list = Strings.splitTrimToNull(everything, ",\n");
+            for (String pair : list) {
+                String[] split = pair.split("=", 2);
+                String key = split.length > 0 ? split[0] : null;
+                String value = split.length > 1 ? split[1] : null;
+                if (key != null && value != null) {
+                    if (value.startsWith("\"") && value.endsWith("\"")) {
+                        value = value.substring(1, value.length() - 1);
+                    }
+                    map.put(key, value);
+                }
+            }
+            String username = map.get("username");
+            if (username != null) {
+                credentials.add(new NameCredential(username));
+            }
+            // TODO: complete per SWITCHYARD-1082
+        }
+		
+		return credentials;
+	}
+
+}
diff --git a/core/security/base/src/main/resources/META-INF/services/org.switchyard.security.credential.extractor.CredentialExtractorStrategy b/core/security/base/src/main/resources/META-INF/services/org.switchyard.security.credential.extractor.CredentialExtractorStrategy
new file mode 100644
index 0000000..a1f3c19
--- /dev/null
+++ b/core/security/base/src/main/resources/META-INF/services/org.switchyard.security.credential.extractor.CredentialExtractorStrategy
@@ -0,0 +1,3 @@
+org.switchyard.security.credential.extractor.BasicAuthenticationCredentialExtractorStrategy
+org.switchyard.security.credential.extractor.BearerAuthenticationCredentialExtractorStrategy
+org.switchyard.security.credential.extractor.DigestAuthenticationCredentialExtractorStrategy
\ No newline at end of file
-- 
2.5.0.windows.1

