Basic jdbc authentication, authorization not working - spring

I am novice in spring security. Just added simple basic authentication to my project using jdbcauthenticationmanager and it is not working.
SpringSecurityConfig
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource ds;
#Bean
public BCryptPasswordEncoder getEncoder() {
return new BCryptPasswordEncoder(12);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(ds).usersByUsernameQuery("select * from users where username = ?")
.authoritiesByUsernameQuery("select username, authority from roles where username = ?")
.passwordEncoder(getEncoder());
;
}
#Override
public void configure(HttpSecurity http) throws Exception {
// Spring Security 4 automatically prefixes any role with ROLE_.
http.authorizeRequests().antMatchers("/").permitAll().anyRequest()
.hasAnyRole("ADMIN","USER").anyRequest().authenticated().and().httpBasic();
}
}
Data in table:
insert into users ( username, password)
values ( 'payal', '$2a$12$YcoYj8Si2mbx.gYTLWwPeu51cfI2bTJlWBnnpaI2uYitfQtKzjPxm');
insert into users ( username, password)
values ( 'admin', '$2a$12$vhk1ELFdkwuvtAb8HrnUzOHEGJsnqX5ZX.C3TV3Q4Vuu9dsDcRH8e');
insert into roles ( username, authority)
values ( 'payal', 'ROLE_USER');
insert into roles ( username, authority)
values ( 'admin', 'ROLE_ADMIN');
The entire code can be found at https://github.com/payalbnsl/SpringMvcSecurity_err
This is using in-memory database with db scripts, so can just run without any extra set-up needed.
It will be of great help if someone can point out why it is not authenticating successfully. Every username, password, it is saying 401, not authorized
However it works if i change it to inMemoryAuthentication, hardcoding the username, password.
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("payal").password("$2a$12$YcoYj8Si2mbx.gYTLWwPeu51cfI2bTJlWBnnpaI2uYitfQtKzjPxm").roles("USER");
}

Worked if changed
auth.jdbcAuthentication().dataSource(ds).usersByUsernameQuery("select * from users where username = ?")
.authoritiesByUsernameQuery("select username, authority from roles where username = ?")
.passwordEncoder(getEncoder());
;
to
auth.jdbcAuthentication().dataSource(ds).usersByUsernameQuery("select username, password, 'true' as enabled from users where username = ?")
.authoritiesByUsernameQuery("select username, authority from roles where username = ?")
.passwordEncoder(getEncoder());
;
Adding "'true' as enabled" fixed it.

You have to store encrypted password using the default method, bcrypt, not plaintext.
Use this to encrypt your passwords and store the encrypted format
System.out.println(new BCryptPasswordEncoder().encode("payal123"));
System.out.println(new BCryptPasswordEncoder().encode("admin"));
// . . .

Related

Spring Security Stored Procedures

Can I use stored procedures for login in Spring Security? If possible can you give an example?
Now I can login with this queries
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery( "select login, password, 'true' from my_user " +"where login=?")
.authoritiesByUsernameQuery("select login, authority from my_user " + "where login=?");
}

Spring security providers precedence

