You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Maciej Pigulski <ma...@gmail.com> on 2009/03/19 14:46:17 UTC

Reading user roles from Active Directory

Hello,

I have a following problem with jSecurity, ActiveDirectoryRealm and Groups
mappings.

I have an AD setup on one server (WHEEL) with a simple user called user1.
This user is in ldap group called "login" (CN=login,OU=Groups,DC=WHEEL).

Next I'm trying to login and retrieve roles for this user. Login works fine
but when it comes to user roles I  have to additionally provide username and
password in activeDirectoryRealm.setSystemUsername/Password. I've found in
the API that it is a pretty normal behaviour (but IMHO very inconvenient)
(http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String):
<cite>
systemUsername - the username to use when logging into the LDAP server for
authorization.
</cite>

Is there any tricky way to bypass this? Setting same credentials on two
objects to authorize and authenticate one user seems to be quite wrong.

I've managed to obtain this by creating a super user (with enterprise
administrator rights) that has hardcoded username and password in
application (systemUsername and systemPassword) and this works for
authenticating other users but I'd like to avoid using such powerfull user
just for groups fetching as it seems to be an huge overkill for me.

Here is a class I'm using to test with AD:

import java.util.HashMap;
import java.util.Map;

import org.jsecurity.authc.UsernamePasswordToken;
import org.jsecurity.mgt.DefaultSecurityManager;
import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
import org.jsecurity.subject.Subject;

public class TestJSec {

        private DefaultSecurityManager securityManager = new
DefaultSecurityManager();
	private ActiveDirectoryRealm activeDirectoryRealm = new
ActiveDirectoryRealm();

	public TestJSec() {
		activeDirectoryRealm.setSearchBase("DC=WHEEL");
		activeDirectoryRealm.setUrl("ldap://ldap-host:389");
		activeDirectoryRealm.setSystemUsername("user1@wheel"); // if this is
missing user wont fetch his roles
		activeDirectoryRealm.setSystemPassword("user1");              // if this
is missing user wont fetch his roles
		Map<String, String> map = new HashMap<String, String>();
		map.put("CN=login,OU=Groups,DC=WHEEL", "login");
		activeDirectoryRealm.setGroupRolesMap(map);

		securityManager.setRealm(activeDirectoryRealm);
	}

	private void testLogin() {
		UsernamePasswordToken userToken = new UsernamePasswordToken("user1@wheel",
"user1");

		Subject subject = securityManager.login(userToken);
		if (subject.hasRole("login")) {
                        System.out.println("User in role");
		} else {
			System.out.println("User has no role");			
		}
	}

	public static void main(String[] args) {
		TestJSec tjs = new TestJSec();
		tjs.testLogin();
	}
}


For example in jBoss this config works without a super user:


<application-policy name="DLG_REGW_POLICY">
	<authentication>
		<login-module code="org.jboss.security.auth.spi.LdapLoginModule"
flag="required" >
			<module-option
name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
			<module-option name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
			<module-option name="matchOnUserDN">false</module-option>
			<module-option name="uidAttributeID">sAMAccountName</module-option>
			<module-option name="roleAttributeID">memberOf</module-option>
			<module-option name="roleAttributeIsDN">true</module-option>
			<module-option name="roleNameAttributeID">name</module-option>
			<module-option name="searchTimeLimit">5000</module-option>
			<module-option name="allowEmptyPasswords">false</module-option>
			<module-option name="searchScope">SUBTREE_SCOPE</module-option>
		</login-module>
	</authentication>
</application-policy> 

-- 
View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
Sent from the JSecurity User mailing list archive at Nabble.com.


Re: Reading user roles from Active Directory

Posted by Maciej Pigulski <ma...@gmail.com>.
Thanks Les, I'll try to put your advices into use.

Jeremy, I have no problem with creating a user with the read access,
but my client has:) As I mentioned in the first post JAAS configured
in jBoss doesn't require any additional users to perform such simple
task like checking users own groups so I was looking for same solution
in jSecurity.

>From my point of view (maybe this is a lazy developer point of view)
creating a separate user to only read permissions (groups) is a bit an
overkill. I understand when I need to edit LDAP tree or create users
for instance, but separate user to read for some other user that he has
a group X looks odd to me. What if I would like to have two users, one
with read access and one with write access? Create a user that can do
both as a system user and then I'd have to put those two users in
groups (such as 'read', 'write') and then check if they can read or write?
Maybe I'm exaggerating here, but my knowledge of security is not as 
good as yours for sure.

Regards,
Maciej


Maciej,  I'm curious - what is the difficulty in creating a system  
user account that can be used to simply check authorization  
information.  This account could be granted read-only access that lets  
it check on the roles and permissions that individual users have.   
This is the way most of our LDAP/Active Directory users do this.  You  
mentioned wanting to avoid this because you created a powerful user,  
but what if you only gave that user read only access and a secure  
password that is only stored on your server (presumably in a secured  
file)?

Jeremy

On Mar 31, 2009, at 2:37 AM, Maciej Pigulski wrote:

>
> Jeremy,
>
> you are absolutely right and I'm not proud at all from this  
> solution, but it is the fastest implementation I've managed to get  
> to work. I treat this as a temporary solution until jSecurity 1.0.
>
> Anyway, obviously I was doing something wrong while trying to make  
> your solution working.
>
> I had problems with getting to Subjects session to store the  
> authorization info - SecurityUtils.getSubject() was returning a null  
> value. I guess the issue is that this object does not exist in this  
> stage, but I couldn't get any other idea how to get into the Session  
> object.
>
> Another issue was getting the AuthorizationInfo to work. Without  
> setting systemUsername and systemPassword AuthorizationInfo was  
> trying to obtain data from Active Directory with a null user and  
> this failed. I think I should get this information using LdapContext  
> (a new object, not the default one) with credentials passed by this  
> user, but the queryForAuthorizationInfo uses  
> getRoleNamesForUser(...) private method so I'd have to copy paste  
> this method with LdapContext ldapContext =  
> ldapContextFactory.getLdapContext(username, password); used instead  
> the  LdapContext ldapContext =  
> ldapContextFactory.getSystemLdapContext(); one. This bugs me because  
> when I'm copy-pasting then I'm doing something obviously wrong so I  
> guess this way is not the correct way.
>
> Thanks for pointing me out possible issues with this solution. Now  
> I'm getting worried ;)
>
> Maciej
>
>
>
> Marciej,
>
> This approach isn't the most secure since each time a new user
> authenticates, the system username and password will be updated to
> store their username and password.
>
> For example:
> 1) Bob logs in.  His username/password are set as the system username/
> password
> 2) Bob does a permission check and it uses bob's account to access  
> LDAP
> 3) Sue logs in.  Her username/password are set as the system username/
> password
> 4) Bob does another permission check.  this time Sue's credentials are
> used to access LDAP
>
> In this scenario, it's impossible to predict which user and password
> will be used to authenticate.
>
> Even neglecting the security implications, there is a possible race
> condition that could result in errors obtaining authorization
> information.  Since DefaultLdapContextFactory is a singleton and is
> not synchronized in any way, it's possible that an authorization check
> will occur in one thread while in another thread the system username
> and password are being updated due to another user authenticating.
> This means that username could be set to "Sue" while the password is
> still set to Bob's password.  This would result in an LDAP error since
> Bob's password is invalid for Sue's account.
>
> If you really want to just store the user's credentials, I would
> suggest storing them in the user's principal and pulling them out of
> the Principal object when you need to check for authorization info.
> That being said, holding onto a user's credentials in memory is
> considered a bad security practice, since if anyone hacks your machine
> or gets access to RAM, they could grab all of your user's
> credentials.  Also, since the credentials would be stored in a
> session, and sessions are sometimes serialized to disk, a hacker could
> possible just get access to the serialized sessions file and obtain
> their credentials from the file.
>
> My 2 cents,
> Jeremy
>
> On Mar 30, 2009, at 10:43 AM, Maciej Pigulski wrote:
>
>>
>> Hello,
>>
>> thanks for the clarification. I've done it in a 3rd way by
>> overriding DefaultLdapContextFactory settings in
>> queryForAuthenticationInfo:
>>
>>
>> 	/* (non-Javadoc)
>> 	 * @see
>> org
>> .jsecurity
>> .realm
>> .activedirectory
>> .ActiveDirectoryRealm
>> #queryForAuthenticationInfo(org.jsecurity.authc.AuthenticationToken,
>> org.jsecurity.realm.ldap.LdapContextFactory)
>> 	 */
>> 	@Override
>> 	protected AuthenticationInfo
>> queryForAuthenticationInfo(AuthenticationToken token,
>> 			LdapContextFactory ldapContextFactory) throws NamingException {
>>
>> 		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
>> 		DefaultLdapContextFactory defaultLdapContextFactory =
>> (DefaultLdapContextFactory) ldapContextFactory;
>> 		defaultLdapContextFactory.setSystemUsername(upToken.getUsername());
>> 		
>> defaultLdapContextFactory
>> .setSystemPassword(upToken.getPassword().toString());
>>
>> 		return super.queryForAuthenticationInfo(token, ldapContextFactory);
>> 	}
>>
>>
>> Maybe it is not the best workaround but I had no time to do it like
>> you suggested. Looking forward for jSecurity 1.0, keep up the good
>> work!
>>
>> Greetings,
>> Maciej
>>
>>
>> Maciej,
>>
>> The problem is that if the LDAP server requires credentials to login
>> (as they typically do), there is no way to obtain authorization
>> information at a later point without having a username/password to
>> login to the LDAP server.  Due to the way JSecurity works,
>> authentication and authorization happen independently of each other,
>> and so when authorization occurs we do not have the username/password
>> that was originally used to authenticate (as we shouldn't).
>>
>> I think this brings to light an option that JSecurity should offer -
>> which is to allow authorization information to be obtained at login
>> and cached for the duration of a user's session.  This is the way  
>> many
>> security frameworks operate, and usually we tout the fact that
>> JSecurity doesn't work this way as an advantage (i.e. dynamic  
>> security
>> updates, flexible caching, etc.)
>>
>> However - in this case it's a disadvantage because login is the only
>> time when we have the information we need to obtain the authorization
>> information (since the authentication info is needed to obtain  
>> it).  I
>> think there will be other scenarios where this is the case (external
>> authorization systems, SSO systems, etc.) so I do think JSecurity
>> should offer this mechanism as an option.  I'll open a JIRA issue to
>> address this for the 1.0 release.
>>
>> As far as a short-term workaround, you could either:
>> 1) configure the system username and password for now (as I think
>> you've already done)
>> or
>> 2) extend the Active Directory realm, and override
>> queryForAuthenticationInfo to grab the AuthorizationInfo (similar to
>> how queryForAuthorizationInfo does) at login.  You could then cache
>> the AuthorizationInfo in the subject's session and override
>> queryForAuthorizationInfo to return the session-cached authorization
>> information.  This is similar to how JSecurity would probably do this
>> in the future, but obviously you'd have to manually implement it.
>>
>> Please let me know if you have any further questions or ideas!
>>
>> Jeremy
>>
>> On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:
>>
>>>
>>> Unfortunately this is still an issue to me.
>>>
>>>
>>> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I
>>> don't
>>> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,
>>> have
>>> you been able to work through this issue?
>>>
>>> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
>>> <ma...@gmail.com>wrote:
>>>
>>>>
>>>> Hello,
>>>>
>>>> I have a following problem with jSecurity, ActiveDirectoryRealm and
>>>> Groups
>>>> mappings.
>>>>
>>>> I have an AD setup on one server (WHEEL) with a simple user called
>>>> user1.
>>>> This user is in ldap group called
>>>> "login" (CN=login,OU=Groups,DC=WHEEL).
>>>>
>>>> Next I'm trying to login and retrieve roles for this user. Login
>>>> works fine
>>>> but when it comes to user roles I  have to additionally provide
>>>> username
>>>> and
>>>> password in activeDirectoryRealm.setSystemUsername/Password. I've
>>>> found in
>>>> the API that it is a pretty normal behaviour (but IMHO very
>>>> inconvenient)
>>>> (
>>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)
>>>> <http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29
>>>>>
>>>> :
>>>> <cite>
>>>> systemUsername - the username to use when logging into the LDAP
>>>> server for
>>>> authorization.
>>>> </cite>
>>>>
>>>> Is there any tricky way to bypass this? Setting same credentials on
>>>> two
>>>> objects to authorize and authenticate one user seems to be quite
>>>> wrong.
>>>>
>>>> I've managed to obtain this by creating a super user (with
>>>> enterprise
>>>> administrator rights) that has hardcoded username and password in
>>>> application (systemUsername and systemPassword) and this works for
>>>> authenticating other users but I'd like to avoid using such
>>>> powerfull user
>>>> just for groups fetching as it seems to be an huge overkill for me.
>>>>
>>>> Here is a class I'm using to test with AD:
>>>>
>>>> import java.util.HashMap;
>>>> import java.util.Map;
>>>>
>>>> import org.jsecurity.authc.UsernamePasswordToken;
>>>> import org.jsecurity.mgt.DefaultSecurityManager;
>>>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>>>> import org.jsecurity.subject.Subject;
>>>>
>>>> public class TestJSec {
>>>>
>>>>     private DefaultSecurityManager securityManager = new
>>>> DefaultSecurityManager();
>>>>     private ActiveDirectoryRealm activeDirectoryRealm = new
>>>> ActiveDirectoryRealm();
>>>>
>>>>     public TestJSec() {
>>>>             activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>>>             activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>>>
>>>> activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>>>> if this is
>>>> missing user wont fetch his roles
>>>>             activeDirectoryRealm.setSystemPassword("user1");
>>>> // if this
>>>> is missing user wont fetch his roles
>>>>             Map<String, String> map = new HashMap<String,
>>>> String>();
>>>>             map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>>>             activeDirectoryRealm.setGroupRolesMap(map);
>>>>
>>>>             securityManager.setRealm(activeDirectoryRealm);
>>>>     }
>>>>
>>>>     private void testLogin() {
>>>>             UsernamePasswordToken userToken = new
>>>> UsernamePasswordToken("user1@wheel",
>>>> "user1");
>>>>
>>>>             Subject subject = securityManager.login(userToken);
>>>>             if (subject.hasRole("login")) {
>>>>                     System.out.println("User in role");
>>>>             } else {
>>>>                     System.out.println("User has no role");
>>>>             }
>>>>     }
>>>>
>>>>     public static void main(String[] args) {
>>>>             TestJSec tjs = new TestJSec();
>>>>             tjs.testLogin();
>>>>     }
>>>> }
>>>>
>>>>
>>>> For example in jBoss this config works without a super user:
>>>>
>>>>
>>>> <application-policy name="DLG_REGW_POLICY">
>>>>     <authentication>
>>>>             <login-module
>>>> code="org.jboss.security.auth.spi.LdapLoginModule"
>>>> flag="required" >
>>>>                     <module-option
>>>> name="java.naming.provider.url">ldap://ldap-host:389/</module-
>>>> option>
>>>>                     <module-option
>>>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>>>                     <module-option
>>>> name="matchOnUserDN">false</module-option>
>>>>                     <module-option
>>>> name="uidAttributeID">sAMAccountName</module-option>
>>>>                     <module-option
>>>> name="roleAttributeID">memberOf</module-option>
>>>>                     <module-option
>>>> name="roleAttributeIsDN">true</module-option>
>>>>                     <module-option
>>>> name="roleNameAttributeID">name</module-option>
>>>>                     <module-option
>>>> name="searchTimeLimit">5000</module-option>
>>>>                     <module-option
>>>> name="allowEmptyPasswords">false</module-option>
>>>>                     <module-option
>>>> name="searchScope">SUBTREE_SCOPE</module-option>
>>>>             </login-module>
>>>>     </authentication>
>>>> </application-policy>
>>>>
>>>> --
>>>> View this message in context:
>>>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>>
>>>>
>>>
>>>
>>>
>>> -- 
>>> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>
>>
>>
>>
>>
>> -- 
>> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2557591.html
>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>
>
>
>
>
> -- 
> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2561437.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>




