Add users dynamically in Spring Java - spring

This code I use to add users from my database that can authenticate but the problem this code is executed once , I want to have users that register how can I achieve that ?
I have this solution How to adding new user to Spring Security in runtime but I coudn't add it to my actual code please help.
this is my code
#Configuration
#EnableWebSecurity
protected static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
#Autowired
UserRepository userRepository;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
for (UsersEntity user : userRepository.findAll())
if (user.getUsername() != null && user.getPassword() != null)
auth.
inMemoryAuthentication()
.passwordEncoder(UsersEntity.ENCODE_PASS)
.withUser(user.getUsername()).password(user.getPassword())
.roles("USER");
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}

You can simply set another authenticationProvider.
#Autowired
private MyAuthenticationProvider authenticationProvider;
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
Simply implement your own MyAuthenticationProvider that asks your UserRepository for each login attempt. Or another way would be to simply use basic jdbc:
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select username,password, enabled from users where username=?")
.authoritiesByUsernameQuery(
"select username, role from user_roles where username=?");
}
...of course, you would need to set your own queries there.

Related

Vaadin 21 Migration to View-Based Access Control - RolesAllowed not working

This is a follow up question to this question.
I migrated my Vaadin 20 application to 21 to use view-based access control. The Annotations #PermitAll and #AnonymousAllowed are working fine. However when I try to restrict a route to a specific user role with #RolesAllowed I can't get access to this site (being logged in with a user who has this role).
Is there some special code required to get Vaadin to recognize the roles of my authenticated user?
Role restricted page:
#Component
#Route(value = "admin", layout = MainLayout.class, absolute = true)
#RolesAllowed("admin")
#UIScope
public class AdminView ...
SecurityConfig
#EnableWebSecurity
#Configuration
public class SecurityConfiguration extends VaadinWebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
setLoginView(http, LoginView.class, "/login");
}
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/images/**");
}
}
The roles you pass into #RolesAllowed are case-sensitive and should match the roles you have in Spring Security. Most likely in your case, you want to use #RolesAllowed({"ROLE_ADMIN"}). You can read more in the docs here https://vaadin.com/docs/v21/flow/integrations/spring/view-based-access-control/#annotating-the-view-classes
After a lot of debugging, I found the problem, the implementation of the getAuthorities() Function in my implementation of UserDetails.java was incorrect. A working dummy version with one role looks something like this:
#Override
#JsonIgnore
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of( new SimpleGrantedAuthority("ROLE_" + "admin"));
}
Important was to add "ROLE_" in front of the actual role name. Then I can use #RolesAllowed("admin") in the view class.

Spring security cannot access userService while login NullPointerException

When making post request to login this error shows up telling me that userService is null.
When I create an object of UserService instead of autowiring it it passes it but tell me that the repository called in userService is null. The repository is autowired and i cannot instanciate it because its an interface.
Here is the service class:
#Service
public class MyUserDetailsService implements UserDetailsService {
#Autowired
UserService userService;
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return new MyUserDetails(userService.getByUsernameOrEmail(s));
}
}
And this is the security configuration class:
Also I am creating an object of MyUserService because spring cannot autowire it telling me that no bean have such name.
#Configuration
#EnableWebSecurity
public class UserSercurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(new MyUserDetailsService());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.anyRequest().hasRole(UserType.ADMIN.toString())
.and().formLogin();
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
You cannot instantiate method or variables in your repository as it is an interface but you can autowire your repository class to use your method declared in userRepository interface, you have to autowire your repository class.You can do it this way as I have done in the below code.
Your service class should be like this:
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users user = userRepository.getUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("Could not find user");
}
return new MyUserDetails(user);
}
And your repository should be like this:
#Repository
public interface UserRepository extends JpaRepository<Users, Long> {
#Query("SELECT u FROM Users u WHERE u.name = ?1")
public Users getUserByUsername(String username);
}
And also autowire UserDetailsService in your configuration class and pass the instance userDetailsService in your configure(AuthenticationManagerBuilder auth) method, UserDetailsService provides you instance of your MyUserDetailService class.
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Bean
public PasswordEncoder getPasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.and()
.formLogin().permitAll()
.defaultSuccessUrl("/", true)
.and()
.logout().permitAll()
.logoutSuccessUrl("/");
}
Try to implement in this way, If this is solution of your question please let me know and if you still have doubt feel free to ask.

Spring Security Permitting even unauthenticated user? whats wrong with this code?

I doing a simple poc of spring security but am running in to issues.
After extending WebSecurityConfigurerAdapter and implementing own UserDetailsService, spring security is permitting all users even without authentication. Please point the flaw in below code
...
#EnableWebSecurity
public class MyWebSecurity extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService myUserDtlSrv;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDtlSrv);
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}
my implementation of UserDetailsService
...
#Service
public class MyUserDtlSrv implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new User("a", "a", Arrays.asList());
}
}
Does not spring security secure every url (resource by default)?
You need to specify what requests are authorized. The following fragment
authorizes authenticated (by form login) requests.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.csrf(t -> t.disable())
.authorizeRequests(t -> t.anyRequest().authenticated())
.formLogin(Customizer.withDefaults());
}
}

Why SecurityContextHolder.getContext() == null?

I don't run my app, because auth == null. Why? I use spring boot 2.2.7.RELEASE and spring-security-oauth2-autoconfigure.
When starting SecurityContextHolder.getContext() always equal null
#Component
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
#Autowired
UserRepository userRepository;
#Autowired
PasswordEncoder passwordEncoder;
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/addPet").authenticated()
.antMatchers("/", "/**").access("permitAll")
.and().oauth2Login().loginPage("/login").defaultSuccessUrl("/", true).and().logout().logoutSuccessUrl("/")
.and().formLogin().loginPage("/login").loginProcessingUrl("/login").usernameParameter("login").passwordParameter("password")
.defaultSuccessUrl("/", true).and().logout().logoutSuccessUrl("/").deleteCookies("JSESSIONID").and().csrf().disable();
}
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select login, password, enabled from users where login=?")
.authoritiesByUsernameQuery(
"select login, role from users where login=?");
}
}
I assume that you're referring to this line,
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
In this case, you don't need this line, it's not being used anywhere. In the bigger answer, SecurityContextHolder.getContext() will never be null, according to the documentation. The call to getAuthentication(), however, will be null unless there's an authenticated principal associated to the session.

Custom Authentication provider with Spring Security and Java Config

How can I define a custom Authentication provider by using Spring Security with Java Configurations?
I would like to perform a login checking credentials on my own database.
The following does what you need (CustomAuthenticationProvider is your implementation which needs to be managed by Spring)
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
#Override
protected void configure(HttpSecurity http) throws Exception {
/**
* Do your stuff here
*/
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
}
As shown on baeldung.com, define your authentication provider as follow:
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
if (shouldAuthenticateAgainstThirdPartySystem(username, password)) {
// use the credentials
// and authenticate against the third-party system
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
} else {
return null;
}
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
UsernamePasswordAuthenticationToken.class);
}
}
and following code is corresponding java config:
#Configuration
#EnableWebSecurity
#ComponentScan("org.project.security")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider authProvider;
#Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
}

Resources