how to make custom login with token in JSF with Spring Security - spring-boot

I've requirement to login with username and password then upon valid credentials to send token on his mail and ask him to enter the token.
I'm setting Login.xhtml page as login page as follows, but the result I'm any form submission goes to authority filter not to the bean, I need it to capture the action in the managed bean first to validate inputs then send him token and validate his input.
http.authorizeRequests()
.antMatchers("/", "/login.xhtml", "/finance.xhtml", "/WEB-INF/errorpages/**",
"/javax.faces.resource/**")
.permitAll().anyRequest().fullyAuthenticated().and().formLogin().loginPage("/login.xhtml")
.defaultSuccessUrl("/index.xhtml").failureUrl("/login.xhtml?authfailed=true").permitAll().and().logout()
.logoutSuccessUrl("/login.xhtml").logoutUrl("/j_spring_security_logout").and().csrf().disable();

I changed loginprocessingurl to fake url and kept login page, so it's redirecting to login page if not logged in and then I'm doing normal stuff to authenticate the user then use authmanger to auth, it's working fine but not optimal specially I'm making explicit redirect to home (not the page the user was accessing) ***Authentication auth = authenticationManager .authenticate(new UsernamePasswordAuthenticationToken(email, token)); SecurityContextHolder.getContext().setAuthentication(auth); Faces.redirect("/index.xhtml");

Related

password reset and thymeleaf redirect