-- 
View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2567400.html
Sent from the JSecurity User mailing list archive at Nabble.com.


Re: Reading user roles from Active Directory

Posted by Jeremy Haile <jh...@fastmail.fm>.
Maciej,  I'm curious - what is the difficulty in creating a system  
user account that can be used to simply check authorization  
information.  This account could be granted read-only access that lets  
it check on the roles and permissions that individual users have.   
This is the way most of our LDAP/Active Directory users do this.  You  
mentioned wanting to avoid this because you created a powerful user,  
but what if you only gave that user read only access and a secure  
password that is only stored on your server (presumably in a secured  
file)?

Jeremy

On Mar 31, 2009, at 2:37 AM, Maciej Pigulski wrote:

>
> Jeremy,
>
> you are absolutely right and I'm not proud at all from this  
> solution, but it is the fastest implementation I've managed to get  
> to work. I treat this as a temporary solution until jSecurity 1.0.
>
> Anyway, obviously I was doing something wrong while trying to make  
> your solution working.
>
> I had problems with getting to Subjects session to store the  
> authorization info - SecurityUtils.getSubject() was returning a null  
> value. I guess the issue is that this object does not exist in this  
> stage, but I couldn't get any other idea how to get into the Session  
> object.
>
> Another issue was getting the AuthorizationInfo to work. Without  
> setting systemUsername and systemPassword AuthorizationInfo was  
> trying to obtain data from Active Directory with a null user and  
> this failed. I think I should get this information using LdapContext  
> (a new object, not the default one) with credentials passed by this  
> user, but the queryForAuthorizationInfo uses  
> getRoleNamesForUser(...) private method so I'd have to copy paste  
> this method with LdapContext ldapContext =  
> ldapContextFactory.getLdapContext(username, password); used instead  
> the  LdapContext ldapContext =  
> ldapContextFactory.getSystemLdapContext(); one. This bugs me because  
> when I'm copy-pasting then I'm doing something obviously wrong so I  
> guess this way is not the correct way.
>
> Thanks for pointing me out possible issues with this solution. Now  
> I'm getting worried ;)
>
> Maciej
>
>
>
> Marciej,
>
> This approach isn't the most secure since each time a new user
> authenticates, the system username and password will be updated to
> store their username and password.
>
> For example:
> 1) Bob logs in.  His username/password are set as the system username/
> password
> 2) Bob does a permission check and it uses bob's account to access  
> LDAP
> 3) Sue logs in.  Her username/password are set as the system username/
> password
> 4) Bob does another permission check.  this time Sue's credentials are
> used to access LDAP
>
> In this scenario, it's impossible to predict which user and password
> will be used to authenticate.
>
> Even neglecting the security implications, there is a possible race
> condition that could result in errors obtaining authorization
> information.  Since DefaultLdapContextFactory is a singleton and is
> not synchronized in any way, it's possible that an authorization check
> will occur in one thread while in another thread the system username
> and password are being updated due to another user authenticating.
> This means that username could be set to "Sue" while the password is
> still set to Bob's password.  This would result in an LDAP error since
> Bob's password is invalid for Sue's account.
>
> If you really want to just store the user's credentials, I would
> suggest storing them in the user's principal and pulling them out of
> the Principal object when you need to check for authorization info.
> That being said, holding onto a user's credentials in memory is
> considered a bad security practice, since if anyone hacks your machine
> or gets access to RAM, they could grab all of your user's
> credentials.  Also, since the credentials would be stored in a
> session, and sessions are sometimes serialized to disk, a hacker could
> possible just get access to the serialized sessions file and obtain
> their credentials from the file.
>
> My 2 cents,
> Jeremy
>
> On Mar 30, 2009, at 10:43 AM, Maciej Pigulski wrote:
>
>>
>> Hello,
>>
>> thanks for the clarification. I've done it in a 3rd way by
>> overriding DefaultLdapContextFactory settings in
>> queryForAuthenticationInfo:
>>
>>
>> 	/* (non-Javadoc)
>> 	 * @see
>> org
>> .jsecurity
>> .realm
>> .activedirectory
>> .ActiveDirectoryRealm
>> #queryForAuthenticationInfo(org.jsecurity.authc.AuthenticationToken,
>> org.jsecurity.realm.ldap.LdapContextFactory)
>> 	 */
>> 	@Override
>> 	protected AuthenticationInfo
>> queryForAuthenticationInfo(AuthenticationToken token,
>> 			LdapContextFactory ldapContextFactory) throws NamingException {
>>
>> 		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
>> 		DefaultLdapContextFactory defaultLdapContextFactory =
>> (DefaultLdapContextFactory) ldapContextFactory;
>> 		defaultLdapContextFactory.setSystemUsername(upToken.getUsername());
>> 		
>> defaultLdapContextFactory
>> .setSystemPassword(upToken.getPassword().toString());
>>
>> 		return super.queryForAuthenticationInfo(token, ldapContextFactory);
>> 	}
>>
>>
>> Maybe it is not the best workaround but I had no time to do it like
>> you suggested. Looking forward for jSecurity 1.0, keep up the good
>> work!
>>
>> Greetings,
>> Maciej
>>
>>
>> Maciej,
>>
>> The problem is that if the LDAP server requires credentials to login
>> (as they typically do), there is no way to obtain authorization
>> information at a later point without having a username/password to
>> login to the LDAP server.  Due to the way JSecurity works,
>> authentication and authorization happen independently of each other,
>> and so when authorization occurs we do not have the username/password
>> that was originally used to authenticate (as we shouldn't).
>>
>> I think this brings to light an option that JSecurity should offer -
>> which is to allow authorization information to be obtained at login
>> and cached for the duration of a user's session.  This is the way  
>> many
>> security frameworks operate, and usually we tout the fact that
>> JSecurity doesn't work this way as an advantage (i.e. dynamic  
>> security
>> updates, flexible caching, etc.)
>>
>> However - in this case it's a disadvantage because login is the only
>> time when we have the information we need to obtain the authorization
>> information (since the authentication info is needed to obtain  
>> it).  I
>> think there will be other scenarios where this is the case (external
>> authorization systems, SSO systems, etc.) so I do think JSecurity
>> should offer this mechanism as an option.  I'll open a JIRA issue to
>> address this for the 1.0 release.
>>
>> As far as a short-term workaround, you could either:
>> 1) configure the system username and password for now (as I think
>> you've already done)
>> or
>> 2) extend the Active Directory realm, and override
>> queryForAuthenticationInfo to grab the AuthorizationInfo (similar to
>> how queryForAuthorizationInfo does) at login.  You could then cache
>> the AuthorizationInfo in the subject's session and override
>> queryForAuthorizationInfo to return the session-cached authorization
>> information.  This is similar to how JSecurity would probably do this
>> in the future, but obviously you'd have to manually implement it.
>>
>> Please let me know if you have any further questions or ideas!
>>
>> Jeremy
>>
>> On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:
>>
>>>
>>> Unfortunately this is still an issue to me.
>>>
>>>
>>> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I
>>> don't
>>> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,
>>> have
>>> you been able to work through this issue?
>>>
>>> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
>>> <ma...@gmail.com>wrote:
>>>
>>>>
>>>> Hello,
>>>>
>>>> I have a following problem with jSecurity, ActiveDirectoryRealm and
>>>> Groups
>>>> mappings.
>>>>
>>>> I have an AD setup on one server (WHEEL) with a simple user called
>>>> user1.
>>>> This user is in ldap group called
>>>> "login" (CN=login,OU=Groups,DC=WHEEL).
>>>>
>>>> Next I'm trying to login and retrieve roles for this user. Login
>>>> works fine
>>>> but when it comes to user roles I  have to additionally provide
>>>> username
>>>> and
>>>> password in activeDirectoryRealm.setSystemUsername/Password. I've
>>>> found in
>>>> the API that it is a pretty normal behaviour (but IMHO very
>>>> inconvenient)
>>>> (
>>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)
>>>> <http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29
>>>>>
>>>> :
>>>> <cite>
>>>> systemUsername - the username to use when logging into the LDAP
>>>> server for
>>>> authorization.
>>>> </cite>
>>>>
>>>> Is there any tricky way to bypass this? Setting same credentials on
>>>> two
>>>> objects to authorize and authenticate one user seems to be quite
>>>> wrong.
>>>>
>>>> I've managed to obtain this by creating a super user (with
>>>> enterprise
>>>> administrator rights) that has hardcoded username and password in
>>>> application (systemUsername and systemPassword) and this works for
>>>> authenticating other users but I'd like to avoid using such
>>>> powerfull user
>>>> just for groups fetching as it seems to be an huge overkill for me.
>>>>
>>>> Here is a class I'm using to test with AD:
>>>>
>>>> import java.util.HashMap;
>>>> import java.util.Map;
>>>>
>>>> import org.jsecurity.authc.UsernamePasswordToken;
>>>> import org.jsecurity.mgt.DefaultSecurityManager;
>>>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>>>> import org.jsecurity.subject.Subject;
>>>>
>>>> public class TestJSec {
>>>>
>>>>     private DefaultSecurityManager securityManager = new
>>>> DefaultSecurityManager();
>>>>     private ActiveDirectoryRealm activeDirectoryRealm = new
>>>> ActiveDirectoryRealm();
>>>>
>>>>     public TestJSec() {
>>>>             activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>>>             activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>>>
>>>> activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>>>> if this is
>>>> missing user wont fetch his roles
>>>>             activeDirectoryRealm.setSystemPassword("user1");
>>>> // if this
>>>> is missing user wont fetch his roles
>>>>             Map<String, String> map = new HashMap<String,
>>>> String>();
>>>>             map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>>>             activeDirectoryRealm.setGroupRolesMap(map);
>>>>
>>>>             securityManager.setRealm(activeDirectoryRealm);
>>>>     }
>>>>
>>>>     private void testLogin() {
>>>>             UsernamePasswordToken userToken = new
>>>> UsernamePasswordToken("user1@wheel",
>>>> "user1");
>>>>
>>>>             Subject subject = securityManager.login(userToken);
>>>>             if (subject.hasRole("login")) {
>>>>                     System.out.println("User in role");
>>>>             } else {
>>>>                     System.out.println("User has no role");
>>>>             }
>>>>     }
>>>>
>>>>     public static void main(String[] args) {
>>>>             TestJSec tjs = new TestJSec();
>>>>             tjs.testLogin();
>>>>     }
>>>> }
>>>>
>>>>
>>>> For example in jBoss this config works without a super user:
>>>>
>>>>
>>>> <application-policy name="DLG_REGW_POLICY">
>>>>     <authentication>
>>>>             <login-module
>>>> code="org.jboss.security.auth.spi.LdapLoginModule"
>>>> flag="required" >
>>>>                     <module-option
>>>> name="java.naming.provider.url">ldap://ldap-host:389/</module-
>>>> option>
>>>>                     <module-option
>>>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>>>                     <module-option
>>>> name="matchOnUserDN">false</module-option>
>>>>                     <module-option
>>>> name="uidAttributeID">sAMAccountName</module-option>
>>>>                     <module-option
>>>> name="roleAttributeID">memberOf</module-option>
>>>>                     <module-option
>>>> name="roleAttributeIsDN">true</module-option>
>>>>                     <module-option
>>>> name="roleNameAttributeID">name</module-option>
>>>>                     <module-option
>>>> name="searchTimeLimit">5000</module-option>
>>>>                     <module-option
>>>> name="allowEmptyPasswords">false</module-option>
>>>>                     <module-option
>>>> name="searchScope">SUBTREE_SCOPE</module-option>
>>>>             </login-module>
>>>>     </authentication>
>>>> </application-policy>
>>>>
>>>> --
>>>> View this message in context:
>>>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>>
>>>>
>>>
>>>
>>>
>>> -- 
>>> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>
>>
>>
>>
>>
>> -- 
>> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2557591.html
>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>
>
>
>
>
> -- 
> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2561437.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>


