Spring Security Authentication using DynamoDB - spring-security

Does anyone know how to provide spring security authentication using DynamoDB? In other words, how would you convert/represent the following configAuthentication method using DynamoDB?
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth)
throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username, password, enabled from appuser where username = ?")
.authoritiesByUsernameQuery("select username, rolename from appuser natural join user_role natural join role where username = ?;");
}

You can use anything as a Spring Security authentication backend. You would need to write custom query logic in a class that implements the UserDetailsService interface and return a domain object that implements the UserDetails interface, but you can use that class.
Your configuration would like something like
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myCustomDynamoDbDetailService);
}
Where myCustomDynamoDBDetailService is your class that implements UserDetailService and does the lookup by username from DynamoDB.

Related

How to perform authorization with external authenticate

Im applying Spring Security for my Spring Boot application, for the part authentication, i have 3rd party to do it, basically, when user access website, the gateway will navigate user to a central login platform to do authenticate. If user login successfully, a special key will be append for every later HttpServletRequest.
From my Controller, i just need to extract authenticated user from request.
So now i have question, if i want to use Authorization feature from Spring Security, how do i inject the user info (username, email) and role from request to spring authorization process?
Because i want to validate user access to some specific url, like /admin/** only can access by role admin
i see we can create user detail like this:
public class SecurityUser implements UserDetails{
String ROLE_PREFIX = "ROLE_";
String userName;
String password;
String role;
public SecurityUser(String username, String password, String role){
this.userName = username;
this.password = password;
this.role = role;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
list.add(new SimpleGrantedAuthority(ROLE_PREFIX + role));
return list;
}
and user detail service
public class DefaultUserDetailService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//How to create user detail with information from httprequest?
return null;
}
}
But i only have username and role from httpRequest from 3rd party. How do i collect it?
Thanks
spring-security user UsernamePasswordAuthenticationFilter that extend AbstractAuthenticationProcessingFilter do authentication
maybe you need a new AbstractAuthenticationProcessingFilter to replace UsernamePasswordAuthenticationFilter.

How to authenticate user from database using Spring rest api and oauth security

I want to implement Rest api security using oauth2 and I have implemented this security using static user data by following this. Now I would like to change this case to authenticate data from database using jdbc but till now I'm not able to find any tutorial on jdbc authentication. Please do suggest me some examples of my requirements, My requirement is Spring mvc Rest api+OAuth2+jdbc database+java-config example.
currently I have tested with static users like below.
public void globalUserDetails(AuthenticationManagerBuilder auth) throws
Exception {
auth.inMemoryAuthentication()
.withUser("crmadmin").password("crmpass").roles("ADMIN","USER").and()
.withUser("crmuser").password("pass123").roles("USER");
}
I think you can configure it as below:
Put the code below in the class that extends WebSecurityConfigurerAdapter
#Autowired
private DataSource securityDataSource; // from Bean where you have connection, jdbc driver set up for database containing login information
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(securityDataSource);
}

rest with Spring boot + spring security with custom users table

I want to configure Spring boot and spring security for some rest services.
I have tables User, priviledge, priviledge_user
I have this Configuration files
WebSecurityConfig
#EnableWebSecurity
#Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated().and().
httpBasic().and().
csrf().disable();
}
}
and AuthenticationConfiguration
#Configuration
public class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
#Autowired
UserRepository userRepository;
Logger log = LoggerFactory.getLogger(this.getClass());
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
}
#Bean
UserDetailsService userDetailsService() {
return new UserDetailsService() {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User account = userRepository.findByUsername(username);
log.info("The user ({}) logged has the password {}", username, account.getPassword());
org.springframework.security.core.userdetails.User userSession = new org.springframework.security.core.userdetails.User(account.getUsername(), account.getPassword(), true, true, true, true,
AuthorityUtils.createAuthorityList("USER"));
return userSession;
}
};
}
}
debuging the code seems Authentication is working well cause I have the user from database(I am using JNDI datasoure and have this configured in application.properties)
but When I try to get anything on http://localhost:8080/ and set my credentials I cant access and always get the prompt for credentials
Whats I am doing bad?
You are not instantiating the UserDetails object with the correct authorities.
Instead of always passing "USER" to AuthorityUtils.createAuthorityList method, you should pass a List with all the roles/privileges in the privilege_user table for the user you are loading. This roles by default are in the form of "ROLE_USER", "ROLE_ADMIN"...
So loading the User from the database successfully doesn't mean the authentication process is working well. You still have to tell him how to load the authorities for that User.
The problem is, you are using the DB audit with either of #CreatedBy or #LastModifiedBy annotation and yet you are trying to insert a document before any user is logged in. This use to happen, when you create a new user or create operations in a landing page controller. To overcome this, have a system user in your DB, say, system#yourdomain.com then set principal in the corresponding controller if the input params are right.
While doing so, the DBAuditor will get your system user id for the annotated filed. Make sure, you load newly created user principal after this operation.

Security Config - configureGlobal

Playing with Spring Session REST example, I'm curious is it possible to make the following flow:
1. In first time, an user passes its credentials, usename and password.
2. Spring Session will generate a token, puts it into Redis
3. Next time a user asks for some resources it passes its tiken.
My problem is that the following code is hardcoded:
code
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
code`
How can I do it to be dynamic?
Thanks in advance.
Spring Session works independent of the security framework you choose, so the answer depends on which security framework you want to use. This means selecting the username / password for your users is totally independent of Spring Session.
Since the question is unrelated to Spring Session, you should consult the documentation of the security framework you choose. In this instance, it is Spring Security so you can consult Spring Security's documentation on authentication.
The first step is to determine how you want to authenticate.
For example, if you want to use JDBC authentication, you can use something like the following.
#Autowired
private DataSource dataSource;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.withDefaultSchema()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
By default jdbcAuthentication expects that:
select username, password, enabled from users where username = ?
will return the username, the password, and if that user is enabled. You can customize this query if you like using properties on jdbcAuthentication(). See the javadoc for details.
NOTE: It is important to understand that withDefaultSchema and withUser are really only intended for in memory databases since it will try to add the schema and the user every time. In a production environment your users and schema should be added using other mechanisms (i.e. liquibase).
The most flexible option is to implement a UserDetailsService. You can then look up users in any way you want. For example:
#Service
public class UserRepositoryUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
#Autowired
public UserRepositoryUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
MyUser user = userRepository.findByEmail(username);
if(user == null) {
throw new UsernameNotFoundException("Could not find user " + username);
}
List<GrantedAuthority> authorities = convert(user.getRoles());
return new User(user.getUsername(), user.getPassword(), authorities);
}
}
Then you can configure it using:
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsService userDetailsService) throws Exception {
auth
.userDetailsService(userDetailsService);
}
You can find a complete example of using a UserDetailsService in my Spring Security 4 talk.

Lookup LDAP entries from inside LdapAuthoritiesPopulator

I'm using Spring Security and spring-security-ldap for authentication in a Spring Boot application.
I want to implement an LdapAuthoritiesPopulator that looks up some entries from the LDAP server to decide the roles of the user. These entries are not under the user, so the userData object provided to getGrantedAuthorities method is not enough. (I have no control over the LDAP server so I cannot add the roles to user entries).
I thought about injecting the ContextSource that Spring Security creates when calling auth.ldapAuthentication().contextSource() (see (1) in the code below) into the LdapAuthoritiesPopulator. But that doesn't work because the LdapAuthoritiesPopulator is created before the WebSecurityConfigurerAdapter, and so the ContextSource does not exist yet.
My WebSecurityConfigurerAdapter contains the following method:
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.contextSource() // (1)
.url("ldap://example.org/o=organization")
.and()
.ldapAuthoritiesPopulator(ldapAuthoritiesPopulator)
.userSearchFilter("uid={0}");
}
ldapAuthoritiesPopulator is autowired, the class is currently a dummy implementation that simply adds ROLE_USER:
#Component
public class CustomLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
#Override
public Collection<? extends GrantedAuthority> getGrantedAuthorities(
DirContextOperations userData, String username) {
// I want to look up some entries in LDAP here, so I need a ContextSource
// but I can't inject it because it does not exist when this bean is created
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("USER"));
return authorities;
}
}
You don't need the roles populated till after the application is running (I suppose). So one thing that would work would be to inject the ApplicationContext instead of the ContextSource and look up the latter lazily. If that works there might be a truck with #Lazy.

Resources