I have this configuration, where activeDirectoryAuthenticationProvider is a customized Active Directory provider. What I want to achieve, is that if database authentication fails, no further authentications are attempted.
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
JdbcUserDetailsManager udm = jdbcUserDetailsManager(ds);
udm.setEnableGroups(true);
udm.setEnableAuthorities(false);
auth.userDetailsService(udm).passwordEncoder(userPasswordEncoder())
.and().authenticationProvider(activeDirectoryAuthenticationProvider);
}
Current scenario is:
I have a users databse with PK on the user name
I have a database user with usernname user with some password with some permissions assigned
I have an unrelated user user on active directory with a different password
I login with the user and the password from Active Directory
The user is logged in and gets the permissions from the database user
What I want is:
Login fails, since database authentication has precedence over any other method (that's a biz requirement)
Is this achievable? How could it be done?
SpringSecurity default providers chain don't know anything about priority of providers. Spring tries to authenticate via each provider until someone return Authentication object.
You need custom implementation of AuthenticationProvider, something like PrimaryOrientedAuthenticationProvider. I had a similar case. My implementitaion:
public class PrimaryOrientedAuthenticationProvider implements AuthenticationProvider {
private final AuthenticationProvider primaryAuthenticationProvider;
private final AuthenticationProvider secondaryAuthenticationProvider;
#Override
public Authentication authenticate(Authentication authentication) {
Authentication auth;
try {
auth = primaryAuthenticationProvider.authenticate(authentication);
} catch (UsernameNotFoundException | InternalAuthenticationServiceException ex) {
log.debug("Trying to authenticate with secondary provider after exception", ex);
return secondaryAuthenticationProvider.authenticate(authentication);
}
if (auth == null) {
log.debug("Trying to authenticate with secondary provider after no primary one was returned");
return secondaryAuthenticationProvider.authenticate(authentication);
}
return auth;
}
#Override
public boolean supports(Class<?> authentication) {
return primaryAuthenticationProvider.supports(authentication) &&
secondaryAuthenticationProvider.supports(authentication);
}
}
So, activeDirectoryAuthenticationProvider will try to authenticate only if databaseAuthenticationProvider will throw UsernameNotFoundException (user does not exist) or InternalAuthenticationServiceException (database not available for example).

Can't insert encrypted password in database using bcryptpasswordencoder in java [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm using spring security in spring boot. I want user password should be encrypted and insert into database through controller. But I got this error
Data too long for column 'password' at row 1
Here is WebSecurityConfig class
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username, password, enabled from users where username=?")
.authoritiesByUsernameQuery("select username, authority from authorities where username=?")
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Here is Controller class
....
#Autowired
private PasswordEncoder passwordEncoder;
...
#RequestMapping(value="/register", method=RequestMethod.POST)
public String submitMemberForm(#ModelAttribute("user") #Valid User user, BindingResult result, Model model) {
if (result.hasErrors()) {
viewPage = "membership";
return viewPage;
}
String userPassword = user.getPassword();
String encodedPassword = passwordEncoder.encode(userPassword);
Authority authority = new Authority(user.getUsername(),"ROLE_USER");
user.setPassword(encodedPassword);
user.setAuthority(authority);
userDaoServiceImpl.createUser(user);
viewPage = "membership";
return viewPage;
}
I used hibernate.
How can fix this problem?
Thanks in advance.
Spring security uses $2a$ BCrypt which generates a password string that is 60 characters in legnth. Example: $2a$10$IvpDzjQ3RhFvIECF7r2muOlLsDFywkyGJNEg1q6OudgK9.2vkubfW
so ensure your password column is char(60) or varchar(60) at least

How to set Manually Authenticate User with Spring boot Security

I Created Spring boot application with SSO login. I have used saml.xml file for it. After SSO login i called getAuthentication() method it will return annonymousUser
every time. I want to get SSO Logged User details.
Principal principal =
SecurityContextHolder.getContext().getAuthentication();
Security configuration class look like following :
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/actuator").authenticated();
http.headers().cacheControl().disable();
http.csrf().disable();
http.logout().logoutSuccessUrl("/assets/logout.html");
}
}
You can make user login into spring security like below.
public void login(HttpServletRequest req, String user, String pass) {
UsernamePasswordAuthenticationToken authReq
= new UsernamePasswordAuthenticationToken(user, pass);
Authentication auth = authManager.authenticate(authReq);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
HttpSession session = req.getSession(true);
session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, sc);
}
Refer manually-set-user-authentication-spring-security

How to use Spring Security's JDBC authentication without using "authorities"?

I have problem with authorities.
Reason: PreparedStatementCallback; bad SQL grammar [select
username,authority from authorities where username = ?]; nested
exception is org.postgresql.util.PSQLException: ERROR: relation
"authorities" does not exist Position: 32
I don't want to implement authorities, but don't know how to disable it in JavaConfig in Spring.
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(
"select username,password,'true' as enabled from users where username=?")
.passwordEncoder(new ShaPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
}
As far as I know, you can't deactivate the authorities mechanism with JavaConfig in Spring Security but you can override the query used to fetch the authorities data to achieve the same effect.
When using Spring Security's JDBC authentication, it makes certain assumptions about the database scheme to retrieve authentication data. You already override the query used to fetch the user data in your example with the the call to usersByUsernameQuery().
I managed to effectively disable the whole authorities check by also overriding the query to fetch authorities data like this (as described in "Spring in Action" by Craig Walls):
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)
throws Exception {
authenticationManagerBuilder.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"SELECT username, password, enabled FROM users WHERE username=?")
.authoritiesByUsernameQuery(
"SELECT username, 'ROLE_USER' FROM users WHERE username=?");
}

Resources