Re: Reading user roles from Active Directory

Posted by Les Hazlewood <lh...@apache.org>.
Ah.  In 'standalone' mode, you have to tell SecurityUtils where the
SecurityManager is by calling
SecurityUtils.setSecurityManager(securityManager);

This is because in a web or Spring/EJB environment, SecurityUtils assumes
some framework code elsewhere first executes to set up thread-bound Subject
instances: in the web environment, a Servlet Filter will intercept requests,
create a Subject based on the request, and bind it to the thread.  In RMI
environments, AOP proxies will do the same thing based on the incoming
invocation.

In a standalone environment, where there might not be any Filters
intercepting web requests or AOP proxies intercepting remote method
invocations, SecurityUtils can't rely on a thread-bound instance.  So it has
to ask the SecurityManager directly.  SecurityUtils.setSecurityManager sets
the instance in static memory, shared across the VM.

This however is NOT recommended for any environment other than standalone
applications - it is sort of a 'last resort' when you can't rely on a
container to manage dependency graphs for you...

HTH,

Les

On Tue, Mar 31, 2009 at 9:21 AM, Maciej Pigulski
<ma...@gmail.com>wrote:

>
>
> On Tue, Mar 31, 2009 at 2:37 AM, Maciej Pigulski
> <ma...@gmail.com>wrote:
>
> >
> > I had problems with getting to Subjects session to store the
> authorization
> > info - SecurityUtils.getSubject() was returning a null value. I guess the
> > issue is that this object does not exist in this stage, but I couldn't
> get
> > any other idea how to get into the Session object.
>
>
> That is extremely odd.  There should _always_ be a Subject for any thread's
> execution.  If one does not exist at the time getSubject() is called, it
> should have been created automatically.
>
> Are you running in a webapp or a standalone application?
>
> Regards,
>
> Les
>
>
>
> I was testing it in a standalone application running outside any containter
> (snippet of this class is in my first post in this thread). My target
> application is a web application.
>
> Take notice that I'm trying to SecurityUtils.getSubject() inside overriding
> class that extends ActiveDirectoryRealm in queryForAuthenticationInfo(...)
> method. Then it returns null.
>
>
> Regards,
> Maciej
>
> --
> View this message in context:
> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2562906.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>
>

Re: Reading user roles from Active Directory

Posted by Maciej Pigulski <ma...@gmail.com>.

On Tue, Mar 31, 2009 at 2:37 AM, Maciej Pigulski
<ma...@gmail.com>wrote:

>
> I had problems with getting to Subjects session to store the authorization
> info - SecurityUtils.getSubject() was returning a null value. I guess the
> issue is that this object does not exist in this stage, but I couldn't get
> any other idea how to get into the Session object.


That is extremely odd.  There should _always_ be a Subject for any thread's
execution.  If one does not exist at the time getSubject() is called, it
should have been created automatically.

Are you running in a webapp or a standalone application?

Regards,

Les



I was testing it in a standalone application running outside any containter (snippet of this class is in my first post in this thread). My target application is a web application.

Take notice that I'm trying to SecurityUtils.getSubject() inside overriding class that extends ActiveDirectoryRealm in queryForAuthenticationInfo(...) method. Then it returns null.


Regards,
Maciej

-- 
View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2562906.html
Sent from the JSecurity User mailing list archive at Nabble.com.


Re: Reading user roles from Active Directory

Posted by Les Hazlewood <lh...@apache.org>.
On Tue, Mar 31, 2009 at 2:37 AM, Maciej Pigulski
<ma...@gmail.com>wrote:

>
> I had problems with getting to Subjects session to store the authorization
> info - SecurityUtils.getSubject() was returning a null value. I guess the
> issue is that this object does not exist in this stage, but I couldn't get
> any other idea how to get into the Session object.


That is extremely odd.  There should _always_ be a Subject for any thread's
execution.  If one does not exist at the time getSubject() is called, it
should have been created automatically.

Are you running in a webapp or a standalone application?

Regards,

Les

Re: Reading user roles from Active Directory

Posted by Maciej Pigulski <ma...@gmail.com>.
Jeremy, 

you are absolutely right and I'm not proud at all from this solution, but it is the fastest implementation I've managed to get to work. I treat this as a temporary solution until jSecurity 1.0.

Anyway, obviously I was doing something wrong while trying to make your solution working. 

I had problems with getting to Subjects session to store the authorization info - SecurityUtils.getSubject() was returning a null value. I guess the issue is that this object does not exist in this stage, but I couldn't get any other idea how to get into the Session object.

Another issue was getting the AuthorizationInfo to work. Without setting systemUsername and systemPassword AuthorizationInfo was trying to obtain data from Active Directory with a null user and this failed. I think I should get this information using LdapContext (a new object, not the default one) with credentials passed by this user, but the queryForAuthorizationInfo uses getRoleNamesForUser(...) private method so I'd have to copy paste this method with LdapContext ldapContext = ldapContextFactory.getLdapContext(username, password); used instead the  LdapContext ldapContext = ldapContextFactory.getSystemLdapContext(); one. This bugs me because when I'm copy-pasting then I'm doing something obviously wrong so I guess this way is not the correct way.

Thanks for pointing me out possible issues with this solution. Now I'm getting worried ;)

Maciej



Marciej,

This approach isn't the most secure since each time a new user  
authenticates, the system username and password will be updated to  
store their username and password.

For example:
1) Bob logs in.  His username/password are set as the system username/ 
password
2) Bob does a permission check and it uses bob's account to access LDAP
3) Sue logs in.  Her username/password are set as the system username/ 
password
4) Bob does another permission check.  this time Sue's credentials are  
used to access LDAP

In this scenario, it's impossible to predict which user and password  
will be used to authenticate.

Even neglecting the security implications, there is a possible race  
condition that could result in errors obtaining authorization  
information.  Since DefaultLdapContextFactory is a singleton and is  
not synchronized in any way, it's possible that an authorization check  
will occur in one thread while in another thread the system username  
and password are being updated due to another user authenticating.   
This means that username could be set to "Sue" while the password is  
still set to Bob's password.  This would result in an LDAP error since  
Bob's password is invalid for Sue's account.

If you really want to just store the user's credentials, I would  
suggest storing them in the user's principal and pulling them out of  
the Principal object when you need to check for authorization info.   
That being said, holding onto a user's credentials in memory is  
considered a bad security practice, since if anyone hacks your machine  
or gets access to RAM, they could grab all of your user's  
credentials.  Also, since the credentials would be stored in a  
session, and sessions are sometimes serialized to disk, a hacker could  
possible just get access to the serialized sessions file and obtain  
their credentials from the file.

My 2 cents,
Jeremy

On Mar 30, 2009, at 10:43 AM, Maciej Pigulski wrote:

>
> Hello,
>
> thanks for the clarification. I've done it in a 3rd way by  
> overriding DefaultLdapContextFactory settings in  
> queryForAuthenticationInfo:
>
>
> 	/* (non-Javadoc)
> 	 * @see  
> org 
> .jsecurity 
> .realm 
> .activedirectory 
> .ActiveDirectoryRealm 
> #queryForAuthenticationInfo(org.jsecurity.authc.AuthenticationToken,  
> org.jsecurity.realm.ldap.LdapContextFactory)
> 	 */
> 	@Override
> 	protected AuthenticationInfo  
> queryForAuthenticationInfo(AuthenticationToken token,
> 			LdapContextFactory ldapContextFactory) throws NamingException {
>
> 		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
> 		DefaultLdapContextFactory defaultLdapContextFactory =  
> (DefaultLdapContextFactory) ldapContextFactory;
> 		defaultLdapContextFactory.setSystemUsername(upToken.getUsername());
> 		 
> defaultLdapContextFactory 
> .setSystemPassword(upToken.getPassword().toString());
>
> 		return super.queryForAuthenticationInfo(token, ldapContextFactory);
> 	}
>
>
> Maybe it is not the best workaround but I had no time to do it like  
> you suggested. Looking forward for jSecurity 1.0, keep up the good  
> work!
>
> Greetings,
> Maciej
>
>
> Maciej,
>
> The problem is that if the LDAP server requires credentials to login
> (as they typically do), there is no way to obtain authorization
> information at a later point without having a username/password to
> login to the LDAP server.  Due to the way JSecurity works,
> authentication and authorization happen independently of each other,
> and so when authorization occurs we do not have the username/password
> that was originally used to authenticate (as we shouldn't).
>
> I think this brings to light an option that JSecurity should offer -
> which is to allow authorization information to be obtained at login
> and cached for the duration of a user's session.  This is the way many
> security frameworks operate, and usually we tout the fact that
> JSecurity doesn't work this way as an advantage (i.e. dynamic security
> updates, flexible caching, etc.)
>
> However - in this case it's a disadvantage because login is the only
> time when we have the information we need to obtain the authorization
> information (since the authentication info is needed to obtain it).  I
> think there will be other scenarios where this is the case (external
> authorization systems, SSO systems, etc.) so I do think JSecurity
> should offer this mechanism as an option.  I'll open a JIRA issue to
> address this for the 1.0 release.
>
> As far as a short-term workaround, you could either:
> 1) configure the system username and password for now (as I think
> you've already done)
> or
> 2) extend the Active Directory realm, and override
> queryForAuthenticationInfo to grab the AuthorizationInfo (similar to
> how queryForAuthorizationInfo does) at login.  You could then cache
> the AuthorizationInfo in the subject's session and override
> queryForAuthorizationInfo to return the session-cached authorization
> information.  This is similar to how JSecurity would probably do this
> in the future, but obviously you'd have to manually implement it.
>
> Please let me know if you have any further questions or ideas!
>
> Jeremy
>
> On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:
>
>>
>> Unfortunately this is still an issue to me.
>>
>>
>> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I
>> don't
>> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,
>> have
>> you been able to work through this issue?
>>
>> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
>> <ma...@gmail.com>wrote:
>>
>>>
>>> Hello,
>>>
>>> I have a following problem with jSecurity, ActiveDirectoryRealm and
>>> Groups
>>> mappings.
>>>
>>> I have an AD setup on one server (WHEEL) with a simple user called
>>> user1.
>>> This user is in ldap group called
>>> "login" (CN=login,OU=Groups,DC=WHEEL).
>>>
>>> Next I'm trying to login and retrieve roles for this user. Login
>>> works fine
>>> but when it comes to user roles I  have to additionally provide
>>> username
>>> and
>>> password in activeDirectoryRealm.setSystemUsername/Password. I've
>>> found in
>>> the API that it is a pretty normal behaviour (but IMHO very
>>> inconvenient)
>>> (
>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)
>>> <http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29
>>>>
>>> :
>>> <cite>
>>> systemUsername - the username to use when logging into the LDAP
>>> server for
>>> authorization.
>>> </cite>
>>>
>>> Is there any tricky way to bypass this? Setting same credentials on
>>> two
>>> objects to authorize and authenticate one user seems to be quite
>>> wrong.
>>>
>>> I've managed to obtain this by creating a super user (with  
>>> enterprise
>>> administrator rights) that has hardcoded username and password in
>>> application (systemUsername and systemPassword) and this works for
>>> authenticating other users but I'd like to avoid using such
>>> powerfull user
>>> just for groups fetching as it seems to be an huge overkill for me.
>>>
>>> Here is a class I'm using to test with AD:
>>>
>>> import java.util.HashMap;
>>> import java.util.Map;
>>>
>>> import org.jsecurity.authc.UsernamePasswordToken;
>>> import org.jsecurity.mgt.DefaultSecurityManager;
>>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>>> import org.jsecurity.subject.Subject;
>>>
>>> public class TestJSec {
>>>
>>>      private DefaultSecurityManager securityManager = new
>>> DefaultSecurityManager();
>>>      private ActiveDirectoryRealm activeDirectoryRealm = new
>>> ActiveDirectoryRealm();
>>>
>>>      public TestJSec() {
>>>              activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>>              activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>>
>>> activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>>> if this is
>>> missing user wont fetch his roles
>>>              activeDirectoryRealm.setSystemPassword("user1");
>>> // if this
>>> is missing user wont fetch his roles
>>>              Map<String, String> map = new HashMap<String,
>>> String>();
>>>              map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>>              activeDirectoryRealm.setGroupRolesMap(map);
>>>
>>>              securityManager.setRealm(activeDirectoryRealm);
>>>      }
>>>
>>>      private void testLogin() {
>>>              UsernamePasswordToken userToken = new
>>> UsernamePasswordToken("user1@wheel",
>>> "user1");
>>>
>>>              Subject subject = securityManager.login(userToken);
>>>              if (subject.hasRole("login")) {
>>>                      System.out.println("User in role");
>>>              } else {
>>>                      System.out.println("User has no role");
>>>              }
>>>      }
>>>
>>>      public static void main(String[] args) {
>>>              TestJSec tjs = new TestJSec();
>>>              tjs.testLogin();
>>>      }
>>> }
>>>
>>>
>>> For example in jBoss this config works without a super user:
>>>
>>>
>>> <application-policy name="DLG_REGW_POLICY">
>>>      <authentication>
>>>              <login-module
>>> code="org.jboss.security.auth.spi.LdapLoginModule"
>>> flag="required" >
>>>                      <module-option
>>> name="java.naming.provider.url">ldap://ldap-host:389/</module- 
>>> option>
>>>                      <module-option
>>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>>                      <module-option
>>> name="matchOnUserDN">false</module-option>
>>>                      <module-option
>>> name="uidAttributeID">sAMAccountName</module-option>
>>>                      <module-option
>>> name="roleAttributeID">memberOf</module-option>
>>>                      <module-option
>>> name="roleAttributeIsDN">true</module-option>
>>>                      <module-option
>>> name="roleNameAttributeID">name</module-option>
>>>                      <module-option
>>> name="searchTimeLimit">5000</module-option>
>>>                      <module-option
>>> name="allowEmptyPasswords">false</module-option>
>>>                      <module-option
>>> name="searchScope">SUBTREE_SCOPE</module-option>
>>>              </login-module>
>>>      </authentication>
>>> </application-policy>
>>>
>>> --
>>> View this message in context:
>>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>
>>>
>>
>>
>>
>> -- 
>> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>
>
>
>
>
> -- 
> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2557591.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>




-- 
View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2561437.html
Sent from the JSecurity User mailing list archive at Nabble.com.


Re: Reading user roles from Active Directory

Posted by Jeremy Haile <jh...@fastmail.fm>.
Marciej,

This approach isn't the most secure since each time a new user  
authenticates, the system username and password will be updated to  
store their username and password.

For example:
1) Bob logs in.  His username/password are set as the system username/ 
password
2) Bob does a permission check and it uses bob's account to access LDAP
3) Sue logs in.  Her username/password are set as the system username/ 
password
4) Bob does another permission check.  this time Sue's credentials are  
used to access LDAP

In this scenario, it's impossible to predict which user and password  
will be used to authenticate.

Even neglecting the security implications, there is a possible race  
condition that could result in errors obtaining authorization  
information.  Since DefaultLdapContextFactory is a singleton and is  
not synchronized in any way, it's possible that an authorization check  
will occur in one thread while in another thread the system username  
and password are being updated due to another user authenticating.   
This means that username could be set to "Sue" while the password is  
still set to Bob's password.  This would result in an LDAP error since  
Bob's password is invalid for Sue's account.

If you really want to just store the user's credentials, I would  
suggest storing them in the user's principal and pulling them out of  
the Principal object when you need to check for authorization info.   
That being said, holding onto a user's credentials in memory is  
considered a bad security practice, since if anyone hacks your machine  
or gets access to RAM, they could grab all of your user's  
credentials.  Also, since the credentials would be stored in a  
session, and sessions are sometimes serialized to disk, a hacker could  
possible just get access to the serialized sessions file and obtain  
their credentials from the file.

My 2 cents,
Jeremy

On Mar 30, 2009, at 10:43 AM, Maciej Pigulski wrote:

