Reputation: 427
I am building a Spring application which uses a database as the Authorisation Service in an OAuth2 configuration.
Here is my SecurityConfig class for Spring Security
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(getPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("**/secured/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().permitAll();
}
private PasswordEncoder getPasswordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return true;
}
};
}
}
Here is my Repository for my database, which aims to locate users on their email.
@Repository
public interface UsersRepository extends JpaRepository<User, Integer> {
@Query
Optional<User> findByEmail(String email);
}
Here is my Service class:
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<User> optionalUsers = usersRepository.findByEmail(email);
optionalUsers
.orElseThrow(() -> new UsernameNotFoundException("Username not found"));
return optionalUsers
.map(CustomUserDetails::new).get();
}
}
When I type an email and password I have on the database it comes back saying
"Bad Credentials"
Can anybody spot anything wrong with my set up?
If I remove the
@PreAuthorise("hasRole('ROLE_admin')")
in the controller which would get rid of the login screen but I wish to have the login screen.
As requested by the comments, here is my database schema. I use H2 to provide an in memory database.
DROP TABLE IF EXISTS 'User'
CREATE TABLE IF NOT EXISTS User (
id INT,
role VARCHAR(5),
title VARCHAR(5),
firstname VARCHAR(20),
lastname VARCHAR(20),
email VARCHAR(50),
password VARCHAR(50),
modified DATETIME,
accessed DATETIME
)
INSERT INTO User VALUES
(
'1',
'admin',
'mr',
'bob',
'smith',
'[email protected]',
'gobob',
'1993-10-25 22:10:00',
'2018-04-09 08:30:00'
),
....
spring.h2.console.enabled=true
spring.h2.console.path=/h2
# Datasource
spring.datasource.url=jdbc:h2:file:path/to/application/src/main/resources/DATA-DUMP.sql
spring.datasource.username=<user>
spring.datasource.password=<pass>
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming- strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
I don't think my H2 is populating my Table it creates:
2018-04-17 13:52:43.523 INFO 4407 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2018-04-17 13:52:43.583 INFO 4407 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: create table hibernate_sequence (next_val bigint) engine=MyISAM
Hibernate: insert into hibernate_sequence values ( 1 )
Hibernate: create table user (id integer not null, accessed datetime, email varchar(255), firstname varchar(255), lastname varchar(255), modified datetime, password varchar(255), role varchar(255), title varchar(255), primary key (id)) engine=MyISAM
2018-04-17 13:52:43.881 INFO 4407 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
Upvotes: 0
Views: 988
Reputation: 3824
Although you're currently getting a Bad Credentials
message, you might run into another problem afterward:
@PreAuthorise("hasRole('ROLE_admin')")
Note that hasRole
is case sensitive, and it might be possible that the correct role is ROLE_ADMIN
. Also, depending on your version of Spring Security, you might need to omit ROLE_
and simply use
@PreAuthorise("hasRole('ADMIN')")
Like I mentioned in the comments, with your implementation of PasswordEncoder, the password you use to login doesn't matter as long as the username exists because your implementation's matches
method always return true.
In other words, the problem is likely to be that your repository cannot find any user with the username you're trying to test.
Your database is most likely empty.
UPDATE
The User
table is automatically created by Hibernate after reading all class annotated with @Entity
, not because you wrote it in your schema file.
Create a file named data-h2.sql
in src/main/resources
and move all insertions there, e.g.:
INSERT INTO User VALUES (
'1',
'admin',
'mr',
'bob',
'smith',
'[email protected]',
'gobob',
'1993-10-25 22:10:00',
'2018-04-09 08:30:00'
),
...
See Spring Boot - Loading Initial Data for further details
Upvotes: 1