How can I get the user information using Spring Security with LDAP - spring

Im using Spring 3.1.1 with Spring Security 3.2.0 with LDAP authencitation.
I have gotten it to a point that works fine and I can log in using my LDAP username and password, I can even display the username with this
<security:authentication property="principal.username" />, is currently logged in.
I want to know how, if at all possible, can I get the first name, surname, email address or other information like that stored in my LDAP credentials.
I've tried property="credentials" but this returns null...
PLEASE HELP!!

This is eerily similar to my question a few days ago:
How do I use a custom authorities populator with Spring Security and the ActiveDirectoryLdapAuthenticationProvider?
If you're not using Active Directory, you can simply extend the LdapAuthenticationProvider class and override the loadUserAuthorities method, in which you can capture the relevant user information based on the LDAP attributes for the user:
String firstName = userData.getStringAttribute("givenName");
String lastName = userData.getStringAttribute("sn");
//etc.
You can store these wherever or however you like, and you're only limited to the attributes available via LDAP. Then, you'd have to specify your LdapAuthoritiesProvider in the appropriate bean (ldapAuthoritiesPopulator, if memory serves).
I believe the above will work for non-AD LDAP, but you'll obviously need to test it to be sure. I recommend the LDAP browser for Eclipse provided by Apache Studios, if you're not already using it.

Implement your own UserDetailsContextMapper and load LDAP user properties into the UserDetails object
http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#ldap-custom-user-details

Related

Spring Authorization Server - Configure User Info Endpoint - Spring Roles in Resource Server

I have an existing resource server that is configured to use Spring user rules as security methods. I am trying to migrate onto the Spring Authorization server and trying to figure out how these roles can be accessed in the resource server.
When the user is authentication, I can see in debug logs that my roles are part of the authorized user details. But in the resource server, I am getting default roles from OidcService and scopes as granted authorities.
I know Spring Authorization server 0.21 has implemented the User Info endpoint, but there seems to be no sample or documentation available on how to configure that, and I am sure implementing it will solve my issue.
Another option that I am thinking about is to configure oauth2TokenCustomizer in the server and then add roles in JWT's claims. Then in the resource server think about overriding default OidcService and parse claims to add roles as granted authorities. But issue is with OidcUserService i don't see any code which can give me access to JWT claims.
public class CustomOAuth2Token implementsOAuth2TokenCustomizer<JwtEncodingContext> {
#Override
public void customize(JwtEncodingContext context) {
// Load user details and add roles to claims
}
}
Probably will have to provide a custom extension for OidcAuthorizationCodeAuthenticationProvider and then modify authenticated principal details.
I was facing the same issue.
Customizing the response of the "well-known" openid-configuration endpoint is somewhat tricky because the filter handling this endpoint has hardcoded mappings for which field go and do not go in the response.
I worked around this by:
copying this class into my codebase and giving it another name, in my case CustomOidcProviderConfigurationEndpointFilter
using my custom class as an objectPostProcessor for OidcProviderConfigurationEndpointFilter replacing it entirely instead of just customizing it.
This means your custom filter will supply the OidcProviderConfiguration object from now on.
You could then call the claim method on this object to add properties such as "userinfo_endpoint".
Note: I was unable to properly format the code snippet in the second link inside this post. If someone with administrative rights could edit this in, this would be nice.

Cas and Spring example: I don't understand "setUserDetailsService"