>
> Hello,
>
> thanks for the clarification. I've done it in a 3rd way by  
> overriding DefaultLdapContextFactory settings in  
> queryForAuthenticationInfo:
>
>
> 	/* (non-Javadoc)
> 	 * @see  
> org 
> .jsecurity 
> .realm 
> .activedirectory 
> .ActiveDirectoryRealm 
> #queryForAuthenticationInfo(org.jsecurity.authc.AuthenticationToken,  
> org.jsecurity.realm.ldap.LdapContextFactory)
> 	 */
> 	@Override
> 	protected AuthenticationInfo  
> queryForAuthenticationInfo(AuthenticationToken token,
> 			LdapContextFactory ldapContextFactory) throws NamingException {
>
> 		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
> 		DefaultLdapContextFactory defaultLdapContextFactory =  
> (DefaultLdapContextFactory) ldapContextFactory;
> 		defaultLdapContextFactory.setSystemUsername(upToken.getUsername());
> 		 
> defaultLdapContextFactory 
> .setSystemPassword(upToken.getPassword().toString());
>
> 		return super.queryForAuthenticationInfo(token, ldapContextFactory);
> 	}
>
>
> Maybe it is not the best workaround but I had no time to do it like  
> you suggested. Looking forward for jSecurity 1.0, keep up the good  
> work!
>
> Greetings,
> Maciej
>
>
> Maciej,
>
> The problem is that if the LDAP server requires credentials to login
> (as they typically do), there is no way to obtain authorization
> information at a later point without having a username/password to
> login to the LDAP server.  Due to the way JSecurity works,
> authentication and authorization happen independently of each other,
> and so when authorization occurs we do not have the username/password
> that was originally used to authenticate (as we shouldn't).
>
> I think this brings to light an option that JSecurity should offer -
> which is to allow authorization information to be obtained at login
> and cached for the duration of a user's session.  This is the way many
> security frameworks operate, and usually we tout the fact that
> JSecurity doesn't work this way as an advantage (i.e. dynamic security
> updates, flexible caching, etc.)
>
> However - in this case it's a disadvantage because login is the only
> time when we have the information we need to obtain the authorization
> information (since the authentication info is needed to obtain it).  I
> think there will be other scenarios where this is the case (external
> authorization systems, SSO systems, etc.) so I do think JSecurity
> should offer this mechanism as an option.  I'll open a JIRA issue to
> address this for the 1.0 release.
>
> As far as a short-term workaround, you could either:
> 1) configure the system username and password for now (as I think
> you've already done)
> or
> 2) extend the Active Directory realm, and override
> queryForAuthenticationInfo to grab the AuthorizationInfo (similar to
> how queryForAuthorizationInfo does) at login.  You could then cache
> the AuthorizationInfo in the subject's session and override
> queryForAuthorizationInfo to return the session-cached authorization
> information.  This is similar to how JSecurity would probably do this
> in the future, but obviously you'd have to manually implement it.
>
> Please let me know if you have any further questions or ideas!
>
> Jeremy
>
> On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:
>
>>
>> Unfortunately this is still an issue to me.
>>
>>
>> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I
>> don't
>> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,
>> have
>> you been able to work through this issue?
>>
>> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
>> <ma...@gmail.com>wrote:
>>
>>>
>>> Hello,
>>>
>>> I have a following problem with jSecurity, ActiveDirectoryRealm and
>>> Groups
>>> mappings.
>>>
>>> I have an AD setup on one server (WHEEL) with a simple user called
>>> user1.
>>> This user is in ldap group called
>>> "login" (CN=login,OU=Groups,DC=WHEEL).
>>>
>>> Next I'm trying to login and retrieve roles for this user. Login
>>> works fine
>>> but when it comes to user roles I  have to additionally provide
>>> username
>>> and
>>> password in activeDirectoryRealm.setSystemUsername/Password. I've
>>> found in
>>> the API that it is a pretty normal behaviour (but IMHO very
>>> inconvenient)
>>> (
>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)
>>> <http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29
>>>>
>>> :
>>> <cite>
>>> systemUsername - the username to use when logging into the LDAP
>>> server for
>>> authorization.
>>> </cite>
>>>
>>> Is there any tricky way to bypass this? Setting same credentials on
>>> two
>>> objects to authorize and authenticate one user seems to be quite
>>> wrong.
>>>
>>> I've managed to obtain this by creating a super user (with  
>>> enterprise
>>> administrator rights) that has hardcoded username and password in
>>> application (systemUsername and systemPassword) and this works for
>>> authenticating other users but I'd like to avoid using such
>>> powerfull user
>>> just for groups fetching as it seems to be an huge overkill for me.
>>>
>>> Here is a class I'm using to test with AD:
>>>
>>> import java.util.HashMap;
>>> import java.util.Map;
>>>
>>> import org.jsecurity.authc.UsernamePasswordToken;
>>> import org.jsecurity.mgt.DefaultSecurityManager;
>>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>>> import org.jsecurity.subject.Subject;
>>>
>>> public class TestJSec {
>>>
>>>      private DefaultSecurityManager securityManager = new
>>> DefaultSecurityManager();
>>>      private ActiveDirectoryRealm activeDirectoryRealm = new
>>> ActiveDirectoryRealm();
>>>
>>>      public TestJSec() {
>>>              activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>>              activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>>
>>> activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>>> if this is
>>> missing user wont fetch his roles
>>>              activeDirectoryRealm.setSystemPassword("user1");
>>> // if this
>>> is missing user wont fetch his roles
>>>              Map<String, String> map = new HashMap<String,
>>> String>();
>>>              map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>>              activeDirectoryRealm.setGroupRolesMap(map);
>>>
>>>              securityManager.setRealm(activeDirectoryRealm);
>>>      }
>>>
>>>      private void testLogin() {
>>>              UsernamePasswordToken userToken = new
>>> UsernamePasswordToken("user1@wheel",
>>> "user1");
>>>
>>>              Subject subject = securityManager.login(userToken);
>>>              if (subject.hasRole("login")) {
>>>                      System.out.println("User in role");
>>>              } else {
>>>                      System.out.println("User has no role");
>>>              }
>>>      }
>>>
>>>      public static void main(String[] args) {
>>>              TestJSec tjs = new TestJSec();
>>>              tjs.testLogin();
>>>      }
>>> }
>>>
>>>
>>> For example in jBoss this config works without a super user:
>>>
>>>
>>> <application-policy name="DLG_REGW_POLICY">
>>>      <authentication>
>>>              <login-module
>>> code="org.jboss.security.auth.spi.LdapLoginModule"
>>> flag="required" >
>>>                      <module-option
>>> name="java.naming.provider.url">ldap://ldap-host:389/</module- 
>>> option>
>>>                      <module-option
>>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>>                      <module-option
>>> name="matchOnUserDN">false</module-option>
>>>                      <module-option
>>> name="uidAttributeID">sAMAccountName</module-option>
>>>                      <module-option
>>> name="roleAttributeID">memberOf</module-option>
>>>                      <module-option
>>> name="roleAttributeIsDN">true</module-option>
>>>                      <module-option
>>> name="roleNameAttributeID">name</module-option>
>>>                      <module-option
>>> name="searchTimeLimit">5000</module-option>
>>>                      <module-option
>>> name="allowEmptyPasswords">false</module-option>
>>>                      <module-option
>>> name="searchScope">SUBTREE_SCOPE</module-option>
>>>              </login-module>
>>>      </authentication>
>>> </application-policy>
>>>
>>> --
>>> View this message in context:
>>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>
>>>
>>
>>
>>
>> -- 
>> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>
>
>
>
>
> -- 
> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2557591.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>


Re: Reading user roles from Active Directory

Posted by Maciej Pigulski <ma...@gmail.com>.
Hello,

thanks for the clarification. I've done it in a 3rd way by overriding DefaultLdapContextFactory settings in queryForAuthenticationInfo:


	/* (non-Javadoc)
	 * @see org.jsecurity.realm.activedirectory.ActiveDirectoryRealm#queryForAuthenticationInfo(org.jsecurity.authc.AuthenticationToken, org.jsecurity.realm.ldap.LdapContextFactory)
	 */
	@Override
	protected AuthenticationInfo queryForAuthenticationInfo(AuthenticationToken token,
			LdapContextFactory ldapContextFactory) throws NamingException {

		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		DefaultLdapContextFactory defaultLdapContextFactory = (DefaultLdapContextFactory) ldapContextFactory;
		defaultLdapContextFactory.setSystemUsername(upToken.getUsername());
		defaultLdapContextFactory.setSystemPassword(upToken.getPassword().toString());

		return super.queryForAuthenticationInfo(token, ldapContextFactory);
	}


Maybe it is not the best workaround but I had no time to do it like you suggested. Looking forward for jSecurity 1.0, keep up the good work!

Greetings,
Maciej


Maciej,

The problem is that if the LDAP server requires credentials to login  
(as they typically do), there is no way to obtain authorization  
information at a later point without having a username/password to  
login to the LDAP server.  Due to the way JSecurity works,  
authentication and authorization happen independently of each other,  
and so when authorization occurs we do not have the username/password  
that was originally used to authenticate (as we shouldn't).

I think this brings to light an option that JSecurity should offer -  
which is to allow authorization information to be obtained at login  
and cached for the duration of a user's session.  This is the way many  
security frameworks operate, and usually we tout the fact that  
JSecurity doesn't work this way as an advantage (i.e. dynamic security  
updates, flexible caching, etc.)

However - in this case it's a disadvantage because login is the only  
time when we have the information we need to obtain the authorization  
information (since the authentication info is needed to obtain it).  I  
think there will be other scenarios where this is the case (external  
authorization systems, SSO systems, etc.) so I do think JSecurity  
should offer this mechanism as an option.  I'll open a JIRA issue to  
address this for the 1.0 release.

As far as a short-term workaround, you could either:
1) configure the system username and password for now (as I think  
you've already done)
or
2) extend the Active Directory realm, and override  
queryForAuthenticationInfo to grab the AuthorizationInfo (similar to  
how queryForAuthorizationInfo does) at login.  You could then cache  
the AuthorizationInfo in the subject's session and override  
queryForAuthorizationInfo to return the session-cached authorization  
information.  This is similar to how JSecurity would probably do this  
in the future, but obviously you'd have to manually implement it.

Please let me know if you have any further questions or ideas!

Jeremy

On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:

>
> Unfortunately this is still an issue to me.
>
>
> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I  
> don't
> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,   
> have
> you been able to work through this issue?
>
> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
> <ma...@gmail.com>wrote:
>
>>
>> Hello,
>>
>> I have a following problem with jSecurity, ActiveDirectoryRealm and  
>> Groups
>> mappings.
>>
>> I have an AD setup on one server (WHEEL) with a simple user called  
>> user1.
>> This user is in ldap group called  
>> "login" (CN=login,OU=Groups,DC=WHEEL).
>>
>> Next I'm trying to login and retrieve roles for this user. Login  
>> works fine
>> but when it comes to user roles I  have to additionally provide  
>> username
>> and
>> password in activeDirectoryRealm.setSystemUsername/Password. I've  
>> found in
>> the API that it is a pretty normal behaviour (but IMHO very  
>> inconvenient)
>> (
>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String) 
>> <http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29 
>> >
>> :
>> <cite>
>> systemUsername - the username to use when logging into the LDAP  
>> server for
>> authorization.
>> </cite>
>>
>> Is there any tricky way to bypass this? Setting same credentials on  
>> two
>> objects to authorize and authenticate one user seems to be quite  
>> wrong.
>>
>> I've managed to obtain this by creating a super user (with enterprise
>> administrator rights) that has hardcoded username and password in
>> application (systemUsername and systemPassword) and this works for
>> authenticating other users but I'd like to avoid using such  
>> powerfull user
>> just for groups fetching as it seems to be an huge overkill for me.
>>
>> Here is a class I'm using to test with AD:
>>
>> import java.util.HashMap;
>> import java.util.Map;
>>
>> import org.jsecurity.authc.UsernamePasswordToken;
>> import org.jsecurity.mgt.DefaultSecurityManager;
>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>> import org.jsecurity.subject.Subject;
>>
>> public class TestJSec {
>>
>>       private DefaultSecurityManager securityManager = new
>> DefaultSecurityManager();
>>       private ActiveDirectoryRealm activeDirectoryRealm = new
>> ActiveDirectoryRealm();
>>
>>       public TestJSec() {
>>               activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>               activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>                
>> activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>> if this is
>> missing user wont fetch his roles
>>               activeDirectoryRealm.setSystemPassword("user1");
>> // if this
>> is missing user wont fetch his roles
>>               Map<String, String> map = new HashMap<String,  
>> String>();
>>               map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>               activeDirectoryRealm.setGroupRolesMap(map);
>>
>>               securityManager.setRealm(activeDirectoryRealm);
>>       }
>>
>>       private void testLogin() {
>>               UsernamePasswordToken userToken = new
>> UsernamePasswordToken("user1@wheel",
>> "user1");
>>
>>               Subject subject = securityManager.login(userToken);
>>               if (subject.hasRole("login")) {
>>                       System.out.println("User in role");
>>               } else {
>>                       System.out.println("User has no role");
>>               }
>>       }
>>
>>       public static void main(String[] args) {
>>               TestJSec tjs = new TestJSec();
>>               tjs.testLogin();
>>       }
>> }
>>
>>
>> For example in jBoss this config works without a super user:
>>
>>
>> <application-policy name="DLG_REGW_POLICY">
>>       <authentication>
>>               <login-module
>> code="org.jboss.security.auth.spi.LdapLoginModule"
>> flag="required" >
>>                       <module-option
>> name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
>>                       <module-option
>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>                       <module-option
>> name="matchOnUserDN">false</module-option>
>>                       <module-option
>> name="uidAttributeID">sAMAccountName</module-option>
>>                       <module-option
>> name="roleAttributeID">memberOf</module-option>
>>                       <module-option
>> name="roleAttributeIsDN">true</module-option>
>>                       <module-option
>> name="roleNameAttributeID">name</module-option>
>>                       <module-option
>> name="searchTimeLimit">5000</module-option>
>>                       <module-option
>> name="allowEmptyPasswords">false</module-option>
>>                       <module-option
>> name="searchScope">SUBTREE_SCOPE</module-option>
>>               </login-module>
>>       </authentication>
>> </application-policy>
>>
>> --
>> View this message in context:
>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>
>>
>
>
>
> -- 
> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>




-- 
View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2557591.html
Sent from the JSecurity User mailing list archive at Nabble.com.


Re: Reading user roles from Active Directory

