Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting an email address for a user logged in through Active Directory with Spring Securitu

I'm working on a Spring MVC based web application that uses Spring Security to allow users to log in with their Active Directory credentials. I'd like to get the user's email address once they've logged in. I've got the logging in working and now I'm trying to figure out how to get the user's email. It looks like I should be getting that from an InetOrgPerson object. I've tried specifying an InetOrgPersonContextMapper in the xml configuration as such:

<bean id="ldapActiveDirectoryAuthProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <constructor-arg name="domain" value="foo.bar" />
    <constructor-arg name="url" value="ldap://foo.bar" />
    <property name="useAuthenticationRequestCredentials" value="true" />
    <property name="convertSubErrorCodesToExceptions" value="true" />
    <property name="userDetailsContextMapper">
        <bean class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" />
    </property>
</bean>

I'm trying to get the email in a Controller like so:

@RequestMapping(value = "/startProcess.html", method = RequestMethod.POST)
public ModelAndView startProcess(@ModelAttribute Token token, Principal principal)
{
    ModelAndView mav = new ModelAndView();

    String user = principal.getName();
    String email = ((InetOrgPerson)principal).getMail();

    logger.info("Got email \"" + email + "\" for user \"" + user + "\"");

    ...
}

This was giving me a class cast exception saying it can't cast a UsernamePasswordAuthenticationToken to a InetOrgPerson. I decided to try getting the Principal object manually instead of having Spring inject it:

@RequestMapping(value = "/startProcess.html", method = RequestMethod.POST)
public ModelAndView startProcess(@ModelAttribute Token token, Principal principal)
{
    ModelAndView mav = new ModelAndView();

    String user = principal.getName();

    Object p = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    String email = ((InetOrgPerson)p).getMail();

    logger.info("Got email \"" + email + "\" for user \"" + user + "\"");

    ...
}

This is telling me that it can't cast an LdapUserDetailsImpl to an InetOrgPerson. Shouldn't the LdapUserDetailsImpl be an InetOrgPerson since I'm using an InetOrgPersonContextMapper?

like image 569
JDiPierro Avatar asked Oct 02 '22 07:10

JDiPierro


1 Answers

First you need to change the mapper to org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper

<beans:bean id="inetOrgPersonContextMapper" class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper">
</beans:bean>

then use it in your authentication provider

<beans:bean id="adAuthenticationProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <beans:constructor-arg value="mydomain.com.local" />
    <beans:constructor-arg value="ldap://servername/" />
    <beans:property name="userDetailsContextMapper" ref="inetOrgPersonContextMapper" />
</beans:bean>   

and then you will be able to cast your principal to InetOrgPerson

InetOrgPerson userDetails = (InetOrgPerson)(SecurityContextHolder.getContext().getAuthentication().getPrincipal());
like image 163
kadir malak Avatar answered Oct 13 '22 10:10

kadir malak