spring security login always ends with failure url [closed] - spring-boot

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I have a problem with proper configuration of spring security, registering works well, restricting access works well but when it comes to logging I get always a failure url result, can anyone tell me where the problem is?
Here is my SecurityConfiguration:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${spring.queries.users-query}")
private String usersQuery;
#Value("${spring.queries.roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource).passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/manage/**").hasAuthority("USER").antMatchers("/").permitAll()
.antMatchers("/business_login").permitAll().antMatchers("/business_password_recovery").permitAll()
.antMatchers("/business_register").permitAll().anyRequest().authenticated().and().csrf().disable()
.formLogin().loginPage("/business_login").defaultSuccessUrl("/manage")
.loginProcessingUrl("/process_business_login").usernameParameter("username").passwordParameter("password")
.failureUrl("/business_login").usernameParameter("email").passwordParameter("password").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**", "/templates/**",
"/boomerang/**");
}
}
this is my login form:
<form autocomplete="off" class="form-default" method="POST" role="form" action="/process_business_login">
<div class="row">
<div class="col-12">
<div class="form-group login-form-input">
<input type="text" name="username" placeholder="email"
class="form-control form-control-lg login-form-input">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group has-feedback">
<input type="password" name="password"
placeholder="password"
class="form-control form-control-lg login-form-input">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="checkbox danger-checkbox">
<input type="checkbox" id="chkRemember"> <label
class="light-gray-color" for="chkRemember">Remember
me</label>
</div>
</div>
</div>
<button type="submit"
class="btn btn-styled btn-lg btn-block btn-danger mt-4 no-border-radius danger-button-login">LOG
IN</button>
</form>
Right there you can see a part of my application.properties file, here I define queries for spring security, they look like this:
spring.queries.users-query=select email, password, active from business_user where email=?
spring.queries.roles-query=select u.email, r.role from business_user u inner join user_role ur on(u.id_business_user=ur.id_business_user) inner join role r on(ur.id_role=r.id_role) where u.email=?
The login always redirects to failure url site, where do I make a mistake?

Your configuration states
.usernameParameter("email")
but the parameter name from the login form states:
<input type="text" name="username" placeholder="email"
class="form-control form-control-lg login-form-input">
So there is a mismatch. I'm thinking that you want to name your form correctly,
instead of
name="username"
you have
name="email"
or you change your configuration from
.usernameParameter("email")
to
.usernameParameter("username")
or remove it, since .usernameParameter("username") is the default.

Related

Failed to load resource 405

I'm a bit at a loss here.
I have a thymeleaf page and a spring-boot backend that takes in a user object, getting the object to the page is fine, my problem comes in when I'm trying to get it to the back end to do stuff with it.
I keep getting the following
2021-09-15 09:21:07.834 WARN 3624 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
and on the browser
Failed to load resource: the server responded with a status of 405 ()
for my controller I have the following
#Controller("/user")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#RequestMapping(value = "/add")
public String addUser(#ModelAttribute("user") final UserDto userDto) {
//do stuff
//userService.save(modelMapper.map(userDto, User.class));
return "/user";
}
}
as for my thymeleaf page
<form th:action="#{/user/add}" th:object="${user}" method="post">
<label for="fullName">Full Name</label>
<input id="fullName" class="form-control form-group" type="text" th:field="*{fullName}">
<label for="email">Email</label>
<input id="email" class="form-control form-group" type="email" th:field="*{email}">
<label for="password">Password</label>
<input id="password" class="form-control form-group" type="password" th:field="*{password}">
<p>
<button class="form-group form-control btn btn-primary" type="submit" value="Submit">Submit</button>
</p>
</form>
What am I missing here?
I did try to mess around the #GetMapping, #PostMapping, #RequestMapping(method = GET), #RequestMapping(method = POST), #RequestMapping(method = {GET, POST})
I also tried <form ... th:method="post"> and <form ... th:method="get">
But none of these seems to work.
You add global /user in #Controller. this annotation is used to implement Web Application not for path and it is better to give global path in application.properties like below code. Inside addUser() method you want to return with page name like return "user" if go to the url then put return "redirect:/user"
Here down is modified code:
application.properties
server.servlet.contextPath=/user/
Controller
#Controller
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute("user") final UserDto userDto) {
//do stuff
//userService.save(modelMapper.map(userDto, User.class));
return "pagename"; // enter page name where you wanna go not url
}
}
Template
<form th:action="#{/add}" th:object="${user}" method="post">
<label for="fullName">Full Name</label>
<input id="fullName" class="form-control form-group" type="text" th:field="*{fullName}">
<label for="email">Email</label>
<input id="email" class="form-control form-group" type="email" th:field="*{email}">
<label for="password">Password</label>
<input id="password" class="form-control form-group" type="password" th:field="*{password}">
<p>
<button class="form-group form-control btn btn-primary" type="submit" value="Submit">Submit</button>
</p>
</form>

404 Page not found after login in custom login page

I am new in Spring and I'm trying to implement a custom login page. I am able to redirect to the custom login page but it goes to error 404 when I hit the Submit button in my page. The url went to : http://localhost:12345/login?username=abcd&password=qwer
Here is my code of the htm, controller and also the security config:
SecurityConfig.java
http
.authorizeRequests()
.antMatchers("/main",
"/main#/home",
"/login**",
"/resources/**",
"/css/**",
"/images/**",
"/js/**",
"/std/**",
"/system/**",
"/favicon.ico",
"/rest/**",
"/rest/user/**" ).permitAll()
.anyRequest().authenticated()
.and().csrf().disable()
.formLogin()
.loginPage("/main#/login").permitAll()
.defaultSuccessUrl("/main#/home")
.failureUrl("/main#/page/b").permitAll();
LoginController.Java
#RestController
#RequestMapping(value = "/rest/user")
public class LoginController
{
#RequestMapping(value = "login")
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("errorMsg", "Your username and password are invalid.");
if (logout != null)
model.addAttribute("msg", "You have been logged out successfully.");
return "login";
}
}
login-content.htm
<div class="col-md-6 col-md-offset-3">
<h2>Login</h2>
<form name="form" action="/login" ng-controller="LoginController" role="form">
<div class="form-group" ng-class="{ 'has-error': form.username.$dirty && form.username.$error.required }">
<label for="username">Username</label>
<input type="text" name="username" id="username" class="form-control" ng-model="user.username" required />
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
</div>
<div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required }">
<label for="password">Password</label>
<input type="password" name="password" id="password" class="form-control" ng-model="user.password" required />
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">password is required</span>
</div>
<input type="submit" ng-click="login(user)" value="Submit">
</form>
Thanks!
At the end I have modified the "action" in the Login-content.htm to another word (e.g. perform_login) and also added .loginProcessingUrl("/perform_login").permitAll() in the SecurityConfig.java.
Besides, the another problem is Spring Security will need to have a specific POST method in order to authenticate it. I have added method="POST" in the HTM page.
Thanks!

How can I fix the CSRF related issues when it is enabled using Spring Boot with Spring Security?

I have a spring boot application. I am using Spring Security. I am facing two issues when CSRF is enabled. Please find the below issues, code and screenshots. How can I fix this?
Whenever the server is restarted, the login always fails the first time. It gives 404 error. But it is successful the second time.
I am using customAuthenticationFailureHandler in case if login is
failed, I am setting the error message in session and redirecting it
to login jsp to display it. It was working fine before CSRF was
enabled. Now, it looks like the value stored in session is destroyed
Security configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
//http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/ui/static/assets/**").permitAll()
.antMatchers("/register", "/forgotPassword").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/LoginPage")
.loginProcessingUrl("/authenticate")
.permitAll()
.defaultSuccessUrl("/addDocument")
.failureHandler(customAuthenticationFailureHandler)
.and().exceptionHandling().accessDeniedPage("/Access_Denied")
.and().logout().permitAll().invalidateHttpSession(true);
}
CustomAuthenticationFailureHandler
#Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
String errMsg=exception.getMessage();;
request.getSession().setAttribute("loginErrorMessage", errMsg);
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.sendRedirect(request.getContextPath()+"/login?error");
}
}
Login.jsp
<c:set var="params" value="${requestScope['javax.servlet.forward.query_string']}"/>
<div class="account-content">
<c:if test="${params eq 'error' && loginErrorMessage ne null}">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>${loginErrorMessage}</strong>
</div>
</c:if>
<form action="${pageContext.servletContext.contextPath}/authenticate" class="form-horizontal" method="post" id="formLogin" data-parsley-validate="">
<sec:csrfInput />
<div class="form-group m-b-25">
<div class="col-12">
<label for="emailaddress">Email address<span class="text-danger">*</span></label>
<input class="form-control input-lg" type="email" name="username" id="username" placeholder="Enter your email" data-parsley-required="true">
</div>
</div>
<div class="form-group m-b-25">
<div class="col-12">
Forgot your password?
<label for="password">Password<span class="text-danger">*</span></label>
<input class="form-control input-lg" type="password" id="pwd" name="password" placeholder="Enter your password" data-parsley-required="true">
</div>
</div>
<div class="form-group account-btn text-center m-t-10">
<div class="col-12">
<button class="btn w-lg btn-rounded btn-lg btn-primary waves-effect waves-light"
id="signInBtn" type="submit" value="Next" >Sign In
<i class="fas fa-spinner fa-spin" id="loadingBtn" style="display:none;"></i></button>
</div>
</div>
</form>
<div class="clearfix"></div>
</div>

Forbidden Error when login in SpringBoot app

I have a basic SpringBoot app. using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.
This is my config file:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(publicMatchers()).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/menu/config")
.failureUrl("/login?error").permitAll()
.and()
.logout().permitAll();
}
my Thymeleaf template:
<form id="loginForm" th:action="#{/login}" method="post">
<div class="row">
<div class="col-md-6 col-md-offset-3 text-center">
<div th:if="${param.error}" class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">x</span>
</button>
<p th:text="#{login.error.message}" />
</div>
<div th:if="${param.logout}" class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">x</span>
</button>
<p th:text="#{login.logout.success}" />
</div>
</div>
</div>
<div class="input_label"><i class="fa fa-user"></i><input type="text" id="usernameId" name="username" th:attr="placeholder=#{login.user.placeholder}" value="peris" /></div>
<div class="input_label"><i class="fa fa-key"></i><input type="password" name="password" value="peris"/></div>
<input type="submit" value="LOGIN" />
</form>
and my Login controller:
#Controller
public class LoginController {
public static final Logger LOG = LoggerFactory.getLogger(LoginController.class);
/** The login view name */
public static final String LOGIN_VIEW_NAME = "login/login";
#RequestMapping(value={ "/", "/login", "/elCor/login"}, method = {RequestMethod.GET})
public String login() {
LOG.info(serverContextPath + "/" + LOGIN_VIEW_NAME);
return serverContextPath + "/" + LOGIN_VIEW_NAME;
}
}
Evefything is OK using the browser, but when I use the mobile, I log in, I go back using the browser button, then I try to log in again but I have this error:
2018-06-28 08:56 [http-nio-5678-exec-2] ERROR c.t.w.c.AppErrorController - getErrorAttributes(request, true) --> {timestamp=Thu Jun 28 08:56:48 CEST 2018, status=403, error=Forbidden, message=Forbidden, path=/elCor/login}
I found the same problem in the computer browser but just once, and I can't not reproduce the problem.. I am trying to guess it
Try adding csrf tokens for login request.
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