Posted by Jeremy Haile <jh...@fastmail.fm>.
Sorry - hadn't gotten around to filing it.  Here it is: https://issues.apache.org/jira/browse/KI-73

On Mar 30, 2009, at 1:09 PM, Les Hazlewood wrote:

> Oops - you said you'd do that in the email - sorry I missed it.   
> What is the issue #?
>
> On Mon, Mar 30, 2009 at 1:08 PM, Les Hazlewood  
> <lh...@apache.org> wrote:
> Jeremy, you bring up some good points (caching authc info if a user  
> wants us to).  Can you please open a Jira issue to address this?   
> That way we have it as a place holder during discussion.
>
>
> On Wed, Mar 25, 2009 at 1:05 PM, Jeremy Haile <jh...@fastmail.fm>  
> wrote:
> Maciej,
>
> The problem is that if the LDAP server requires credentials to login  
> (as they typically do), there is no way to obtain authorization  
> information at a later point without having a username/password to  
> login to the LDAP server.  Due to the way JSecurity works,  
> authentication and authorization happen independently of each other,  
> and so when authorization occurs we do not have the username/ 
> password that was originally used to authenticate (as we shouldn't).
>
> I think this brings to light an option that JSecurity should offer -  
> which is to allow authorization information to be obtained at login  
> and cached for the duration of a user's session.  This is the way  
> many security frameworks operate, and usually we tout the fact that  
> JSecurity doesn't work this way as an advantage (i.e. dynamic  
> security updates, flexible caching, etc.)
>
> However - in this case it's a disadvantage because login is the only  
> time when we have the information we need to obtain the  
> authorization information (since the authentication info is needed  
> to obtain it).  I think there will be other scenarios where this is  
> the case (external authorization systems, SSO systems, etc.) so I do  
> think JSecurity should offer this mechanism as an option.  I'll open  
> a JIRA issue to address this for the 1.0 release.
>
> As far as a short-term workaround, you could either:
> 1) configure the system username and password for now (as I think  
> you've already done)
> or
> 2) extend the Active Directory realm, and override  
> queryForAuthenticationInfo to grab the AuthorizationInfo (similar to  
> how queryForAuthorizationInfo does) at login.  You could then cache  
> the AuthorizationInfo in the subject's session and override  
> queryForAuthorizationInfo to return the session-cached authorization  
> information.  This is similar to how JSecurity would probably do  
> this in the future, but obviously you'd have to manually implement it.
>
> Please let me know if you have any further questions or ideas!
>
> Jeremy
>
>
> On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:
>
>
> Unfortunately this is still an issue to me.
>
>
> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I  
> don't
> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,   
> have
> you been able to work through this issue?
>
> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
> <ma...@gmail.com>wrote:
>
>
> Hello,
>
> I have a following problem with jSecurity, ActiveDirectoryRealm and  
> Groups
> mappings.
>
> I have an AD setup on one server (WHEEL) with a simple user called  
> user1.
> This user is in ldap group called  
> "login" (CN=login,OU=Groups,DC=WHEEL).
>
> Next I'm trying to login and retrieve roles for this user. Login  
> works fine
> but when it comes to user roles I  have to additionally provide  
> username
> and
> password in activeDirectoryRealm.setSystemUsername/Password. I've  
> found in
> the API that it is a pretty normal behaviour (but IMHO very  
> inconvenient)
> (
> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String) 
> <http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29 
> >
> :
> <cite>
> systemUsername - the username to use when logging into the LDAP  
> server for
> authorization.
> </cite>
>
> Is there any tricky way to bypass this? Setting same credentials on  
> two
> objects to authorize and authenticate one user seems to be quite  
> wrong.
>
> I've managed to obtain this by creating a super user (with enterprise
> administrator rights) that has hardcoded username and password in
> application (systemUsername and systemPassword) and this works for
> authenticating other users but I'd like to avoid using such  
> powerfull user
> just for groups fetching as it seems to be an huge overkill for me.
>
> Here is a class I'm using to test with AD:
>
> import java.util.HashMap;
> import java.util.Map;
>
> import org.jsecurity.authc.UsernamePasswordToken;
> import org.jsecurity.mgt.DefaultSecurityManager;
> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
> import org.jsecurity.subject.Subject;
>
> public class TestJSec {
>
>      private DefaultSecurityManager securityManager = new
> DefaultSecurityManager();
>      private ActiveDirectoryRealm activeDirectoryRealm = new
> ActiveDirectoryRealm();
>
>      public TestJSec() {
>              activeDirectoryRealm.setSearchBase("DC=WHEEL");
>              activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>              activeDirectoryRealm.setSystemUsername("user1@wheel"); //
> if this is
> missing user wont fetch his roles
>              activeDirectoryRealm.setSystemPassword("user1");
> // if this
> is missing user wont fetch his roles
>              Map<String, String> map = new HashMap<String, String>();
>              map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>              activeDirectoryRealm.setGroupRolesMap(map);
>
>              securityManager.setRealm(activeDirectoryRealm);
>      }
>
>      private void testLogin() {
>              UsernamePasswordToken userToken = new
> UsernamePasswordToken("user1@wheel",
> "user1");
>
>              Subject subject = securityManager.login(userToken);
>              if (subject.hasRole("login")) {
>                      System.out.println("User in role");
>              } else {
>                      System.out.println("User has no role");
>              }
>      }
>
>      public static void main(String[] args) {
>              TestJSec tjs = new TestJSec();
>              tjs.testLogin();
>      }
> }
>
>
> For example in jBoss this config works without a super user:
>
>
> <application-policy name="DLG_REGW_POLICY">
>      <authentication>
>              <login-module
> code="org.jboss.security.auth.spi.LdapLoginModule"
> flag="required" >
>                      <module-option
> name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
>                      <module-option
> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>                      <module-option
> name="matchOnUserDN">false</module-option>
>                      <module-option
> name="uidAttributeID">sAMAccountName</module-option>
>                      <module-option
> name="roleAttributeID">memberOf</module-option>
>                      <module-option
> name="roleAttributeIsDN">true</module-option>
>                      <module-option
> name="roleNameAttributeID">name</module-option>
>                      <module-option
> name="searchTimeLimit">5000</module-option>
>                      <module-option
> name="allowEmptyPasswords">false</module-option>
>                      <module-option
> name="searchScope">SUBTREE_SCOPE</module-option>
>              </login-module>
>      </authentication>
> </application-policy>
>
> --
> View this message in context:
> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>
>
>
>
>
> -- 
> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>
>
>
>


Re: Reading user roles from Active Directory

Posted by Les Hazlewood <lh...@apache.org>.
Oops - you said you'd do that in the email - sorry I missed it.  What is the
issue #?

On Mon, Mar 30, 2009 at 1:08 PM, Les Hazlewood <lh...@apache.org>wrote:

> Jeremy, you bring up some good points (caching authc info if a user wants
> us to).  Can you please open a Jira issue to address this?  That way we have
> it as a place holder during discussion.
>
>
> On Wed, Mar 25, 2009 at 1:05 PM, Jeremy Haile <jh...@fastmail.fm> wrote:
>
>> Maciej,
>>
>> The problem is that if the LDAP server requires credentials to login (as
>> they typically do), there is no way to obtain authorization information at a
>> later point without having a username/password to login to the LDAP server.
>>  Due to the way JSecurity works, authentication and authorization happen
>> independently of each other, and so when authorization occurs we do not have
>> the username/password that was originally used to authenticate (as we
>> shouldn't).
>>
>> I think this brings to light an option that JSecurity should offer - which
>> is to allow authorization information to be obtained at login and cached for
>> the duration of a user's session.  This is the way many security frameworks
>> operate, and usually we tout the fact that JSecurity doesn't work this way
>> as an advantage (i.e. dynamic security updates, flexible caching, etc.)
>>
>> However - in this case it's a disadvantage because login is the only time
>> when we have the information we need to obtain the authorization information
>> (since the authentication info is needed to obtain it).  I think there will
>> be other scenarios where this is the case (external authorization systems,
>> SSO systems, etc.) so I do think JSecurity should offer this mechanism as an
>> option.  I'll open a JIRA issue to address this for the 1.0 release.
>>
>> As far as a short-term workaround, you could either:
>> 1) configure the system username and password for now (as I think you've
>> already done)
>> or
>> 2) extend the Active Directory realm, and override
>> queryForAuthenticationInfo to grab the AuthorizationInfo (similar to how
>> queryForAuthorizationInfo does) at login.  You could then cache the
>> AuthorizationInfo in the subject's session and override
>> queryForAuthorizationInfo to return the session-cached authorization
>> information.  This is similar to how JSecurity would probably do this in the
>> future, but obviously you'd have to manually implement it.
>>
>> Please let me know if you have any further questions or ideas!
>>
>> Jeremy
>>
>>
>> On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:
>>
>>
>>> Unfortunately this is still an issue to me.
>>>
>>>
>>> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I don't
>>> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,  have
>>> you been able to work through this issue?
>>>
>>> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
>>> <ma...@gmail.com>wrote:
>>>
>>>
>>>> Hello,
>>>>
>>>> I have a following problem with jSecurity, ActiveDirectoryRealm and
>>>> Groups
>>>> mappings.
>>>>
>>>> I have an AD setup on one server (WHEEL) with a simple user called
>>>> user1.
>>>> This user is in ldap group called "login" (CN=login,OU=Groups,DC=WHEEL).
>>>>
>>>> Next I'm trying to login and retrieve roles for this user. Login works
>>>> fine
>>>> but when it comes to user roles I  have to additionally provide username
>>>> and
>>>> password in activeDirectoryRealm.setSystemUsername/Password. I've found
>>>> in
>>>> the API that it is a pretty normal behaviour (but IMHO very
>>>> inconvenient)
>>>> (
>>>>
>>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)<http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29>
>>>> <
>>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29
>>>> >
>>>> :
>>>> <cite>
>>>> systemUsername - the username to use when logging into the LDAP server
>>>> for
>>>> authorization.
>>>> </cite>
>>>>
>>>> Is there any tricky way to bypass this? Setting same credentials on two
>>>> objects to authorize and authenticate one user seems to be quite wrong.
>>>>
>>>> I've managed to obtain this by creating a super user (with enterprise
>>>> administrator rights) that has hardcoded username and password in
>>>> application (systemUsername and systemPassword) and this works for
>>>> authenticating other users but I'd like to avoid using such powerfull
>>>> user
>>>> just for groups fetching as it seems to be an huge overkill for me.
>>>>
>>>> Here is a class I'm using to test with AD:
>>>>
>>>> import java.util.HashMap;
>>>> import java.util.Map;
>>>>
>>>> import org.jsecurity.authc.UsernamePasswordToken;
>>>> import org.jsecurity.mgt.DefaultSecurityManager;
>>>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>>>> import org.jsecurity.subject.Subject;
>>>>
>>>> public class TestJSec {
>>>>
>>>>      private DefaultSecurityManager securityManager = new
>>>> DefaultSecurityManager();
>>>>      private ActiveDirectoryRealm activeDirectoryRealm = new
>>>> ActiveDirectoryRealm();
>>>>
>>>>      public TestJSec() {
>>>>              activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>>>              activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>>>              activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>>>> if this is
>>>> missing user wont fetch his roles
>>>>              activeDirectoryRealm.setSystemPassword("user1");
>>>> // if this
>>>> is missing user wont fetch his roles
>>>>              Map<String, String> map = new HashMap<String, String>();
>>>>              map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>>>              activeDirectoryRealm.setGroupRolesMap(map);
>>>>
>>>>              securityManager.setRealm(activeDirectoryRealm);
>>>>      }
>>>>
>>>>      private void testLogin() {
>>>>              UsernamePasswordToken userToken = new
>>>> UsernamePasswordToken("user1@wheel",
>>>> "user1");
>>>>
>>>>              Subject subject = securityManager.login(userToken);
>>>>              if (subject.hasRole("login")) {
>>>>                      System.out.println("User in role");
>>>>              } else {
>>>>                      System.out.println("User has no role");
>>>>              }
>>>>      }
>>>>
>>>>      public static void main(String[] args) {
>>>>              TestJSec tjs = new TestJSec();
>>>>              tjs.testLogin();
>>>>      }
>>>> }
>>>>
>>>>
>>>> For example in jBoss this config works without a super user:
>>>>
>>>>
>>>> <application-policy name="DLG_REGW_POLICY">
>>>>      <authentication>
>>>>              <login-module
>>>> code="org.jboss.security.auth.spi.LdapLoginModule"
>>>> flag="required" >
>>>>                      <module-option
>>>> name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
>>>>                      <module-option
>>>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>>>                      <module-option
>>>> name="matchOnUserDN">false</module-option>
>>>>                      <module-option
>>>> name="uidAttributeID">sAMAccountName</module-option>
>>>>                      <module-option
>>>> name="roleAttributeID">memberOf</module-option>
>>>>                      <module-option
>>>> name="roleAttributeIsDN">true</module-option>
>>>>                      <module-option
>>>> name="roleNameAttributeID">name</module-option>
>>>>                      <module-option
>>>> name="searchTimeLimit">5000</module-option>
>>>>                      <module-option
>>>> name="allowEmptyPasswords">false</module-option>
>>>>                      <module-option
>>>> name="searchScope">SUBTREE_SCOPE</module-option>
>>>>              </login-module>
>>>>      </authentication>
>>>> </application-policy>
>>>>
>>>> --
>>>> View this message in context:
>>>>
>>>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>>
>>>>
>>>>
>>>
>>>
>>> --
>>> View this message in context:
>>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>
>>>
>>
>

