Provide dummy user manager for OS security model
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 20 Aug 2012 20:43:31 +0000 (20:43 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 20 Aug 2012 20:43:31 +0000 (20:43 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@5522 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml
security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml
security/modules/org.argeo.security.dao.os/META-INF/spring/security-os.xml
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/MatchingAuthenticationProvider.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/OsAuthenticationProvider.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java [new file with mode: 0644]

index e8a6c0d864f5d50ba853940a881fe14256af177a..3af0501ed0377b145b974d4745f5cfa33d1bc5ec 100644 (file)
        <service ref="authenticationManager"\r
                interface="org.springframework.security.AuthenticationManager"\r
                context-class-loader="service-provider" />\r
-       <!-- <service ref="ldapAuthenticationProvider" -->\r
-       <!-- interface="org.springframework.security.providers.AuthenticationProvider" -->\r
-       <!-- context-class-loader="service-provider" /> -->\r
 \r
+       <!-- User management -->\r
        <service ref="userDetailsManager"\r
                interface="org.springframework.security.userdetails.UserDetailsService"\r
                context-class-loader="service-provider" />\r
index 493d80a8be1cb4e2b63e4fcd02e395347896d9ca..8c6977a687e3406e7cf73cdbec7ef2fa1f7b1b7b 100644 (file)
 \r
        <service ref="systemExecutionService" interface="org.argeo.security.SystemExecutionService" />\r
 \r
+       <!-- User management -->\r
+       <service ref="userDetailsManager"\r
+               interface="org.springframework.security.userdetails.UserDetailsService"\r
+               context-class-loader="service-provider" />\r
+       <service ref="userDetailsManager"\r
+               interface="org.springframework.security.userdetails.UserDetailsManager"\r
+               context-class-loader="service-provider" />\r
+       <service ref="userDetailsManager" interface="org.argeo.security.UserAdminService"\r
+               context-class-loader="service-provider" />\r
+\r
 </beans:beans>
\ No newline at end of file
index 33b4be32fe18d3d4a63b58a6028169548363921e..41b23cc092c1abe8397b7b22988df4b1704284bb 100644 (file)
                <property name="authenticationManager" ref="internalAuthenticationManager" />
        </bean>
 
+       <!-- Dummy user manager -->
+       <bean id="userDetailsManager" class="org.argeo.security.jcr.OsJcrUserAdminService"
+               init-method="init" destroy-method="destroy">
+               <property name="repository" ref="nodeRepository" />
+       </bean>
+
 </beans>
\ No newline at end of file
index 29f956eb2c8361dcf73ac43f4986e41fe4752b11..c020c2a5c768f79f89e7da8838d2b5384703e3ef 100644 (file)
@@ -30,6 +30,8 @@ import org.springframework.security.providers.dao.AbstractUserDetailsAuthenticat
 import org.springframework.security.userdetails.User;
 import org.springframework.security.userdetails.UserDetails;
 
+/** @deprecated */
+@Deprecated
 public class MatchingAuthenticationProvider extends
                AbstractUserDetailsAuthenticationProvider {
 
index 33a4f6376326bf37571e18220e97e515ba446020..d613545674de1e780872d52d8bd15aa9e6ed5d4a 100644 (file)
@@ -29,21 +29,22 @@ import org.springframework.security.providers.AuthenticationProvider;
  * Validates an OS authentication. The id is that it will always be
  * authenticated since we are always runnign within an OS, but the fact that the
  * {@link Authentication} works properly depends on the proper OS login module
- * having been called as well.
+ * having been called as well. TODO make it more configurable (base roles, is
+ * admin)
  */
 public class OsAuthenticationProvider implements AuthenticationProvider {
-       private String osUserRole = "ROLE_OS_USER";
-       private String userRole = "ROLE_USER";
-       private String adminRole = "ROLE_ADMIN";
+       final static String osUserRole = "ROLE_OS_USER";
+       final static String userRole = "ROLE_USER";
+       final static String adminRole = "ROLE_ADMIN";
 
-       private Boolean isAdmin = true;
+       final static Boolean isAdmin = true;
 
        public Authentication authenticate(Authentication authentication)
                        throws AuthenticationException {
                return new OsAuthenticationToken(getBaseAuthorities());
        }
 
-       protected GrantedAuthority[] getBaseAuthorities() {
+       public static GrantedAuthority[] getBaseAuthorities() {
                List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
                auths.add(new GrantedAuthorityImpl(osUserRole));
                auths.add(new GrantedAuthorityImpl(userRole));
@@ -57,20 +58,4 @@ public class OsAuthenticationProvider implements AuthenticationProvider {
                return OsAuthenticationToken.class.isAssignableFrom(authentication);
        }
 
-       public void setOsUserRole(String osUserRole) {
-               this.osUserRole = osUserRole;
-       }
-
-       public void setUserRole(String userRole) {
-               this.userRole = userRole;
-       }
-
-       public void setAdminRole(String adminRole) {
-               this.adminRole = adminRole;
-       }
-
-       public void setIsAdmin(Boolean isAdmin) {
-               this.isAdmin = isAdmin;
-       }
-
 }
index 4f3e6a18e5a5ff0e3c4bf058c3664d915b79cbc2..917733dbcb5a059c5389445908fc4ee27e3885da 100644 (file)
@@ -19,7 +19,6 @@ import javax.jcr.Node;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.security.Privilege;
 
 import org.argeo.ArgeoException;
 import org.argeo.jcr.JcrUtils;
@@ -27,6 +26,9 @@ import org.argeo.security.OsAuthenticationToken;
 import org.argeo.security.core.OsAuthenticationProvider;
 import org.springframework.security.Authentication;
 import org.springframework.security.AuthenticationException;
+import org.springframework.security.BadCredentialsException;
+import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
+import org.springframework.security.userdetails.UserDetails;
 
 /** Relies on OS to authenticate and additionally setup JCR */
 public class OsJcrAuthenticationProvider extends OsAuthenticationProvider {
@@ -35,6 +37,8 @@ public class OsJcrAuthenticationProvider extends OsAuthenticationProvider {
        private Session securitySession;
        private Session nodeSession;
 
+       private UserDetails userDetails;
+
        public void init() {
                try {
                        securitySession = repository.login(securityWorkspace);
@@ -51,39 +55,50 @@ public class OsJcrAuthenticationProvider extends OsAuthenticationProvider {
 
        public Authentication authenticate(Authentication authentication)
                        throws AuthenticationException {
-               final OsAuthenticationToken authen = (OsAuthenticationToken) super
-                               .authenticate(authentication);
-               try {
-                       // WARNING: at this stage we assume that the java properties
-                       // will have the same value
-                       String username = System.getProperty("user.name");
-                       Node userProfile = JcrUtils.createUserProfileIfNeeded(
-                                       securitySession, username);
-                       JcrUserDetails.checkAccountStatus(userProfile);
-
-                       // each user should have a writable area in the default workspace of
-                       // the node
-                       Node userNodeHome = JcrUtils.createUserHomeIfNeeded(nodeSession,
-                                       username);
-                       // FIXME how to set user home privileges *before* it is created ?
-                       // JcrUtils.addPrivilege(nodeSession, userNodeHome.getPath(),
-                       // username, Privilege.JCR_ALL);
-                       // if (nodeSession.hasPendingChanges())
-                       // nodeSession.save();
-
-                       // user details
-                       JcrUserDetails userDetails = new JcrUserDetails(userProfile, authen
-                                       .getCredentials().toString(), getBaseAuthorities());
+               if (authentication instanceof UsernamePasswordAuthenticationToken) {
+                       // deal with remote access to internal server
+                       // FIXME very primitive and unsecure at this stage
+                       // consider using the keyring for username / password authentication
+                       // or certificate
+                       UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication;
+                       if (!upat.getPrincipal().toString()
+                                       .equals(System.getProperty("user.name")))
+                               throw new BadCredentialsException("Wrong credentials");
+                       UsernamePasswordAuthenticationToken authen = new UsernamePasswordAuthenticationToken(
+                                       authentication.getPrincipal(),
+                                       authentication.getCredentials(), getBaseAuthorities());
                        authen.setDetails(userDetails);
-               } catch (RepositoryException e) {
-                       JcrUtils.discardQuietly(securitySession);
-                       throw new ArgeoException(
-                                       "Unexpected exception when synchronizing OS and JCR security ",
-                                       e);
-               } finally {
-                       JcrUtils.logoutQuietly(securitySession);
+                       return authen;
+               } else if (authentication instanceof OsAuthenticationToken) {
+                       OsAuthenticationToken authen = (OsAuthenticationToken) super
+                                       .authenticate(authentication);
+                       try {
+                               // WARNING: at this stage we assume that the java properties
+                               // will have the same value
+                               String username = System.getProperty("user.name");
+                               Node userProfile = JcrUtils.createUserProfileIfNeeded(
+                                               securitySession, username);
+                               JcrUserDetails.checkAccountStatus(userProfile);
+
+                               // each user should have a writable area in the default
+                               // workspace of the node
+                               JcrUtils.createUserHomeIfNeeded(nodeSession, username);
+                               userDetails = new JcrUserDetails(userProfile, authen
+                                               .getCredentials().toString(), getBaseAuthorities());
+                               authen.setDetails(userDetails);
+                               return authen;
+                       } catch (RepositoryException e) {
+                               JcrUtils.discardQuietly(securitySession);
+                               throw new ArgeoException(
+                                               "Unexpected exception when synchronizing OS and JCR security ",
+                                               e);
+                       } finally {
+                               JcrUtils.logoutQuietly(securitySession);
+                       }
+               } else {
+                       throw new ArgeoException("Unsupported authentication "
+                                       + authentication.getClass());
                }
-               return authen;
        }
 
        public void setSecurityWorkspace(String securityWorkspace) {
@@ -93,4 +108,12 @@ public class OsJcrAuthenticationProvider extends OsAuthenticationProvider {
        public void setRepository(Repository repository) {
                this.repository = repository;
        }
+
+       @SuppressWarnings("rawtypes")
+       public boolean supports(Class authentication) {
+               return OsAuthenticationToken.class.isAssignableFrom(authentication)
+                               || UsernamePasswordAuthenticationToken.class
+                                               .isAssignableFrom(authentication);
+       }
+
 }
diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java
new file mode 100644 (file)
index 0000000..483cc40
--- /dev/null
@@ -0,0 +1,129 @@
+package org.argeo.security.jcr;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.UserAdminService;
+import org.springframework.dao.DataAccessException;
+import org.springframework.security.userdetails.UserDetails;
+import org.springframework.security.userdetails.UsernameNotFoundException;
+
+/**
+ * Dummy user service to be used when running as a single OS user (typically
+ * desktop). TODO integrate with JCR user / groups
+ */
+public class OsJcrUserAdminService implements UserAdminService {
+       private String securityWorkspace = "security";
+       private Repository repository;
+
+       private Session securitySession;
+
+       public void init() {
+               try {
+                       securitySession = repository.login(securityWorkspace);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot initialize", e);
+               }
+       }
+
+       public void destroy() {
+               JcrUtils.logoutQuietly(securitySession);
+       }
+
+       /** <b>Unsupported</b> */
+       public void createUser(UserDetails user) {
+               throw new UnsupportedOperationException();
+       }
+
+       /** Does nothing */
+       public void updateUser(UserDetails user) {
+
+       }
+
+       /** <b>Unsupported</b> */
+       public void deleteUser(String username) {
+               throw new UnsupportedOperationException();
+       }
+
+       /** <b>Unsupported</b> */
+       public void changePassword(String oldPassword, String newPassword) {
+               throw new UnsupportedOperationException();
+       }
+
+       public boolean userExists(String username) {
+               if (getSPropertyUsername().equals(username))
+                       return true;
+               else
+                       return false;
+       }
+
+       public UserDetails loadUserByUsername(String username)
+                       throws UsernameNotFoundException, DataAccessException {
+               if (getSPropertyUsername().equals(username)) {
+                       Node userProfile = JcrUtils.getUserProfile(securitySession,
+                                       username);
+                       JcrUserDetails userDetails;
+                       try {
+                               userDetails = new JcrUserDetails(userProfile, "",
+                                               OsJcrAuthenticationProvider.getBaseAuthorities());
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot retrieve user profile for "
+                                               + username, e);
+                       }
+                       return userDetails;
+               } else {
+                       throw new UnsupportedOperationException();
+               }
+       }
+
+       protected final String getSPropertyUsername() {
+               return System.getProperty("user.name");
+       }
+
+       public Set<String> listUsers() {
+               Set<String> set = new HashSet<String>();
+               set.add(getSPropertyUsername());
+               return set;
+       }
+
+       public Set<String> listUsersInRole(String role) {
+               Set<String> set = new HashSet<String>();
+               set.add(getSPropertyUsername());
+               return set;
+       }
+
+       /** Does nothing */
+       public void synchronize() {
+       }
+
+       /** <b>Unsupported</b> */
+       public void newRole(String role) {
+               throw new UnsupportedOperationException();
+       }
+
+       public Set<String> listEditableRoles() {
+               Set<String> set = new HashSet<String>();
+               return set;
+       }
+
+       /** <b>Unsupported</b> */
+       public void deleteRole(String role) {
+               throw new UnsupportedOperationException();
+       }
+
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+
+       public void setSecurityWorkspace(String securityWorkspace) {
+               this.securityWorkspace = securityWorkspace;
+       }
+
+}