Configuring Spring Security To Work With Two Different Login Pages

One of the situations in which we may need two login pages is when we have one page for administrators of an application and a different page for normal users.
Each http element will have a different login page and a different login processing URL
I have got this Spring boot security config for allowing login for multiple page.
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
#Configuration
#Order(1)
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {
public App1ConfigurationAdapter() {
super();
}
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${admin-users-query}")
private String usersQuery;
#Value("${admin-roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/admin*")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/admin/temp/login")
.failureUrl("//admin/temp?error=loginError")
.defaultSuccessUrl("/")
.usernameParameter("email")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/admin/temp/logout")
.logoutSuccessUrl("/admin/temp")
.and()
.exceptionHandling()
.accessDeniedPage("/403").and().csrf();
}
}
#Configuration
#Order(2)
public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${user-users-query}")
private String usersQuery;
#Value("${user-roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/user*")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/user/temp/login")
.failureUrl("/user/temp/?error=loginError")
.defaultSuccessUrl("/user/temp")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/user/temp/logout")
.logoutSuccessUrl("/user/temp/login")
.and()
.exceptionHandling()enter code here
.accessDeniedPage("/403").and().csrf();
}
}
#Configuration
#Order(3)
public static class guestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring().antMatchers("/js/**", "/js/***", "/js/****");
}
}
Admin login form /admin/temp/login
<form th:action="#{/admin/temp/login}" method="post">
<div class="input-group mb-3">
<span class="input-group-addon"><i class="icon-envelope"></i></span>
<input type="text" class="form-control" placeholder="Email" name="email" data-validation="required" />
</div>
<div class="input-group mb-4">
<span class="input-group-addon"><i class="icon-lock"></i></span>
<input type="password" class="form-control" placeholder="Password" name="password" data-validation="required" />
</div>
<div class="row">
<div class="col-6">
<input type="submit" class="btn btn-primary px-4" value="Login">
</div>
<div class="col-6 text-right">
Forgot password?
</div>
</div>
</form>
User login form /user/temp/login
<form th:action="#{/user/temp/login}" method="post">
<div class="input-group mb-3">
<span class="input-group-addon"><i class="icon-envelope"></i></span>
<input type="text" class="form-control" placeholder="Email" name="username" data-validation="required" />
</div>
<div class="input-group mb-4">
<span class="input-group-addon"><i class="icon-lock"></i></span>
<input type="password" class="form-control" placeholder="Password" name="password" data-validation="required" />
</div>
<div class="row">
<div class="col-6">
<input type="submit" class="btn btn-primary px-4" value="Login">
</div>
<div class="col-6 text-right">
Forgot password?
</div>
</div>
</form>
When I Submit the form I get
**Code: 405
(Method Not Allowed)**
When I use single form the form get submted.
Does anyone has an idea on whats happening her?
As someone already answered you need to add
.loginPage("/login.html")
.loginProcessingUrl("/admin/temp/login")
The default URL where the Spring Login will POST to trigger the authentication process is /login which used to be /j_spring_security_check before Spring Security 4.
By default Spring assumes that URL to validate the credentials is /login. To change it you should set up loginProcessingUrl for both formLogin configurations.
It should be something like:
.formLogin()
.loginPage("/user/temp/login")
.failureUrl("/user/temp/?error=loginError")
.defaultSuccessUrl("/user/temp")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/user/temp/login") # missing line

Resources