Re: Reading user roles from Active Directory

Posted by Les Hazlewood <lh...@apache.org>.
Jeremy, you bring up some good points (caching authc info if a user wants us
to).  Can you please open a Jira issue to address this?  That way we have it
as a place holder during discussion.

On Wed, Mar 25, 2009 at 1:05 PM, Jeremy Haile <jh...@fastmail.fm> wrote:

> Maciej,
>
> The problem is that if the LDAP server requires credentials to login (as
> they typically do), there is no way to obtain authorization information at a
> later point without having a username/password to login to the LDAP server.
>  Due to the way JSecurity works, authentication and authorization happen
> independently of each other, and so when authorization occurs we do not have
> the username/password that was originally used to authenticate (as we
> shouldn't).
>
> I think this brings to light an option that JSecurity should offer - which
> is to allow authorization information to be obtained at login and cached for
> the duration of a user's session.  This is the way many security frameworks
> operate, and usually we tout the fact that JSecurity doesn't work this way
> as an advantage (i.e. dynamic security updates, flexible caching, etc.)
>
> However - in this case it's a disadvantage because login is the only time
> when we have the information we need to obtain the authorization information
> (since the authentication info is needed to obtain it).  I think there will
> be other scenarios where this is the case (external authorization systems,
> SSO systems, etc.) so I do think JSecurity should offer this mechanism as an
> option.  I'll open a JIRA issue to address this for the 1.0 release.
>
> As far as a short-term workaround, you could either:
> 1) configure the system username and password for now (as I think you've
> already done)
> or
> 2) extend the Active Directory realm, and override
> queryForAuthenticationInfo to grab the AuthorizationInfo (similar to how
> queryForAuthorizationInfo does) at login.  You could then cache the
> AuthorizationInfo in the subject's session and override
> queryForAuthorizationInfo to return the session-cached authorization
> information.  This is similar to how JSecurity would probably do this in the
> future, but obviously you'd have to manually implement it.
>
> Please let me know if you have any further questions or ideas!
>
> Jeremy
>
>
> On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:
>
>
>> Unfortunately this is still an issue to me.
>>
>>
>> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I don't
>> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,  have
>> you been able to work through this issue?
>>
>> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
>> <ma...@gmail.com>wrote:
>>
>>
>>> Hello,
>>>
>>> I have a following problem with jSecurity, ActiveDirectoryRealm and
>>> Groups
>>> mappings.
>>>
>>> I have an AD setup on one server (WHEEL) with a simple user called user1.
>>> This user is in ldap group called "login" (CN=login,OU=Groups,DC=WHEEL).
>>>
>>> Next I'm trying to login and retrieve roles for this user. Login works
>>> fine
>>> but when it comes to user roles I  have to additionally provide username
>>> and
>>> password in activeDirectoryRealm.setSystemUsername/Password. I've found
>>> in
>>> the API that it is a pretty normal behaviour (but IMHO very inconvenient)
>>> (
>>>
>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)<http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29>
>>> <
>>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29
>>> >
>>> :
>>> <cite>
>>> systemUsername - the username to use when logging into the LDAP server
>>> for
>>> authorization.
>>> </cite>
>>>
>>> Is there any tricky way to bypass this? Setting same credentials on two
>>> objects to authorize and authenticate one user seems to be quite wrong.
>>>
>>> I've managed to obtain this by creating a super user (with enterprise
>>> administrator rights) that has hardcoded username and password in
>>> application (systemUsername and systemPassword) and this works for
>>> authenticating other users but I'd like to avoid using such powerfull
>>> user
>>> just for groups fetching as it seems to be an huge overkill for me.
>>>
>>> Here is a class I'm using to test with AD:
>>>
>>> import java.util.HashMap;
>>> import java.util.Map;
>>>
>>> import org.jsecurity.authc.UsernamePasswordToken;
>>> import org.jsecurity.mgt.DefaultSecurityManager;
>>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>>> import org.jsecurity.subject.Subject;
>>>
>>> public class TestJSec {
>>>
>>>      private DefaultSecurityManager securityManager = new
>>> DefaultSecurityManager();
>>>      private ActiveDirectoryRealm activeDirectoryRealm = new
>>> ActiveDirectoryRealm();
>>>
>>>      public TestJSec() {
>>>              activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>>              activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>>              activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>>> if this is
>>> missing user wont fetch his roles
>>>              activeDirectoryRealm.setSystemPassword("user1");
>>> // if this
>>> is missing user wont fetch his roles
>>>              Map<String, String> map = new HashMap<String, String>();
>>>              map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>>              activeDirectoryRealm.setGroupRolesMap(map);
>>>
>>>              securityManager.setRealm(activeDirectoryRealm);
>>>      }
>>>
>>>      private void testLogin() {
>>>              UsernamePasswordToken userToken = new
>>> UsernamePasswordToken("user1@wheel",
>>> "user1");
>>>
>>>              Subject subject = securityManager.login(userToken);
>>>              if (subject.hasRole("login")) {
>>>                      System.out.println("User in role");
>>>              } else {
>>>                      System.out.println("User has no role");
>>>              }
>>>      }
>>>
>>>      public static void main(String[] args) {
>>>              TestJSec tjs = new TestJSec();
>>>              tjs.testLogin();
>>>      }
>>> }
>>>
>>>
>>> For example in jBoss this config works without a super user:
>>>
>>>
>>> <application-policy name="DLG_REGW_POLICY">
>>>      <authentication>
>>>              <login-module
>>> code="org.jboss.security.auth.spi.LdapLoginModule"
>>> flag="required" >
>>>                      <module-option
>>> name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
>>>                      <module-option
>>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>>                      <module-option
>>> name="matchOnUserDN">false</module-option>
>>>                      <module-option
>>> name="uidAttributeID">sAMAccountName</module-option>
>>>                      <module-option
>>> name="roleAttributeID">memberOf</module-option>
>>>                      <module-option
>>> name="roleAttributeIsDN">true</module-option>
>>>                      <module-option
>>> name="roleNameAttributeID">name</module-option>
>>>                      <module-option
>>> name="searchTimeLimit">5000</module-option>
>>>                      <module-option
>>> name="allowEmptyPasswords">false</module-option>
>>>                      <module-option
>>> name="searchScope">SUBTREE_SCOPE</module-option>
>>>              </login-module>
>>>      </authentication>
>>> </application-policy>
>>>
>>> --
>>> View this message in context:
>>>
>>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>>
>>>
>>>
>>
>>
>> --
>> View this message in context:
>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>
>>
>

Re: Reading user roles from Active Directory

Posted by Jeremy Haile <jh...@fastmail.fm>.
Maciej,

The problem is that if the LDAP server requires credentials to login  
(as they typically do), there is no way to obtain authorization  
information at a later point without having a username/password to  
login to the LDAP server.  Due to the way JSecurity works,  
authentication and authorization happen independently of each other,  
and so when authorization occurs we do not have the username/password  
that was originally used to authenticate (as we shouldn't).

I think this brings to light an option that JSecurity should offer -  
which is to allow authorization information to be obtained at login  
and cached for the duration of a user's session.  This is the way many  
security frameworks operate, and usually we tout the fact that  
JSecurity doesn't work this way as an advantage (i.e. dynamic security  
updates, flexible caching, etc.)

However - in this case it's a disadvantage because login is the only  
time when we have the information we need to obtain the authorization  
information (since the authentication info is needed to obtain it).  I  
think there will be other scenarios where this is the case (external  
authorization systems, SSO systems, etc.) so I do think JSecurity  
should offer this mechanism as an option.  I'll open a JIRA issue to  
address this for the 1.0 release.

As far as a short-term workaround, you could either:
1) configure the system username and password for now (as I think  
you've already done)
or
2) extend the Active Directory realm, and override  
queryForAuthenticationInfo to grab the AuthorizationInfo (similar to  
how queryForAuthorizationInfo does) at login.  You could then cache  
the AuthorizationInfo in the subject's session and override  
queryForAuthorizationInfo to return the session-cached authorization  
information.  This is similar to how JSecurity would probably do this  
in the future, but obviously you'd have to manually implement it.

Please let me know if you have any further questions or ideas!

Jeremy

On Mar 25, 2009, at 12:24 PM, Maciej Pigulski wrote:

