diff --git a/community/security/src/main/java/org/neo4j/server/security/auth/BasicAuthManager.java b/community/security/src/main/java/org/neo4j/server/security/auth/BasicAuthManager.java
index 4b751129bfbe..25b9e150dea4 100644
--- a/community/security/src/main/java/org/neo4j/server/security/auth/BasicAuthManager.java
+++ b/community/security/src/main/java/org/neo4j/server/security/auth/BasicAuthManager.java
@@ -41,7 +41,7 @@
* so the given UserRepository should not be added to another LifeSupport.
*
*/
-public class BasicAuthManager implements AuthManager, UserManager
+public class BasicAuthManager implements AuthManager, UserManager, UserManagerSupplier
{
protected final AuthenticationStrategy authStrategy;
protected final UserRepository users;
@@ -206,4 +206,10 @@ private void assertValidName( String name )
throw new IllegalArgumentException( "User name contains illegal characters. Please use simple ascii characters and numbers." );
}
}
+
+ @Override
+ public UserManager getUserManager()
+ {
+ return this;
+ }
}
diff --git a/community/security/src/main/java/org/neo4j/server/security/auth/RateLimitedAuthenticationStrategy.java b/community/security/src/main/java/org/neo4j/server/security/auth/RateLimitedAuthenticationStrategy.java
index d8909e5619f7..8d0f163a620b 100644
--- a/community/security/src/main/java/org/neo4j/server/security/auth/RateLimitedAuthenticationStrategy.java
+++ b/community/security/src/main/java/org/neo4j/server/security/auth/RateLimitedAuthenticationStrategy.java
@@ -94,7 +94,7 @@ public AuthenticationResult authenticate( User user, String password)
{
AuthenticationMetadata authMetadata = authMetadataFor( user.name() );
- if ( !isAuthenticationPermitted( user.name() ) )
+ if ( !authMetadata.authenticationPermitted() )
{
return AuthenticationResult.TOO_MANY_ATTEMPTS;
}
diff --git a/community/security/src/main/java/org/neo4j/server/security/auth/UserManagerSupplier.java b/community/security/src/main/java/org/neo4j/server/security/auth/UserManagerSupplier.java
new file mode 100644
index 000000000000..f374c235e276
--- /dev/null
+++ b/community/security/src/main/java/org/neo4j/server/security/auth/UserManagerSupplier.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2002-2016 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.server.security.auth;
+
+public interface UserManagerSupplier
+{
+ UserManager getUserManager();
+}
diff --git a/community/server/src/main/java/org/neo4j/server/rest/dbms/UserService.java b/community/server/src/main/java/org/neo4j/server/rest/dbms/UserService.java
index c8282363f7e7..4756059b72aa 100644
--- a/community/server/src/main/java/org/neo4j/server/rest/dbms/UserService.java
+++ b/community/server/src/main/java/org/neo4j/server/rest/dbms/UserService.java
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.security.Principal;
import java.util.Map;
+import java.util.function.Supplier;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -41,6 +42,7 @@
import org.neo4j.server.rest.transactional.error.Neo4jError;
import org.neo4j.server.security.auth.User;
import org.neo4j.server.security.auth.UserManager;
+import org.neo4j.server.security.auth.UserManagerSupplier;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static org.neo4j.server.rest.web.CustomStatusType.UNPROCESSABLE;
@@ -56,11 +58,11 @@ public class UserService
public UserService( @Context AuthManager authManager, @Context InputFormat input, @Context OutputFormat output )
{
- if ( !(authManager instanceof UserManager) )
+ if ( !(authManager instanceof UserManagerSupplier) )
{
throw new IllegalArgumentException( "The provided auth manager is not capable of user management" );
}
- this.userManager = (UserManager) authManager;
+ this.userManager = ((UserManagerSupplier) authManager).getUserManager();
this.input = input;
this.output = output;
}
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/AuthProcedures.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/AuthProcedures.java
index 777617f639cd..0962fa474cd1 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/AuthProcedures.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/AuthProcedures.java
@@ -155,7 +155,7 @@ public Stream listUsers() throws IllegalCredentialsException, IOExce
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
EnterpriseUserManager userManager = shiroSubject.getUserManager();
- return shiroSubject.getUserManager().getAllUsernames().stream()
+ return userManager.getAllUsernames().stream()
.map( u -> new UserResult( u, userManager.getRoleNamesForUser( u ) ) );
}
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseAuthManagerFactory.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseAuthManagerFactory.java
index 427ba96fbfd9..369bf461925e 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseAuthManagerFactory.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseAuthManagerFactory.java
@@ -63,13 +63,12 @@ public AuthManager newInstance( Config config, LogProvider logProvider )
realms.add( internalRealm );
- if ( config.get( SecuritySettings.ldap_auth_enabled ) )
- {
- realms.add( new LdapRealm( config ) );
- }
-
if ( config.get( SecuritySettings.external_auth_enabled ) )
{
+ if ( config.get( SecuritySettings.ldap_auth_enabled ) )
+ {
+ realms.add( new LdapRealm( config ) );
+ }
// TODO: Load pluggable realms
}
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/FileUserRealm.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/FileUserRealm.java
index 540c6dde3461..f729f548fd2c 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/FileUserRealm.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/FileUserRealm.java
@@ -22,9 +22,11 @@
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.SimpleAuthenticationInfo;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.authc.credential.CredentialsMatcher;
+import org.apache.shiro.authc.DisabledAccountException;
+import org.apache.shiro.authc.ExcessiveAttemptsException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
@@ -47,6 +49,7 @@
import org.neo4j.graphdb.security.AuthorizationViolationException;
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthToken;
+import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.security.exception.IllegalCredentialsException;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;
import org.neo4j.server.security.auth.AuthenticationStrategy;
@@ -59,7 +62,7 @@
/**
* Shiro realm wrapping FileUserRepository
*/
-public class FileUserRealm extends AuthorizingRealm implements NeoLifecycleRealm, EnterpriseUserManager
+public class FileUserRealm extends AuthorizingRealm implements ShiroRealmLifecycle, EnterpriseUserManager
{
/**
* This flag is used in the same way as User.PASSWORD_CHANGE_REQUIRED, but it's
@@ -67,20 +70,6 @@ public class FileUserRealm extends AuthorizingRealm implements NeoLifecycleRealm
*/
public static final String IS_SUSPENDED = "is_suspended";
- private final CredentialsMatcher credentialsMatcher =
- ( AuthenticationToken token, AuthenticationInfo info ) ->
- {
- UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
- String infoUserName = (String) info.getPrincipals().getPrimaryPrincipal();
- Credential infoCredential = (Credential) info.getCredentials();
-
- boolean userNameMatches = infoUserName.equals( usernamePasswordToken.getUsername() );
- boolean credentialsMatches =
- infoCredential.matchesPassword( new String( usernamePasswordToken.getPassword() ) );
-
- return userNameMatches && credentialsMatches;
- };
-
private final RolePermissionResolver rolePermissionResolver = new RolePermissionResolver()
{
@Override
@@ -115,7 +104,7 @@ public FileUserRealm( UserRepository userRepository, RoleRepository roleReposito
this.passwordPolicy = passwordPolicy;
this.authenticationStrategy = authenticationStrategy;
this.authenticationEnabled = authenticationEnabled;
- setCredentialsMatcher( credentialsMatcher );
+ setCredentialsMatcher( new AllowAllCredentialsMatcher() );
setRolePermissionResolver( rolePermissionResolver );
roles = new PredefinedRolesBuilder().buildRoles();
@@ -210,9 +199,11 @@ protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token
ShiroAuthToken shiroAuthToken = (ShiroAuthToken) token;
String username;
+ String password;
try
{
username = AuthToken.safeCast( AuthToken.PRINCIPAL, shiroAuthToken.getMap() );
+ password = AuthToken.safeCast( AuthToken.CREDENTIALS, shiroAuthToken.getMap() );
}
catch ( InvalidAuthTokenException e )
{
@@ -222,24 +213,33 @@ protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token
User user = userRepository.getUserByName( username );
if ( user == null )
{
- throw new AuthenticationException( "User " + username + " does not exist" );
+ throw new UnknownAccountException();
}
- SimpleAuthenticationInfo authenticationInfo =
- new SimpleAuthenticationInfo( user.name(), user.credentials(), getName() );
+ AuthenticationResult result = authenticationStrategy.authenticate( user, password );
+
+ switch (result)
+ {
+ case FAILURE:
+ throw new IncorrectCredentialsException();
+ case TOO_MANY_ATTEMPTS:
+ throw new ExcessiveAttemptsException();
+ }
// TODO: This will not work if AuthenticationInfo is cached,
// unless you always do SecurityManager.logout properly (which will invalidate the cache)
// For REST we may need to connect HttpSessionListener.sessionDestroyed with logout
if ( user.hasFlag( FileUserRealm.IS_SUSPENDED ) )
{
- // We don' want un-authenticated users to learn anything about user suspension state
- // (normally this assertion is done by Shiro after we return from this method)
- assertCredentialsMatch( token, authenticationInfo );
- throw new AuthenticationException( "User " + user.name() + " is suspended" );
+ throw new DisabledAccountException( "User " + user.name() + " is suspended" );
}
- return authenticationInfo;
+ if ( user.passwordChangeRequired() )
+ {
+ result = AuthenticationResult.PASSWORD_CHANGE_REQUIRED;
+ }
+
+ return new ShiroAuthenticationInfo( user.name(), user.credentials(), getName(), result );
}
int numberOfUsers()
@@ -393,7 +393,7 @@ public boolean deleteUser( String username ) throws IOException
@Override
public User getUser( String username )
{
- return null;
+ return userRepository.getUserByName( username );
}
@Override
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/LdapRealm.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/LdapRealm.java
index dcb44a6f80e6..ba8d20764685 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/LdapRealm.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/LdapRealm.java
@@ -45,6 +45,7 @@ public LdapRealm( Config config )
super();
setRolePermissionResolver( rolePermissionResolver );
configureRealm( config );
+ // TODO: Set NeoSubjectFactory on the SecurityManager
}
@Override
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/MultiRealmAuthManager.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/MultiRealmAuthManager.java
index 31903c2414ee..f948d9d5c3cc 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/MultiRealmAuthManager.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/MultiRealmAuthManager.java
@@ -20,13 +20,14 @@
package org.neo4j.server.security.enterprise.auth;
import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.ExcessiveAttemptsException;
+import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
-import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.CachingRealm;
import org.apache.shiro.realm.Realm;
-import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Initializable;
import java.util.Collection;
@@ -35,12 +36,13 @@
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;
+import org.neo4j.server.security.auth.UserManagerSupplier;
-public class MultiRealmAuthManager implements EnterpriseAuthManager
+public class MultiRealmAuthManager implements EnterpriseAuthManager, UserManagerSupplier
{
private final EnterpriseUserManager userManager;
private final Collection realms;
- private final SecurityManager securityManager;
+ private final DefaultSecurityManager securityManager;
private final EhCacheManager cacheManager;
public MultiRealmAuthManager( EnterpriseUserManager userManager, Collection realms )
@@ -48,8 +50,11 @@ public MultiRealmAuthManager( EnterpriseUserManager userManager, Collection authToken ) throws InvalidAuthTokenException
{
- Subject subject = new Subject.Builder( securityManager ).buildSubject();
+ ShiroSubject subject;
ShiroAuthToken token = new ShiroAuthToken( authToken );
- AuthenticationResult result = AuthenticationResult.FAILURE;
-
try
{
- subject.login( token );
- result = AuthenticationResult.SUCCESS;
+ subject = (ShiroSubject) securityManager.login( null, token );
}
catch ( UnsupportedTokenException e )
{
throw new InvalidAuthTokenException( e.getCause().getMessage() );
}
+ catch ( ExcessiveAttemptsException e )
+ {
+ // NOTE: We only get this with single (internal) realm authentication
+ subject = new ShiroSubject( securityManager, AuthenticationResult.TOO_MANY_ATTEMPTS );
+ }
catch ( AuthenticationException e )
{
- result = AuthenticationResult.FAILURE;
+ subject = new ShiroSubject( securityManager, AuthenticationResult.FAILURE );
}
- return new ShiroAuthSubject( this, subject, result );
+ return new ShiroAuthSubject( this, subject );
}
@Override
@@ -95,9 +102,9 @@ public void init() throws Throwable
{
((CachingRealm) realm).setCacheManager( cacheManager );
}
- if ( realm instanceof NeoLifecycleRealm )
+ if ( realm instanceof ShiroRealmLifecycle )
{
- ((NeoLifecycleRealm) realm).initialize();
+ ((ShiroRealmLifecycle) realm).initialize();
}
}
}
@@ -107,9 +114,9 @@ public void start() throws Throwable
{
for ( Realm realm : realms )
{
- if ( realm instanceof NeoLifecycleRealm )
+ if ( realm instanceof ShiroRealmLifecycle )
{
- ((NeoLifecycleRealm) realm).start();
+ ((ShiroRealmLifecycle) realm).start();
}
}
}
@@ -119,9 +126,9 @@ public void stop() throws Throwable
{
for ( Realm realm : realms )
{
- if ( realm instanceof NeoLifecycleRealm )
+ if ( realm instanceof ShiroRealmLifecycle )
{
- ((NeoLifecycleRealm) realm).stop();
+ ((ShiroRealmLifecycle) realm).stop();
}
}
}
@@ -135,9 +142,9 @@ public void shutdown() throws Throwable
{
((CachingRealm) realm).setCacheManager( null );
}
- if ( realm instanceof NeoLifecycleRealm )
+ if ( realm instanceof ShiroRealmLifecycle )
{
- ((NeoLifecycleRealm) realm).shutdown();
+ ((ShiroRealmLifecycle) realm).shutdown();
}
}
cacheManager.destroy();
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/SecuritySettings.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/SecuritySettings.java
index 72fd888f5152..313fce3d2a6f 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/SecuritySettings.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/SecuritySettings.java
@@ -39,11 +39,11 @@ public class SecuritySettings
@Description( "Enable auth via external authentication providers." )
public static final Setting external_auth_enabled =
- setting( "dbms.security.external_auth_enabled", BOOLEAN, "true" );
+ setting( "dbms.security.external_auth_enabled", BOOLEAN, "false" );
- @Description( "Enable auth via a configurable LDAP authentication provider." )
+ @Description( "Enable auth via a settings configurable LDAP authentication realm." )
public static final Setting ldap_auth_enabled =
- setting( "dbms.security.ldap.enabled", BOOLEAN, "true" );
+ setting( "dbms.security.ldap.enabled", BOOLEAN, "false" );
@Description( "Hostname and port of LDAP server to use for authentication and authorization." )
public static final Setting ldap_server =
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthManager.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthManager.java
index 64642e31f485..ef42ded69d65 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthManager.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthManager.java
@@ -23,11 +23,6 @@
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
-import org.apache.shiro.mgt.SecurityManager;
-import org.apache.shiro.realm.Realm;
-import org.apache.shiro.subject.PrincipalCollection;
-import org.apache.shiro.subject.SimplePrincipalCollection;
-import org.apache.shiro.subject.Subject;
import java.io.IOException;
import java.time.Clock;
@@ -48,7 +43,7 @@
public class ShiroAuthManager extends BasicAuthManager implements EnterpriseAuthManager, EnterpriseUserManager
{
- protected SecurityManager securityManager;
+ protected DefaultSecurityManager securityManager;
private final EhCacheManager cacheManager;
private final FileUserRealm realm;
private final RoleRepository roleRepository;
@@ -67,7 +62,7 @@ public ShiroAuthManager( UserRepository userRepository, RoleRepository roleRepos
this.roleRepository = roleRepository;
}
- protected SecurityManager createSecurityManager()
+ protected DefaultSecurityManager createSecurityManager()
{
return new DefaultSecurityManager( realm );
}
@@ -90,6 +85,7 @@ public void init() throws Throwable
realm.initialize();
securityManager = createSecurityManager();
+ securityManager.setSubjectFactory( new ShiroSubjectFactory() );
}
@Override
@@ -161,7 +157,7 @@ public ShiroAuthSubject login( Map authToken ) throws InvalidAuth
String password = AuthToken.safeCast( AuthToken.CREDENTIALS, authToken );
// Start with an anonymous subject
- Subject subject = buildSubject( null );
+ ShiroSubject subject = new ShiroSubject( securityManager, AuthenticationResult.FAILURE );
AuthenticationResult result = AuthenticationResult.FAILURE;
@@ -174,7 +170,7 @@ public ShiroAuthSubject login( Map authToken ) throws InvalidAuth
UsernamePasswordToken token = new UsernamePasswordToken( username, password );
try
{
- subject.login( token );
+ subject = (ShiroSubject) securityManager.login( null, token );
if ( realm.findUser( username ).passwordChangeRequired() )
{
result = AuthenticationResult.PASSWORD_CHANGE_REQUIRED;
@@ -194,7 +190,7 @@ public ShiroAuthSubject login( Map authToken ) throws InvalidAuth
}
authStrategy.updateWithAuthenticationResult( result, username );
}
- return new ShiroAuthSubject( this, subject, result );
+ return new ShiroAuthSubject( this, subject );
}
@Override
@@ -260,24 +256,6 @@ public Set getAllUsernames()
return realm.getAllUsernames();
}
- protected Realm getInternalRealm()
- {
- return realm;
- }
-
- private Subject buildSubject( String username )
- {
- Subject.Builder subjectBuilder = new Subject.Builder( securityManager );
-
- if ( username != null )
- {
- PrincipalCollection identity = new SimplePrincipalCollection( username, realm.getName() );
- subjectBuilder = subjectBuilder.principals( identity );
- }
-
- return subjectBuilder.buildSubject();
- }
-
@Override
public EnterpriseUserManager getUserManager()
{
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthSubject.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthSubject.java
index 80cf5f2b103f..7e4866845473 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthSubject.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthSubject.java
@@ -24,11 +24,9 @@
import java.io.IOException;
import org.neo4j.kernel.api.security.AccessMode;
-import org.neo4j.kernel.api.security.AuthManager;
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.security.exception.IllegalCredentialsException;
-import org.neo4j.server.security.auth.UserManager;
public class ShiroAuthSubject implements AuthSubject
{
@@ -37,8 +35,7 @@ public class ShiroAuthSubject implements AuthSubject
static final String READ = "data:read";
private final EnterpriseAuthManager authManager;
- private final Subject subject;
- private final AuthenticationResult authenticationResult;
+ private final ShiroSubject subject;
public static ShiroAuthSubject castOrFail( AuthSubject authSubject )
{
@@ -49,11 +46,10 @@ public static ShiroAuthSubject castOrFail( AuthSubject authSubject )
return (ShiroAuthSubject) authSubject;
}
- public ShiroAuthSubject( EnterpriseAuthManager authManager, Subject subject, AuthenticationResult authenticationResult )
+ public ShiroAuthSubject( EnterpriseAuthManager authManager, ShiroSubject subject )
{
this.authManager = authManager;
this.subject = subject;
- this.authenticationResult = authenticationResult;
}
@Override
@@ -65,7 +61,7 @@ public void logout()
@Override
public AuthenticationResult getAuthenticationResult()
{
- return authenticationResult;
+ return subject.getAuthenticationResult();
}
@Override
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthenticationInfo.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthenticationInfo.java
new file mode 100644
index 000000000000..bcdfeb7cefa8
--- /dev/null
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroAuthenticationInfo.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002-2016 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.server.security.enterprise.auth;
+
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+
+import org.neo4j.kernel.api.security.AuthenticationResult;
+
+public class ShiroAuthenticationInfo extends SimpleAuthenticationInfo
+{
+ AuthenticationResult authenticationResult;
+
+ public ShiroAuthenticationInfo( Object principal, Object credentials, String realmName,
+ AuthenticationResult authenticationResult )
+ {
+ super( principal, credentials, realmName );
+ this.authenticationResult = authenticationResult;
+ }
+
+ public AuthenticationResult getAuthenticationResult()
+ {
+ return authenticationResult;
+ }
+
+ @Override
+ public void merge( AuthenticationInfo info )
+ {
+ super.merge( info );
+ if ( info instanceof ShiroAuthenticationInfo )
+ {
+ AuthenticationResult result = ((ShiroAuthenticationInfo) info).authenticationResult;
+ // TODO: Merge AuthenticationResult
+ authenticationResult = result;
+ }
+ }
+}
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/NeoLifecycleRealm.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroRealmLifecycle.java
similarity index 96%
rename from enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/NeoLifecycleRealm.java
rename to enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroRealmLifecycle.java
index 6005c265bfc8..25ebbffdded6 100644
--- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/NeoLifecycleRealm.java
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroRealmLifecycle.java
@@ -19,7 +19,7 @@
*/
package org.neo4j.server.security.enterprise.auth;
-public interface NeoLifecycleRealm
+public interface ShiroRealmLifecycle
{
void initialize() throws Throwable;
void start() throws Throwable;
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroSubject.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroSubject.java
new file mode 100644
index 000000000000..2e1a84d5b5fc
--- /dev/null
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroSubject.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002-2016 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.server.security.enterprise.auth;
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.support.DelegatingSubject;
+
+import org.neo4j.kernel.api.security.AuthenticationResult;
+
+public class ShiroSubject extends DelegatingSubject
+{
+ private final AuthenticationResult authenticationResult;
+
+ public ShiroSubject( SecurityManager securityManager, AuthenticationResult authenticationResult )
+ {
+ super( securityManager );
+ this.authenticationResult = authenticationResult;
+ }
+
+ public ShiroSubject( PrincipalCollection principals, boolean authenticated, String host, Session session,
+ boolean sessionCreationEnabled, SecurityManager securityManager, AuthenticationResult authenticationResult )
+ {
+ super( principals, authenticated, host, session, sessionCreationEnabled, securityManager );
+ this.authenticationResult = authenticationResult;
+ }
+
+ public AuthenticationResult getAuthenticationResult()
+ {
+ return authenticationResult;
+ }
+}
diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroSubjectFactory.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroSubjectFactory.java
new file mode 100644
index 000000000000..9a6d679013ad
--- /dev/null
+++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/ShiroSubjectFactory.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2002-2016 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.server.security.enterprise.auth;
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.mgt.SubjectFactory;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.subject.SubjectContext;
+
+public class ShiroSubjectFactory implements SubjectFactory
+{
+ @Override
+ public Subject createSubject( SubjectContext context )
+ {
+ SecurityManager securityManager = context.resolveSecurityManager();
+ Session session = context.resolveSession();
+ boolean sessionCreationEnabled = context.isSessionCreationEnabled();
+ PrincipalCollection principals = context.resolvePrincipals();
+ boolean authenticated = context.resolveAuthenticated();
+ String host = context.resolveHost();
+ ShiroAuthenticationInfo authcInfo = (ShiroAuthenticationInfo) context.getAuthenticationInfo();
+
+ return new ShiroSubject( principals, authenticated, host, session, sessionCreationEnabled, securityManager,
+ authcInfo.authenticationResult );
+ }
+}
diff --git a/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/auth/integration/bolt/EnterpriseAuthenticationIT.java b/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/auth/integration/bolt/EnterpriseAuthenticationIT.java
index a7a6cb0d32fe..bab10bf301af 100644
--- a/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/auth/integration/bolt/EnterpriseAuthenticationIT.java
+++ b/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/auth/integration/bolt/EnterpriseAuthenticationIT.java
@@ -19,27 +19,16 @@
*/
package org.neo4j.server.security.enterprise.auth.integration.bolt;
-import org.junit.Test;
-
import java.util.Map;
import java.util.function.Consumer;
import org.neo4j.bolt.v1.transport.integration.AuthenticationIT;
-import org.neo4j.bolt.v1.transport.integration.TransportTestUtil;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.server.security.enterprise.auth.SecuritySettings;
import org.neo4j.test.TestEnterpriseGraphDatabaseFactory;
import org.neo4j.test.TestGraphDatabaseFactory;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.neo4j.bolt.v1.messaging.message.Messages.init;
-import static org.neo4j.bolt.v1.messaging.message.Messages.pullAll;
-import static org.neo4j.bolt.v1.messaging.message.Messages.run;
-import static org.neo4j.bolt.v1.messaging.util.MessageMatchers.msgSuccess;
-import static org.neo4j.bolt.v1.transport.integration.TransportTestUtil.eventuallyRecieves;
-import static org.neo4j.helpers.collection.MapUtil.map;
-
public class EnterpriseAuthenticationIT extends AuthenticationIT
{
@Override
@@ -54,37 +43,7 @@ protected Consumer