You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2014/08/14 21:50:36 UTC
[1/7] git commit: Initial revision for the SyncopeLoginModule
Repository: karaf
Updated Branches:
refs/heads/master 4a53ed809 -> 7f1ed9b26
Initial revision for the SyncopeLoginModule
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/eb821774
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/eb821774
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/eb821774
Branch: refs/heads/master
Commit: eb821774b112a8b89ad280cd86e71e798942ce69
Parents: 18a8290
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Wed Aug 13 07:32:44 2014 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Wed Aug 13 07:32:44 2014 +0200
----------------------------------------------------------------------
jaas/modules/pom.xml | 13 ++-
.../modules/syncope/SyncopeLoginModule.java | 111 +++++++++++++++++++
.../developers-guide/security-framework.conf | 24 +++-
.../src/main/webapp/users-guide/security.conf | 1 +
4 files changed, 144 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/eb821774/jaas/modules/pom.xml
----------------------------------------------------------------------
diff --git a/jaas/modules/pom.xml b/jaas/modules/pom.xml
index cccf6e1..a6c15f0 100644
--- a/jaas/modules/pom.xml
+++ b/jaas/modules/pom.xml
@@ -93,6 +93,13 @@
<artifactId>org.apache.karaf.util</artifactId>
<scope>provided</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient-osgi</artifactId>
+ <version>4.3.5</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-core-integ</artifactId>
@@ -143,12 +150,16 @@
javax.net,
org.apache.karaf.jaas.config,
org.osgi.service.event;resolution:=optional,
+ net.sf.ehcache*;resolution:=optional,
+ net.spy.memcached*;resolution:=optional,
+ org.apache.commons.codec*;resolution:=optional,
*
</Import-Package>
<Private-Package>
org.apache.karaf.jaas.modules.impl,
org.apache.felix.utils.properties,
- org.apache.karaf.util.tracker
+ org.apache.karaf.util.tracker,
+ org.apache.http*
</Private-Package>
<Bundle-Activator>
org.apache.karaf.jaas.modules.impl.Activator
http://git-wip-us.apache.org/repos/asf/karaf/blob/eb821774/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
new file mode 100644
index 0000000..cdc3f30
--- /dev/null
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * under the License.
+ */
+package org.apache.karaf.jaas.modules.syncope;
+
+import org.apache.http.HttpStatus;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.karaf.jaas.modules.AbstractKarafLoginModule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.LoginException;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.*;
+
+/**
+ * Karaf login module which uses Apache Syncope backend.
+ */
+public class SyncopeLoginModule extends AbstractKarafLoginModule {
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(SyncopeLoginModule.class);
+
+ public final static String ADDRESS = "address";
+
+ private String address;
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
+ super.initialize(subject, callbackHandler, options);
+ address = (String) options.get(ADDRESS);
+ }
+
+ public boolean login() throws LoginException {
+ Callback[] callbacks = new Callback[2];
+ callbacks[0] = new NameCallback("Username: ");
+ callbacks[1] = new PasswordCallback("Password: ", false);
+
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (IOException ioException) {
+ throw new LoginException(ioException.getMessage());
+ } catch (UnsupportedCallbackException unsupportedCallbackException) {
+ throw new LoginException(unsupportedCallbackException.getMessage() + " not available to obtain information from user.");
+ }
+
+ user = ((NameCallback) callbacks[0]).getName();
+
+ char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
+ if (tmpPassword == null) {
+ tmpPassword = new char[0];
+ }
+ String password = new String(tmpPassword);
+ principals = new HashSet<Principal>();
+
+ // authenticate the user on Syncope
+ LOGGER.debug("Authenticate user {} on Syncope located {}", user, address);
+ CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+ credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));
+ CloseableHttpClient client = HttpClients.createDefault();
+ HttpClientContext context = HttpClientContext.create();
+ context.setCredentialsProvider(credentialsProvider);
+ HttpGet get = new HttpGet(address + "/users/self");
+ try {
+ CloseableHttpResponse response = client.execute(get, context);
+ LOGGER.info("Response: " + response.getStatusLine().getStatusCode());
+ if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+ LOGGER.warn("User {} not authenticated", user);
+ return false;
+ }
+ } catch (Exception e) {
+ LOGGER.error("User {} authentication failed", user, e);
+ throw new LoginException("User " + user + " authentication failed: " + e.getMessage());
+ }
+
+ LOGGER.warn("User {} authenticated", user);
+
+ return true;
+ }
+
+ public boolean abort() {
+ return true;
+ }
+
+ public boolean logout() throws LoginException {
+ subject.getPrincipals().removeAll(principals);
+ principals.clear();
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/eb821774/manual/src/main/webapp/developers-guide/security-framework.conf
----------------------------------------------------------------------
diff --git a/manual/src/main/webapp/developers-guide/security-framework.conf b/manual/src/main/webapp/developers-guide/security-framework.conf
index b994a22..49b8b26 100644
--- a/manual/src/main/webapp/developers-guide/security-framework.conf
+++ b/manual/src/main/webapp/developers-guide/security-framework.conf
@@ -48,6 +48,7 @@ Here are two examples using this schema:
</blueprint>
{pygmentize}
+
{pygmentize:xml}
<jaas:keystore xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0"
name="ks"
@@ -90,10 +91,6 @@ JMX layer), you need to deploy a JAAS configuration with the name {{name="karaf"
<!-- Bean to allow the $[karaf.base] property to be correctly resolved -->
<ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
- <type-converters>
- <bean class="org.apache.karaf.jaas.modules.properties.PropertiesConverter"/>
- </type-converters>
-
<jaas:config name="karaf" rank="1">
<jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule"
flags="required">
@@ -296,6 +293,25 @@ default {{karaf}} realm):
</jaas:config>
{code}
+h3. SyncopeLoginModule
+
+The Syncope login module uses the Syncope REST API to authenticate users and retrieve the roles.
+
+The Syncope login module just requires one parameter:
+
+|| Name || Description ||
+| {{address}} | Location of the Syncope REST API |
+
+The following snippet shows how to use Syncope with the karaf realm:
+
+{code}
+<jaas:config name="karaf" rank="2">
+ <jaas:module className="org.apache.karaf.jaas.modules.syncope.SyncopeLoginModule" flags="required">
+ address=http://localhost:9080/syncope/cxf
+ </jaas:module>
+</jaas:config>
+{code}
+
h2. Encryption service
The [EncryptionService|http://svn.apache.org/repos/asf/karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/EncryptionService.java] is a service registered in the OSGi registry providing means to encrypt and check encrypted passwords. This service acts as a factory for [Encryption|http://svn.apache.org/repos/asf/karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/Encryption.java] objects actually performing the encryption.
http://git-wip-us.apache.org/repos/asf/karaf/blob/eb821774/manual/src/main/webapp/users-guide/security.conf
----------------------------------------------------------------------
diff --git a/manual/src/main/webapp/users-guide/security.conf b/manual/src/main/webapp/users-guide/security.conf
index 1d601c0..640c4b7 100644
--- a/manual/src/main/webapp/users-guide/security.conf
+++ b/manual/src/main/webapp/users-guide/security.conf
@@ -43,6 +43,7 @@ Apache Karaf provides additional login modules (see the developer guide for deta
* JDBCLoginModule uses a database as backend
* LDAPLoginModule uses a LDAP server as backend
+* SyncopeLoginModule uses Apache Syncope as backend
* OsgiConfigLoginModule uses a configuration as backend
You can manage an existing realm, login module, or create your own realm using the {{jaas:realm-manage}} command.
[4/7] git commit: Continue the SyncopeBackingEngine
Posted by jb...@apache.org.
Continue the SyncopeBackingEngine
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/2ff6b0e5
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/2ff6b0e5
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/2ff6b0e5
Branch: refs/heads/master
Commit: 2ff6b0e5f5392baf1e18930e1ed90fc5d966d131
Parents: b050fe2
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Thu Aug 14 16:00:03 2014 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Thu Aug 14 16:00:03 2014 +0200
----------------------------------------------------------------------
.../modules/syncope/SyncopeBackingEngine.java | 81 ++++++++++++++++----
.../modules/syncope/SyncopeLoginModule.java | 38 ++++-----
2 files changed, 85 insertions(+), 34 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/2ff6b0e5/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
index bec9dc9..d8e471d 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
@@ -22,6 +22,7 @@ import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.karaf.jaas.boot.principal.GroupPrincipal;
@@ -31,6 +32,7 @@ import org.apache.karaf.jaas.modules.BackingEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.naming.OperationNotSupportedException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
@@ -56,6 +58,24 @@ public class SyncopeBackingEngine implements BackingEngine {
throw new IllegalArgumentException("Group prefix " + GROUP_PREFIX + " not permitted with Syncope backend");
}
HttpPost request = new HttpPost(address + "/users");
+ String userTO = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
+ "<user>" +
+ "<attributes>" +
+ "<attribute><readonly>false</readonly><schema>fullname</schema><value>" + username + "</value></attribute>" +
+ "<attribute><readonly>false</readonly><schema>surname</schema><value>" + username + "</value></attribute>" +
+ "<attribute><readonly>false</readonly><schema>userId</schema><value>" + username + "@karaf.apache.org</value></attribute>" +
+ "</attributes>" +
+ "<password>" + password + "</password>" +
+ "<username>" + username + "</username>" +
+ "</user>";
+ try {
+ StringEntity entity = new StringEntity(userTO);
+ request.setEntity(entity);
+ HttpResponse response = client.execute(request);
+ } catch (Exception e) {
+ logger.error("Can't add user {}", username, e);
+ throw new RuntimeException("Can't add user " + username, e);
+ }
}
public void deleteUser(String username) {
@@ -64,36 +84,65 @@ public class SyncopeBackingEngine implements BackingEngine {
}
HttpDelete request = new HttpDelete(address + "/users/" + username);
try {
- HttpResponse response = client.execute(request);
- logger.warn("Status code: " + response.getStatusLine().getStatusCode());
- logger.warn(EntityUtils.toString(response.getEntity()));
+ client.execute(request);
} catch (Exception e) {
- throw new RuntimeException("Error deleting user", e);
+ logger.error("Can't delete user {}", username, e);
+ throw new RuntimeException("Can't delete user " + username, e);
}
}
public List<UserPrincipal> listUsers() {
+ List<UserPrincipal> users = new ArrayList<>();
HttpGet request = new HttpGet(address + "/users");
try {
HttpResponse response = client.execute(request);
- logger.warn("Status code: " + response.getStatusLine().getStatusCode());
- logger.warn(EntityUtils.toString(response.getEntity()));
+ String responseTO = EntityUtils.toString(response.getEntity());
+ if (responseTO != null && !responseTO.isEmpty()) {
+ // extracting the user
+ int index = responseTO.indexOf("<username>");
+ while (index != -1) {
+ responseTO = responseTO.substring(index + "<username>".length());
+ int end = responseTO.indexOf("</username>");
+ if (end == -1) {
+ index = -1;
+ }
+ String username = responseTO.substring(0, end);
+ users.add(new UserPrincipal(username));
+ responseTO = responseTO.substring(end + "</username>".length());
+ index = responseTO.indexOf("<username>");
+ }
+ }
} catch (Exception e) {
- throw new RuntimeException("Error listing user", e);
+ throw new RuntimeException("Error listing users", e);
}
- return new ArrayList<UserPrincipal>();
+ return users;
}
public List<RolePrincipal> listRoles(Principal principal) {
- HttpGet request = new HttpGet(address + "/users/" + principal.getName());
+ List<RolePrincipal> roles = new ArrayList<>();
+ HttpGet request = new HttpGet(address + "/users?username=" + principal.getName());
try {
HttpResponse response = client.execute(request);
- logger.warn("Status code: " + response.getStatusLine().getStatusCode());
- logger.warn(EntityUtils.toString(response.getEntity()));
+ String responseTO = EntityUtils.toString(response.getEntity());
+ if (responseTO != null && !responseTO.isEmpty()) {
+ int index = responseTO.indexOf("<roleName>");
+ while (index != 1) {
+ responseTO = responseTO.substring(index + "<roleName>".length());
+ int end = responseTO.indexOf("</roleName>");
+ if (end == -1) {
+ index = -1;
+ break;
+ }
+ String role = responseTO.substring(0, end);
+ roles.add(new RolePrincipal(role));
+ responseTO = responseTO.substring(end + "</roleName>".length());
+ index = responseTO.indexOf("<roleName>");
+ }
+ }
} catch (Exception e) {
throw new RuntimeException("Error listing roles", e);
}
- return new ArrayList<RolePrincipal>();
+ return roles;
}
public void addRole(String username, String role) {
@@ -109,19 +158,19 @@ public class SyncopeBackingEngine implements BackingEngine {
}
public void addGroup(String username, String group) {
-
+ throw new RuntimeException("Group management is not supported by Syncope backend");
}
public void deleteGroup(String username, String group) {
-
+ throw new RuntimeException("Group management is not supported by Syncope backend");
}
public void addGroupRole(String group, String role) {
-
+ throw new RuntimeException("Group management is not supported by Syncope backend");
}
public void deleteGroupRole(String group, String role) {
-
+ throw new RuntimeException("Group management is not supported by Syncope backend");
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2ff6b0e5/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
index 582ddda..47cbd0f 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
@@ -116,26 +116,28 @@ public class SyncopeLoginModule extends AbstractKarafLoginModule {
*/
protected List<String> extractingRoles(String response) throws Exception {
List<String> roles = new ArrayList<String>();
- // extract the <memberships> element
- int index = response.indexOf("<memberships>");
- response = response.substring(index + "<memberships>".length());
- index = response.indexOf("</memberships>");
- response = response.substring(0, index);
-
- // looking for the roleName elements
- index = response.indexOf("<roleName>");
- while (index != -1) {
- response = response.substring(index + "<roleName>".length());
- int end = response.indexOf("</roleName>");
- if (end == -1) {
- index = -1;
- }
- String role = response.substring(0, end);
- roles.add(role);
- response = response.substring(end + "</roleName>".length());
+ if (response != null && !response.isEmpty()) {
+ // extract the <memberships> element
+ int index = response.indexOf("<memberships>");
+ response = response.substring(index + "<memberships>".length());
+ index = response.indexOf("</memberships>");
+ response = response.substring(0, index);
+
+ // looking for the roleName elements
index = response.indexOf("<roleName>");
- }
+ while (index != -1) {
+ response = response.substring(index + "<roleName>".length());
+ int end = response.indexOf("</roleName>");
+ if (end == -1) {
+ index = -1;
+ }
+ String role = response.substring(0, end);
+ roles.add(role);
+ response = response.substring(end + "</roleName>".length());
+ index = response.indexOf("<roleName>");
+ }
+ }
return roles;
}
[2/7] git commit: Merge branch 'master' into SYNCOPE_LM
Posted by jb...@apache.org.
Merge branch 'master' into SYNCOPE_LM
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/972a14d3
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/972a14d3
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/972a14d3
Branch: refs/heads/master
Commit: 972a14d30b3ea6520c2b0cbc627c32f4d1eeaf94
Parents: eb82177 9e42abd
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Wed Aug 13 08:17:17 2014 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Wed Aug 13 08:17:17 2014 +0200
----------------------------------------------------------------------
client/pom.xml | 5 ----
.../org/apache/karaf/client/ClientConfig.java | 31 +++++++++++++++++---
2 files changed, 27 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
[7/7] git commit: Update SyncopeLoginModule documentation
Posted by jb...@apache.org.
Update SyncopeLoginModule documentation
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/7f1ed9b2
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/7f1ed9b2
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/7f1ed9b2
Branch: refs/heads/master
Commit: 7f1ed9b26bb71bf0caf5a3b38dfa2cc958efeb3f
Parents: 27a86f3
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Thu Aug 14 21:50:17 2014 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Thu Aug 14 21:50:17 2014 +0200
----------------------------------------------------------------------
.../developers-guide/security-framework.conf | 30 ++++++++++++++++++++
1 file changed, 30 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1ed9b2/manual/src/main/webapp/developers-guide/security-framework.conf
----------------------------------------------------------------------
diff --git a/manual/src/main/webapp/developers-guide/security-framework.conf b/manual/src/main/webapp/developers-guide/security-framework.conf
index 49b8b26..6c12cad 100644
--- a/manual/src/main/webapp/developers-guide/security-framework.conf
+++ b/manual/src/main/webapp/developers-guide/security-framework.conf
@@ -301,6 +301,8 @@ The Syncope login module just requires one parameter:
|| Name || Description ||
| {{address}} | Location of the Syncope REST API |
+| {{admin.user}} | Admin username to administrate Syncope (only required by the backend engine) |
+| {{admin.password}} | Admin password to administrate Syncope (only required by the backend engine) |
The following snippet shows how to use Syncope with the karaf realm:
@@ -308,10 +310,38 @@ The following snippet shows how to use Syncope with the karaf realm:
<jaas:config name="karaf" rank="2">
<jaas:module className="org.apache.karaf.jaas.modules.syncope.SyncopeLoginModule" flags="required">
address=http://localhost:9080/syncope/cxf
+ admin.user=admin
+ admin.password=password
</jaas:module>
</jaas:config>
{code}
+SyncopeLoginModule comes with a backend engine allowing to manipulate users and roles. You have to register the
+SyncopeBackendEngineFactory service.
+For instance, the following blueprint descriptor enables the SyncopeLoginModule and the backend engine factory:
+
+{code}
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0"
+ xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
+
+ <jaas:config name="karaf" rank="2">
+ <jaas:module className="org.apache.karaf.jaas.modules.syncope.SyncopeLoginModule"
+ flags="required">
+ address=http://localhost:9080/syncope/cxf
+ admin.user=admin
+ admin.password=password
+ </jaas:module>
+ </jaas:config>
+
+ <service interface="org.apache.karaf.jaas.modules.BackingEngineFactory">
+ <bean class="org.apache.karaf.jaas.modules.syncope.SyncopeBackingEngineFactory"/>
+ </service>
+
+</blueprint>
+{code}
+
h2. Encryption service
The [EncryptionService|http://svn.apache.org/repos/asf/karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/EncryptionService.java] is a service registered in the OSGi registry providing means to encrypt and check encrypted passwords. This service acts as a factory for [Encryption|http://svn.apache.org/repos/asf/karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/Encryption.java] objects actually performing the encryption.
[6/7] git commit: Merge branch 'master' into SYNCOPE_LM
Posted by jb...@apache.org.
Merge branch 'master' into SYNCOPE_LM
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/27a86f3f
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/27a86f3f
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/27a86f3f
Branch: refs/heads/master
Commit: 27a86f3f45bcfdadce0cc8fbbb193506b2f3b07c
Parents: b02ec41 4a53ed8
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Thu Aug 14 21:42:23 2014 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Thu Aug 14 21:42:23 2014 +0200
----------------------------------------------------------------------
manual/src/main/webapp/users-guide/provisioning.conf | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
[5/7] git commit: Throw exception for operation not supported in the
Syncope backend
Posted by jb...@apache.org.
Throw exception for operation not supported in the Syncope backend
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/b02ec414
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/b02ec414
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/b02ec414
Branch: refs/heads/master
Commit: b02ec41495073925bc38ab0e7146880674c902df
Parents: 2ff6b0e
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Thu Aug 14 21:41:41 2014 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Thu Aug 14 21:41:41 2014 +0200
----------------------------------------------------------------------
.../apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/b02ec414/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
index d8e471d..306b311 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
@@ -146,11 +146,11 @@ public class SyncopeBackingEngine implements BackingEngine {
}
public void addRole(String username, String role) {
-
+ throw new RuntimeException("Roles management should be done on the Syncope side");
}
public void deleteRole(String username, String role) {
-
+ throw new RuntimeException("Roles management should be done on the Syncope side");
}
public List<GroupPrincipal> listGroups(UserPrincipal principal) {
[3/7] git commit: Add Syncope backend engine support
Posted by jb...@apache.org.
Add Syncope backend engine support
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/b050fe28
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/b050fe28
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/b050fe28
Branch: refs/heads/master
Commit: b050fe28c1604c457257dcd8cbea52b428eee4d1
Parents: 972a14d
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Wed Aug 13 13:50:58 2014 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Wed Aug 13 13:50:58 2014 +0200
----------------------------------------------------------------------
jaas/modules/pom.xml | 11 +-
.../modules/syncope/SyncopeBackingEngine.java | 127 +++++++++++++++++++
.../syncope/SyncopeBackingEngineFactory.java | 51 ++++++++
.../modules/syncope/SyncopeLoginModule.java | 67 ++++++++--
.../modules/syncope/SyncopeLoginModuleTest.java | 105 +++++++++++++++
5 files changed, 343 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/b050fe28/jaas/modules/pom.xml
----------------------------------------------------------------------
diff --git a/jaas/modules/pom.xml b/jaas/modules/pom.xml
index a6c15f0..2c6d01c 100644
--- a/jaas/modules/pom.xml
+++ b/jaas/modules/pom.xml
@@ -96,7 +96,8 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient-osgi</artifactId>
+ <artifactId>httpclient</artifactId>
+ <scope>provided</scope>
<version>4.3.5</version>
</dependency>
@@ -150,16 +151,16 @@
javax.net,
org.apache.karaf.jaas.config,
org.osgi.service.event;resolution:=optional,
- net.sf.ehcache*;resolution:=optional,
- net.spy.memcached*;resolution:=optional,
- org.apache.commons.codec*;resolution:=optional,
+ !net.sf.ehcache*,
+ !net.spy.memcached*,
*
</Import-Package>
<Private-Package>
org.apache.karaf.jaas.modules.impl,
org.apache.felix.utils.properties,
org.apache.karaf.util.tracker,
- org.apache.http*
+ org.apache.http*,
+ org.apache.commons.codec*
</Private-Package>
<Bundle-Activator>
org.apache.karaf.jaas.modules.impl.Activator
http://git-wip-us.apache.org/repos/asf/karaf/blob/b050fe28/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
new file mode 100644
index 0000000..bec9dc9
--- /dev/null
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngine.java
@@ -0,0 +1,127 @@
+/*
+ * 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.karaf.jaas.modules.syncope;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.apache.karaf.jaas.boot.principal.GroupPrincipal;
+import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+import org.apache.karaf.jaas.boot.principal.UserPrincipal;
+import org.apache.karaf.jaas.modules.BackingEngine;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SyncopeBackingEngine implements BackingEngine {
+
+ private final Logger logger = LoggerFactory.getLogger(SyncopeBackingEngine.class);
+
+ private String address;
+
+ private DefaultHttpClient client;
+
+ public SyncopeBackingEngine(String address, String adminUser, String adminPassword) {
+ this.address = address;
+
+ client = new DefaultHttpClient();
+ Credentials creds = new UsernamePasswordCredentials(adminUser, adminPassword);
+ client.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
+ }
+
+ public void addUser(String username, String password) {
+ if (username.startsWith(GROUP_PREFIX)) {
+ throw new IllegalArgumentException("Group prefix " + GROUP_PREFIX + " not permitted with Syncope backend");
+ }
+ HttpPost request = new HttpPost(address + "/users");
+ }
+
+ public void deleteUser(String username) {
+ if (username.startsWith(GROUP_PREFIX)) {
+ throw new IllegalArgumentException("Group prefix " + GROUP_PREFIX + " not permitted with Syncope backend");
+ }
+ HttpDelete request = new HttpDelete(address + "/users/" + username);
+ try {
+ HttpResponse response = client.execute(request);
+ logger.warn("Status code: " + response.getStatusLine().getStatusCode());
+ logger.warn(EntityUtils.toString(response.getEntity()));
+ } catch (Exception e) {
+ throw new RuntimeException("Error deleting user", e);
+ }
+ }
+
+ public List<UserPrincipal> listUsers() {
+ HttpGet request = new HttpGet(address + "/users");
+ try {
+ HttpResponse response = client.execute(request);
+ logger.warn("Status code: " + response.getStatusLine().getStatusCode());
+ logger.warn(EntityUtils.toString(response.getEntity()));
+ } catch (Exception e) {
+ throw new RuntimeException("Error listing user", e);
+ }
+ return new ArrayList<UserPrincipal>();
+ }
+
+ public List<RolePrincipal> listRoles(Principal principal) {
+ HttpGet request = new HttpGet(address + "/users/" + principal.getName());
+ try {
+ HttpResponse response = client.execute(request);
+ logger.warn("Status code: " + response.getStatusLine().getStatusCode());
+ logger.warn(EntityUtils.toString(response.getEntity()));
+ } catch (Exception e) {
+ throw new RuntimeException("Error listing roles", e);
+ }
+ return new ArrayList<RolePrincipal>();
+ }
+
+ public void addRole(String username, String role) {
+
+ }
+
+ public void deleteRole(String username, String role) {
+
+ }
+
+ public List<GroupPrincipal> listGroups(UserPrincipal principal) {
+ return new ArrayList<GroupPrincipal>();
+ }
+
+ public void addGroup(String username, String group) {
+
+ }
+
+ public void deleteGroup(String username, String group) {
+
+ }
+
+ public void addGroupRole(String group, String role) {
+
+ }
+
+ public void deleteGroupRole(String group, String role) {
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/b050fe28/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngineFactory.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngineFactory.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngineFactory.java
new file mode 100644
index 0000000..f3a85a5
--- /dev/null
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeBackingEngineFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.jaas.modules.syncope;
+
+import org.apache.karaf.jaas.modules.BackingEngine;
+import org.apache.karaf.jaas.modules.BackingEngineFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+public class SyncopeBackingEngineFactory implements BackingEngineFactory {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SyncopeBackingEngineFactory.class);
+
+ public BackingEngine build(Map<String, ?> options) {
+ SyncopeBackingEngine instance = null;
+ String address = (String) options.get(SyncopeLoginModule.ADDRESS);
+ String adminUser = (String) options.get(SyncopeLoginModule.ADMIN_USER);
+ String adminPassword = (String) options.get(SyncopeLoginModule.ADMIN_PASSWORD);
+
+ try {
+ instance = new SyncopeBackingEngine(address, adminUser, adminPassword);
+ } catch (Exception e) {
+ LOGGER.error("Error creating the Syncope backing engine", e);
+ }
+
+ return instance;
+ }
+
+ /**
+ * Returns the login module class, that this factory can build.
+ */
+ public String getModuleClass() {
+ return SyncopeLoginModule.class.getName();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/b050fe28/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
index cdc3f30..582ddda 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModule.java
@@ -16,14 +16,14 @@ package org.apache.karaf.jaas.modules.syncope;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+import org.apache.karaf.jaas.boot.principal.UserPrincipal;
import org.apache.karaf.jaas.modules.AbstractKarafLoginModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,6 +43,8 @@ public class SyncopeLoginModule extends AbstractKarafLoginModule {
private final static Logger LOGGER = LoggerFactory.getLogger(SyncopeLoginModule.class);
public final static String ADDRESS = "address";
+ public final static String ADMIN_USER = "admin.user"; // for the backing engine
+ public final static String ADMIN_PASSWORD = "admin.password"; // for the backing engine
private String address;
@@ -75,29 +77,68 @@ public class SyncopeLoginModule extends AbstractKarafLoginModule {
// authenticate the user on Syncope
LOGGER.debug("Authenticate user {} on Syncope located {}", user, address);
- CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
- credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));
- CloseableHttpClient client = HttpClients.createDefault();
- HttpClientContext context = HttpClientContext.create();
- context.setCredentialsProvider(credentialsProvider);
+ DefaultHttpClient client = new DefaultHttpClient();
+ Credentials creds = new UsernamePasswordCredentials(user, password);
+ client.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpGet get = new HttpGet(address + "/users/self");
+ List<String> roles = new ArrayList<String>();
try {
- CloseableHttpResponse response = client.execute(get, context);
- LOGGER.info("Response: " + response.getStatusLine().getStatusCode());
+ CloseableHttpResponse response = client.execute(get);
+ LOGGER.debug("Syncope HTTP response status code: {}", response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
LOGGER.warn("User {} not authenticated", user);
return false;
}
+ LOGGER.debug("User {} authenticated", user);
+ LOGGER.debug("Populating principals with user");
+ principals.add(new UserPrincipal(user));
+ LOGGER.debug("Retrieving user {} roles", user);
+ roles = extractingRoles(EntityUtils.toString(response.getEntity()));
} catch (Exception e) {
LOGGER.error("User {} authentication failed", user, e);
throw new LoginException("User " + user + " authentication failed: " + e.getMessage());
}
- LOGGER.warn("User {} authenticated", user);
+ LOGGER.debug("Populating principals with roles");
+ for (String role : roles) {
+ principals.add(new RolePrincipal(role));
+ }
return true;
}
+ /**
+ * Extract the user roles from the Syncope entity response.
+ *
+ * @param response the HTTP response from Syncope.
+ * @return the list of user roles.
+ * @throws Exception in case of extraction failure.
+ */
+ protected List<String> extractingRoles(String response) throws Exception {
+ List<String> roles = new ArrayList<String>();
+ // extract the <memberships> element
+ int index = response.indexOf("<memberships>");
+ response = response.substring(index + "<memberships>".length());
+ index = response.indexOf("</memberships>");
+ response = response.substring(0, index);
+
+ // looking for the roleName elements
+ index = response.indexOf("<roleName>");
+ while (index != -1) {
+ response = response.substring(index + "<roleName>".length());
+ int end = response.indexOf("</roleName>");
+ if (end == -1) {
+ index = -1;
+ }
+ String role = response.substring(0, end);
+ roles.add(role);
+ response = response.substring(end + "</roleName>".length());
+ index = response.indexOf("<roleName>");
+ }
+
+ return roles;
+ }
+
public boolean abort() {
return true;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/b050fe28/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModuleTest.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModuleTest.java b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModuleTest.java
new file mode 100644
index 0000000..eca0818
--- /dev/null
+++ b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/syncope/SyncopeLoginModuleTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.karaf.jaas.modules.syncope;
+
+import org.junit.Test;
+import org.junit.Assert;
+
+import java.util.List;
+
+public class SyncopeLoginModuleTest {
+
+ @Test
+ public void testRolesExtraction() throws Exception {
+ String syncopeResponse = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
+ "<user>\n" +
+ " <attributes>\n" +
+ " <attribute>\n" +
+ " <readonly>false</readonly>\n" +
+ " <schema>cool</schema>\n" +
+ " <value>false</value>\n" +
+ " </attribute>\n" +
+ " <attribute>\n" +
+ " <readonly>false</readonly>\n" +
+ " <schema>email</schema>\n" +
+ " <value>karaf@example.net</value>\n" +
+ " </attribute>\n" +
+ " <attribute>\n" +
+ " <readonly>false</readonly>\n" +
+ " <schema>fullname</schema>\n" +
+ " <value>karaf</value>\n" +
+ " </attribute>\n" +
+ " <attribute>\n" +
+ " <readonly>false</readonly>\n" +
+ " <schema>gender</schema>\n" +
+ " <value>M</value>\n" +
+ " </attribute>\n" +
+ " <attribute>\n" +
+ " <readonly>false</readonly>\n" +
+ " <schema>surname</schema>\n" +
+ " <value>karaf</value>\n" +
+ " </attribute>\n" +
+ " <attribute>\n" +
+ " <readonly>false</readonly>\n" +
+ " <schema>userId</schema>\n" +
+ " <value>karaf@example.net</value>\n" +
+ " </attribute>\n" +
+ " </attributes>\n" +
+ " <derivedAttributes/>\n" +
+ " <id>100</id>\n" +
+ " <propagationStatuses/>\n" +
+ " <resources/>\n" +
+ " <virtualAttributes/>\n" +
+ " <creationDate>2014-08-12T18:37:09.202+02:00</creationDate>\n" +
+ " <failedLogins>0</failedLogins>\n" +
+ " <lastLoginDate>2014-08-13T09:38:02.204+02:00</lastLoginDate>\n" +
+ " <memberships>\n" +
+ " <membership>\n" +
+ " <attributes/>\n" +
+ " <derivedAttributes/>\n" +
+ " <id>100</id>\n" +
+ " <propagationStatuses/>\n" +
+ " <resources/>\n" +
+ " <virtualAttributes/>\n" +
+ " <resources/>\n" +
+ " <roleId>100</roleId>\n" +
+ " <roleName>admin</roleName>\n" +
+ " </membership>\n" +
+ " <membership>\n" +
+ " <attributes/>\n" +
+ " <derivedAttributes/>\n" +
+ " <id>101</id>\n" +
+ " <propagationStatuses/>\n" +
+ " <resources/>\n" +
+ " <virtualAttributes/>\n" +
+ " <resources/>\n" +
+ " <roleId>101</roleId>\n" +
+ " <roleName>another</roleName>\n" +
+ " </membership>\n" +
+ " </memberships>\n" +
+ " <password>36460D3A3C1E27C0DB2AF23344475EE712DD3C9D</password>\n" +
+ " <status>active</status>\n" +
+ " <username>karaf</username>\n" +
+ "</user>\n";
+ SyncopeLoginModule syncopeLoginModule = new SyncopeLoginModule();
+ List<String> roles = syncopeLoginModule.extractingRoles(syncopeResponse);
+ Assert.assertEquals(2, roles.size());
+ Assert.assertEquals("admin", roles.get(0));
+ Assert.assertEquals("another", roles.get(1));
+ }
+
+}