In this example: https://www.baeldung.com/spring-security-cas-sso
there is this piece of code:
#Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider provider = new CasAuthenticationProvider();
provider.setServiceProperties(serviceProperties());
provider.setTicketValidator(ticketValidator());
provider.setUserDetailsService(
s -> new User("casuser", "Mellon", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
provider.setKey("CAS_PROVIDER_LOCALHOST_9000");
return provider;
}
I don't understand this part:
provider.setUserDetailsService(
s -> new User("casuser", "Mellon", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
what are we supposed to put here ? Am I supposed to create my own UserDetailsService (if yes, how ?) ? I was expected some 'default cas user detail service'...
how does this code work? creating a user to provide a UserDetailsService ?
This is how Spring security works on high level.
User tries to authenticate via some type of UI (part of CAS for example). The UI will pass username/password to Spring. Spring will eventually call UserDetailService.loadUserByUsername and pass the username to it, and if user exists the UserDetailService will return non null UserDetails. In case of null UserDetails or non null one with different password Spring will fail authentication.
CAS is just an authentication server, it leaves open how user is stored. You can choose to use LDAP or database. That choice is based on different implementation of UserDetailService. Look at javadoc again. It has list of default implementations you can use.
See part 5 of your linked tutorial. It shows how you can change both CAS and Spring Boot app to use database as user storage. The key here is that in order for back end to work with CAS server against users stored in database both need to be configured appropriately in order to look up user against database. CAS is configured via application.properties and Spring boot via UserDetailService.
Now to your questions in the comment:
why should the client bother about how cas server store the users ?
Client should not bother with UserDetailService. It is only used by back end service that is secured by CAS.
Just to be sure that I get it tight: if I just need to know 'is that
user connected?' then CAS is enough and I will never use
UserDetailService. But if I need some information about the user
(name, telephone etc..) then I call the UserDetailService to load it
(from db, ldap or whatever).
Yes and no. You dont need to store password in UserDetails but you need to be able to return UserDetails for successful CAS authenticated user. See this part from your linked tutorial:
Note again that the principal in the database that the server uses
must be the same as that of the client applications.

Using/configuring Spring Security with Spring 4 and Hibernate

I want to implement the login/logout (authentication/authorization) system of my Spring 4 MVC application with Spring Security.
Currently I use a very simple hand-made implementation which basically does nothing more than comparing the entered username and MD5 hashed password with the database values by looking up the user by the username using a custom service method and comparing the encrypted passwords.
If the passwords match, the username of the logged in member is saved in the session and a ControllerAdvice looks up the Member object for the user using the username in the session prior to each request. The checkLogin method returns true is username and password match:
#Service("loginService")
#Transactional
public class LoginServiceImpl implements LoginService {
private MemberDao dao;
//more methods
#Override
public boolean checkLogin(String username, String password) {
String hashedPassword = getPasswordHash(password);
return dao.checkLogin(username, hashedPassword);
}
}
This does work but is not a very elegant solution, does not handle different roles and is probably not very secure. Besides I want to become familiar with Spring Security.
Reading the official tutorial for Spring Security (http://docs.spring.io/spring-security/site/docs/4.0.4.RELEASE/reference/htmlsingle/#tech-userdetailsservice) the way to go to authenticate against the Login service method does not become clear to me.
The tutorial discusses authentication direct against the database but I cannot find anything about using a Service method to perform the authentication and in my layered architecture, the database is hidden behind the Servoce and Dao (Hibernate) layers.
Also most examples in the tutorial use XML based instead of Java based configuration which I use for my application.
After having search a lot with search engines, I still have not found a tutorial which implements Spring Security in a Spring MVC application using a familiar layered structure using a Service and Dao layer.
Do I need to bypass Service and DAO/Hibernate layers and authenticate directory against the database? Or write a custom authentication-provider implementing UserDetailsService as described in this post?
Spring Security 3 database authentication with Hibernate
And is configuring Spring Security possible with Java based configuration only? I am a bit lost with this issue so I hope for some hints...

Java Configuration equivalent of <jdbc-user-service> in Spring Security

When we use xml based configuration for Spring Security we are able to use <jdbc-user-service> tag with attributes authorities-by-username-query and users-by-username-query to get username, password and role from database for a specific username input.
Reference:
http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#nsa-jdbc-user-service
The code given in Spring Security documentation for Java Configuration seem to be using hard-coded username & password.
Reference:
http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#jc-authentication-jdbc
The related sample project (spring-security / samples / jdbc-jc) also appears to use the same hard-coded username & password values.
So with Java Configuration, how can we validate the user input with user credentials stored in a database?
Looks like you're looking for JdbcDaoImpl class with his setters setAuthoritiesByUsernameQuery() and setUsersByUsernameQuery().

Spring Security user account registration, creation and management

I've been looking into using Spring Security for the authentication/authorization of my web application (this will be JDBC based).
However, a core component seems to be left out from my perspective. How do I register/create new users? Is there an out of the box API for that?
Do i need to write user registration and management from scratch?
Things i need to do include:
- Registering a new user
- Resetting passwords
- Emailing a user to activate their account
- Emailing a user to reset their account.
Thank you in advance.
I use Spring Security on my project. The framework does not have an API for user creation or registration as you asked. For Spring Security to be generic and usable across multiple frameworks, it can only take you so far before you have to write custom code. You can't really get a more specific answer about a framework or tool to use because at this point you will just use the frameworks you are already using anyway.
If you've set it up to use users and roles in your database, from your data access layer you would create a record in the user table or update a password (preferably stored as a hash) in that record. And as Aravind said, Spring does provide email support.
If you really want to see one way to do it: I'm using Spring MVC, JSP, and Hibernate. I use Spring's form tags in a JSP to bind a new user form to a Person object, and my controller method passes that Person object to my Dao to persist it.
The controller method signature looks like this...
#RequestMapping(value = "/newUser", method = RequestMethod.POST)
public ModelAndView createNewUser(final #Valid #ModelAttribute Person user,
final BindingResult result,
final SessionStatus status,
final #RequestParam(value = "unencodedPassword", required = true) String password) {
...
user.getRoles().add(new Role(user, Role.APPLICATION_ROLE.ROLE_USER));
userDao.createNewUser(user);
...
}
and my PersonDao would use Hibernate to persist the user like so
#Transactional
public void createNewUser(Person user)
{
Session session = sessionFactory.getCurrentSession();
session.save(user);
session.flush();
}
Have a look at my answer here.
"I have implemented a JAVA project for this use case. It is open
source, based on Spring-Security. A release version is on
Maven-Central, so you do not need to compile it, but instead you can
fetch it as maven-dependency to your project!"
<dependency>
<groupId>com.ohadr</groupId>
<artifactId>authentication-flows</artifactId>
<version>1.5.0-RELEASE</version>
</dependency>
As far as I know, Spring Security does not have built in support for new user creation and registration. You will have to manage this yourself. However it does have emailing support. Check here for more on this.

Resources