>
> Unfortunately this is still an issue to me.
>
>
> Jeremy or Tim, do you know if you'd be able to help out Maciej?  I  
> don't
> have any experience with the LDAP/AD stuff you guys wrote.  Maciej,   
> have
> you been able to work through this issue?
>
> On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
> <ma...@gmail.com>wrote:
>
>>
>> Hello,
>>
>> I have a following problem with jSecurity, ActiveDirectoryRealm and  
>> Groups
>> mappings.
>>
>> I have an AD setup on one server (WHEEL) with a simple user called  
>> user1.
>> This user is in ldap group called  
>> "login" (CN=login,OU=Groups,DC=WHEEL).
>>
>> Next I'm trying to login and retrieve roles for this user. Login  
>> works fine
>> but when it comes to user roles I  have to additionally provide  
>> username
>> and
>> password in activeDirectoryRealm.setSystemUsername/Password. I've  
>> found in
>> the API that it is a pretty normal behaviour (but IMHO very  
>> inconvenient)
>> (
>> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String) 
>> <http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29 
>> >
>> :
>> <cite>
>> systemUsername - the username to use when logging into the LDAP  
>> server for
>> authorization.
>> </cite>
>>
>> Is there any tricky way to bypass this? Setting same credentials on  
>> two
>> objects to authorize and authenticate one user seems to be quite  
>> wrong.
>>
>> I've managed to obtain this by creating a super user (with enterprise
>> administrator rights) that has hardcoded username and password in
>> application (systemUsername and systemPassword) and this works for
>> authenticating other users but I'd like to avoid using such  
>> powerfull user
>> just for groups fetching as it seems to be an huge overkill for me.
>>
>> Here is a class I'm using to test with AD:
>>
>> import java.util.HashMap;
>> import java.util.Map;
>>
>> import org.jsecurity.authc.UsernamePasswordToken;
>> import org.jsecurity.mgt.DefaultSecurityManager;
>> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
>> import org.jsecurity.subject.Subject;
>>
>> public class TestJSec {
>>
>>       private DefaultSecurityManager securityManager = new
>> DefaultSecurityManager();
>>       private ActiveDirectoryRealm activeDirectoryRealm = new
>> ActiveDirectoryRealm();
>>
>>       public TestJSec() {
>>               activeDirectoryRealm.setSearchBase("DC=WHEEL");
>>               activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>>                
>> activeDirectoryRealm.setSystemUsername("user1@wheel"); //
>> if this is
>> missing user wont fetch his roles
>>               activeDirectoryRealm.setSystemPassword("user1");
>> // if this
>> is missing user wont fetch his roles
>>               Map<String, String> map = new HashMap<String,  
>> String>();
>>               map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>>               activeDirectoryRealm.setGroupRolesMap(map);
>>
>>               securityManager.setRealm(activeDirectoryRealm);
>>       }
>>
>>       private void testLogin() {
>>               UsernamePasswordToken userToken = new
>> UsernamePasswordToken("user1@wheel",
>> "user1");
>>
>>               Subject subject = securityManager.login(userToken);
>>               if (subject.hasRole("login")) {
>>                       System.out.println("User in role");
>>               } else {
>>                       System.out.println("User has no role");
>>               }
>>       }
>>
>>       public static void main(String[] args) {
>>               TestJSec tjs = new TestJSec();
>>               tjs.testLogin();
>>       }
>> }
>>
>>
>> For example in jBoss this config works without a super user:
>>
>>
>> <application-policy name="DLG_REGW_POLICY">
>>       <authentication>
>>               <login-module
>> code="org.jboss.security.auth.spi.LdapLoginModule"
>> flag="required" >
>>                       <module-option
>> name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
>>                       <module-option
>> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>>                       <module-option
>> name="matchOnUserDN">false</module-option>
>>                       <module-option
>> name="uidAttributeID">sAMAccountName</module-option>
>>                       <module-option
>> name="roleAttributeID">memberOf</module-option>
>>                       <module-option
>> name="roleAttributeIsDN">true</module-option>
>>                       <module-option
>> name="roleNameAttributeID">name</module-option>
>>                       <module-option
>> name="searchTimeLimit">5000</module-option>
>>                       <module-option
>> name="allowEmptyPasswords">false</module-option>
>>                       <module-option
>> name="searchScope">SUBTREE_SCOPE</module-option>
>>               </login-module>
>>       </authentication>
>> </application-policy>
>>
>> --
>> View this message in context:
>> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
>> Sent from the JSecurity User mailing list archive at Nabble.com.
>>
>>
>
>
>
> -- 
> View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>


Re: Reading user roles from Active Directory

Posted by Maciej Pigulski <ma...@gmail.com>.
Unfortunately this is still an issue to me.


Jeremy or Tim, do you know if you'd be able to help out Maciej?  I don't
have any experience with the LDAP/AD stuff you guys wrote.  Maciej,  have
you been able to work through this issue?

On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
<ma...@gmail.com>wrote:

>
> Hello,
>
> I have a following problem with jSecurity, ActiveDirectoryRealm and Groups
> mappings.
>
> I have an AD setup on one server (WHEEL) with a simple user called user1.
> This user is in ldap group called "login" (CN=login,OU=Groups,DC=WHEEL).
>
> Next I'm trying to login and retrieve roles for this user. Login works fine
> but when it comes to user roles I  have to additionally provide username
> and
> password in activeDirectoryRealm.setSystemUsername/Password. I've found in
> the API that it is a pretty normal behaviour (but IMHO very inconvenient)
> (
> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)<http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29>
> :
> <cite>
> systemUsername - the username to use when logging into the LDAP server for
> authorization.
> </cite>
>
> Is there any tricky way to bypass this? Setting same credentials on two
> objects to authorize and authenticate one user seems to be quite wrong.
>
> I've managed to obtain this by creating a super user (with enterprise
> administrator rights) that has hardcoded username and password in
> application (systemUsername and systemPassword) and this works for
> authenticating other users but I'd like to avoid using such powerfull user
> just for groups fetching as it seems to be an huge overkill for me.
>
> Here is a class I'm using to test with AD:
>
> import java.util.HashMap;
> import java.util.Map;
>
> import org.jsecurity.authc.UsernamePasswordToken;
> import org.jsecurity.mgt.DefaultSecurityManager;
> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
> import org.jsecurity.subject.Subject;
>
> public class TestJSec {
>
>        private DefaultSecurityManager securityManager = new
> DefaultSecurityManager();
>        private ActiveDirectoryRealm activeDirectoryRealm = new
> ActiveDirectoryRealm();
>
>        public TestJSec() {
>                activeDirectoryRealm.setSearchBase("DC=WHEEL");
>                activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>                activeDirectoryRealm.setSystemUsername("user1@wheel"); //
> if this is
> missing user wont fetch his roles
>                activeDirectoryRealm.setSystemPassword("user1");
>  // if this
> is missing user wont fetch his roles
>                Map<String, String> map = new HashMap<String, String>();
>                map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>                activeDirectoryRealm.setGroupRolesMap(map);
>
>                securityManager.setRealm(activeDirectoryRealm);
>        }
>
>        private void testLogin() {
>                UsernamePasswordToken userToken = new
> UsernamePasswordToken("user1@wheel",
> "user1");
>
>                Subject subject = securityManager.login(userToken);
>                if (subject.hasRole("login")) {
>                        System.out.println("User in role");
>                } else {
>                        System.out.println("User has no role");
>                }
>        }
>
>        public static void main(String[] args) {
>                TestJSec tjs = new TestJSec();
>                tjs.testLogin();
>        }
> }
>
>
> For example in jBoss this config works without a super user:
>
>
> <application-policy name="DLG_REGW_POLICY">
>        <authentication>
>                <login-module
> code="org.jboss.security.auth.spi.LdapLoginModule"
> flag="required" >
>                        <module-option
> name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
>                        <module-option
> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>                        <module-option
> name="matchOnUserDN">false</module-option>
>                        <module-option
> name="uidAttributeID">sAMAccountName</module-option>
>                        <module-option
> name="roleAttributeID">memberOf</module-option>
>                        <module-option
> name="roleAttributeIsDN">true</module-option>
>                        <module-option
> name="roleNameAttributeID">name</module-option>
>                        <module-option
> name="searchTimeLimit">5000</module-option>
>                        <module-option
> name="allowEmptyPasswords">false</module-option>
>                        <module-option
> name="searchScope">SUBTREE_SCOPE</module-option>
>                </login-module>
>        </authentication>
> </application-policy>
>
> --
> View this message in context:
> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>
>



-- 
View this message in context: http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2533411.html
Sent from the JSecurity User mailing list archive at Nabble.com.


Re: Reading user roles from Active Directory

Posted by Les Hazlewood <lh...@apache.org>.
Jeremy or Tim, do you know if you'd be able to help out Maciej?  I don't
have any experience with the LDAP/AD stuff you guys wrote.  Maciej,  have
you been able to work through this issue?

On Thu, Mar 19, 2009 at 9:46 AM, Maciej Pigulski
<ma...@gmail.com>wrote:

>
> Hello,
>
> I have a following problem with jSecurity, ActiveDirectoryRealm and Groups
> mappings.
>
> I have an AD setup on one server (WHEEL) with a simple user called user1.
> This user is in ldap group called "login" (CN=login,OU=Groups,DC=WHEEL).
>
> Next I'm trying to login and retrieve roles for this user. Login works fine
> but when it comes to user roles I  have to additionally provide username
> and
> password in activeDirectoryRealm.setSystemUsername/Password. I've found in
> the API that it is a pretty normal behaviour (but IMHO very inconvenient)
> (
> http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername(java.lang.String)<http://www.jsecurity.org/releases/0.9.0-beta2/docs/api/org/jsecurity/realm/ldap/DefaultLdapContextFactory.html#setSystemUsername%28java.lang.String%29>
> :
> <cite>
> systemUsername - the username to use when logging into the LDAP server for
> authorization.
> </cite>
>
> Is there any tricky way to bypass this? Setting same credentials on two
> objects to authorize and authenticate one user seems to be quite wrong.
>
> I've managed to obtain this by creating a super user (with enterprise
> administrator rights) that has hardcoded username and password in
> application (systemUsername and systemPassword) and this works for
> authenticating other users but I'd like to avoid using such powerfull user
> just for groups fetching as it seems to be an huge overkill for me.
>
> Here is a class I'm using to test with AD:
>
> import java.util.HashMap;
> import java.util.Map;
>
> import org.jsecurity.authc.UsernamePasswordToken;
> import org.jsecurity.mgt.DefaultSecurityManager;
> import org.jsecurity.realm.activedirectory.ActiveDirectoryRealm;
> import org.jsecurity.subject.Subject;
>
> public class TestJSec {
>
>        private DefaultSecurityManager securityManager = new
> DefaultSecurityManager();
>        private ActiveDirectoryRealm activeDirectoryRealm = new
> ActiveDirectoryRealm();
>
>        public TestJSec() {
>                activeDirectoryRealm.setSearchBase("DC=WHEEL");
>                activeDirectoryRealm.setUrl("ldap://ldap-host:389");
>                activeDirectoryRealm.setSystemUsername("user1@wheel"); //
> if this is
> missing user wont fetch his roles
>                activeDirectoryRealm.setSystemPassword("user1");
>  // if this
> is missing user wont fetch his roles
>                Map<String, String> map = new HashMap<String, String>();
>                map.put("CN=login,OU=Groups,DC=WHEEL", "login");
>                activeDirectoryRealm.setGroupRolesMap(map);
>
>                securityManager.setRealm(activeDirectoryRealm);
>        }
>
>        private void testLogin() {
>                UsernamePasswordToken userToken = new
> UsernamePasswordToken("user1@wheel",
> "user1");
>
>                Subject subject = securityManager.login(userToken);
>                if (subject.hasRole("login")) {
>                        System.out.println("User in role");
>                } else {
>                        System.out.println("User has no role");
>                }
>        }
>
>        public static void main(String[] args) {
>                TestJSec tjs = new TestJSec();
>                tjs.testLogin();
>        }
> }
>
>
> For example in jBoss this config works without a super user:
>
>
> <application-policy name="DLG_REGW_POLICY">
>        <authentication>
>                <login-module
> code="org.jboss.security.auth.spi.LdapLoginModule"
> flag="required" >
>                        <module-option
> name="java.naming.provider.url">ldap://ldap-host:389/</module-option>
>                        <module-option
> name="rolesCtxDN">OU=Groups,DC=WHEEL</module-option>
>                        <module-option
> name="matchOnUserDN">false</module-option>
>                        <module-option
> name="uidAttributeID">sAMAccountName</module-option>
>                        <module-option
> name="roleAttributeID">memberOf</module-option>
>                        <module-option
> name="roleAttributeIsDN">true</module-option>
>                        <module-option
> name="roleNameAttributeID">name</module-option>
>                        <module-option
> name="searchTimeLimit">5000</module-option>
>                        <module-option
> name="allowEmptyPasswords">false</module-option>
>                        <module-option
> name="searchScope">SUBTREE_SCOPE</module-option>
>                </login-module>
>        </authentication>
> </application-policy>
>
> --
> View this message in context:
> http://n2.nabble.com/Reading-user-roles-from-Active-Directory-tp2503002p2503002.html
> Sent from the JSecurity User mailing list archive at Nabble.com.
>
>