I have a Spring Boot (1.5.6) with Spring Security (4.2) with ThymeLeaf application that allows a user to reset their password. All html pages are in src/resources/templates. The basic flow is:
user provides username (via resetPage.html)
credentials are cleared
token is generated and emailed to username email
user clicks url from email is redirected to reset password page (changePassword.html) for user to create new password
new password is post'd to service where it is persisted and is handled by this code:
#RequestMapping(value = "/user/savePassword", method = RequestMethod.POST)
public String savePassword(Locale locale, #RequestParam("username") String username,
#RequestParam("password") String password, Model model) {
// logic goes here
...
"return "login";
}
At this point everything has worked as desired. The db has been updated, no errors in the console log.
The user is prompted to the login page (although the browser bar says "savePassword) to login. The username and new password are provided and the server returns a 403. There is no error in the console, the only indication that something went wrong is the Chrome Developer Tools returning a 403 from the login POST. The default error page is shown.
If I navigate to the home & then login page, I can authenticate with the newly changed credentials.
I do not see where the error is coming from or why. I have tried running via "java -jar" and with the IDE debugger with debug comments turned on. No errors or messages at all are generated. There is no session, the user had not authenticated, so why would a 403 be thrown (assuming via Spring Security)?
I finally tracked this down. Because the logs were free of any information, I figured it was Spring Security framework doing the work. I updated the security configuration to disable CSRF for the /login page. Now it works as desired.
See your authentication methods and make sure both passwords match in DB or not.
Make sure when changing new password are you using passwordEncoders?. Because 403 error is Forbidden.

Spring Security loginPage Vs loginProcessingURL

what is the difference between loginPage vs loginProcessingURL.
.formLogin().loginPage("/login").usernameParameter("phone-number").passwordParameter("password")
Seems to be loginProcessingURL is like post method once user submits the data in the login page but when I remove also it is working fine. What is the significance of loginProcessingURL and how does it differ from loginPage?
The line loginPage("/login") instructs Spring Security
when authentication is required, redirect the browser to /login
we are in charge of rendering the login page when /login is requested
when authentication attempt fails, redirect the browser to
/login?error (since we have not specified otherwise)
we are in charge of rendering a failure page when /login?error is
requested
when we successfully logout, redirect the browser to /login?logout
(since we have not specified otherwise)
we are in charge of rendering a logout confirmation page when
/login?logout is requested
AND
.loginProcessingUrl("/login/process")
tells Spring Security to process the submitted credentials when sent the specified path and, by default, redirect user back to the page user came from. It will not pass the request to Spring MVC and your controller.
Refer documentation
Purpose of loginPage()
The loginPage() tells the framework where the user will be redirected when login is required. For example when you are not authorized to the page, you get redirected to this page. This page performs the login activity, for example when you implement a loginForm() or oauth2Login() like in my code using Google OAuth2,this page redirects to google login.
http.anonymous().and()
.authorizeRequests().antMatchers("/images**").permitAll().and()
.authorizeRequests().anyRequest().authenticated().and()
.oauth2Login()
.successHandler((request, response, authentication) -> {
request.authenticate(response);
})
.loginPage("/oauth2/authorization/google")
.loginProcessingUrl("/login")
Purpose of loginProcessingUrl()
The loginProcessingUrl() is the method that automatically set the rule antMatchers("/thisUrl").permitAll() to this URL so that when the response is returned (code, state, token, etc.) will be allowed to be GETed and this response is processed as you can see in the authenticate method of the request. Something more important is that this loginProcessingUrl() tells that the response should be processed to this URL. Without this the request.authenticate(response) will not be executed and authentication will not be returned or otherwise you implement another algorithm.
May the following code segment from spring security source code will help you:
loginPage the login page to redirect to if authentication is required
loginProcessingUrl the URL to validate username and password
DEFAULT_LOGIN_PAGE_URL = "/login"
/**
* Updates the default values for authentication.
*
* #throws Exception
*/
protected final void updateAuthenticationDefaults() {
if (loginProcessingUrl == null) {
loginProcessingUrl(loginPage);
}
//...
}

SAMLException: InResponseToField of the Response doesn't correspond to sent message

We are working on an application, which is protected with spring security saml.
Authentication works fine, but there is one problem with the following workflow in production environment.
user requests the unprotected address www.server.com
response is a html page with an inline script that changes window.location.href to the saml protected page (service provider) www.server.com/app/action?param1=value1&param2=value2
spring saml detects that authentication is needed and redirects the user to the login form (identity provider) on www.login-server.com
at this point the login form is the first page that is displayed to the user
user adds this login page as bookmark (including saml related url params for this http session) www.login-server.com/adfs/ls/?SAMLRequest=xxx&SigAlg=xxx&Signature=arGdsZwJtHzTDjQP1oYqbjNO
user works with the application...
at the next day the user opens this bookmark and login
IdP redirects to the SP but the belonging http session has already expired
Now we get the following exception in our application:
org.opensaml.common.SAMLException: InResponseToField of the Response doesn't correspond to sent message arGdsZwJtHzTDjQP1oYqbjNO
Any ideas how to handle this workflow so the user can use the application after successful login?
Thanks for your answers!
We have solved our issue with following changes to the spring saml configuration:
In bean with id successRedirectHandler (org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler) we set the defaultTargetUrl to the init-Action of our application (including all request parameters). This url will be automatically used in case of IdP initiated SSO.
In Bean with id contextProvider (org.springframework.security.saml.context.SAMLContextProviderLB) we set storageFactory to org.springframework.security.saml.storage.EmptyStorageFactory. This disables the check of the InResponseToField.
When you applicate generated an AuthnRequest, the request has an ID which your application somehow keeps. The corresponding response from IdP must have InResponseTo attribute set to that same ID value so that your application can verify that the response is meant to be for the request it sent.
However, when your user bookmarked the adfs link that contains request (www.login-server.com/adfs/ls/?SAMLRequest=xxx...), your application had totally forgotten about that request. In other word, it no longer kept the request ID somewhere and couldn't verify response.
The solution is to tell your users not to bookmark the www.login-server.com/adfs/ls/?SAMLRequest=xxx... link. Instead, they must bookmark a link in your application where it can generate a new request and send to ADFS.

Spring OAuth2 custom Authentication with external Redirects

I am trying to implement a custom authentication mechanism in Spring.
I have an authentication mechanism, that works like this:
User visits any subpage of my page http://mypage
User gets redirected to http://mypage/login, because my WebSecurityConfigurerAdapter is configured, that any Request (except to /login and /redirect, has to be authenticated)
On the Login page a custom login mechanism happens, where I authenticate the user on an external site, that redirects the user's browser to the external page and then back to another subpage of my page: /redirect with custom data in the response
On /redirect I set the Authentication of the user, depending on the custom data and add a GrantedAuthority ROLE_FIRST
After this step the user is redirected to subpage /home, which is only visible to authenticated users with GrantedAuthority ROLE_FIRST.
If the user clicks on a button on /home a GrantedAuthority ROLE_SECOND is added to the current Authentication of the user and the user is redirected to /secret
The user is then authenticated with two factors (external login, buttonclick) and can see the content of /secret, which requires an authentication with GrantedAuthority ROLE_SECOND
So far so good, but I now want to redirect the user to the initial URL he tried to access. So if the user visited http://mypage/random in the first step, the user should be redirected to /random instead of /secret in the last step.
The problem is, I am loosing the URL in the step with the external login, because there is happening a external redirect and I can't pass the URL to the external service.
How can I manage this?
Bonus Question: What if the URL /random would be the URL to an OAuth2 Token interface instead? Would that change anything?

spring security 2 phase authentication

I'm a newb to spring security and I'm not sure where to start. I have requirements to have a multi-page authentication. The first page authenticates the username, if the username exists the web app progresses to the password page. (site image) The second page authenticates the password, if successful then the user is authenticated. I'm not sure how to fit this into spring auth. Do I add multiple login-filters and authenticationproviders ? If I add multiple authenticationproviders, will I be authenticated after the first login ?
Page 1: User enters username. Submit this to your own controller where you check if the user exists. If the user exists, display page 2, pass the username in the model. You better not include Spring Security authentication in this step.
Page 2: User enters password. Use a readonly or hidden field to keep track of the username. Submit the form to Spring Security form login filter. You don't need multiple authentication providers.
Note: This approach has an information "leak"; any visitor can check whether a username exists in the system or not.
It depends on the kind of your authentication:
JDBCAuthentication
You can do with #holmis83 suggests.
LDAPAuthentication:
I am afraid tht you can't do that.

Resources