Custom .formLogin() Spring Security - spring

I am trying to use my page created to authenticate, it is the login.jsf. I use in .loginPage / login.jsf with 2 inputs and 1 button to authenticate. However, by filling in the logins and password fields, and clicking the button, nothing happens. Unlike Spring Security own .formLogin() itself, which already does all the processing by clicking the button.
My method
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login.jsf").anonymous()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.jsf")
.defaultSuccessUrl("/homepage.jsf")
.failureUrl("/login.jsf?error=true")
.and()
.logout().logoutSuccessUrl("/login.jsf");
}
Anyone have any suggestions?
Print screen default .formLogin()

Take a look at the following article from spring security documentation.
https://docs.spring.io/spring-security/site/docs/current/guides/html5/form-javaconfig.html#creating-a-login-view
Quoting the article,
The URL we submit our username and password to is the same URL as our
login form (i.e. /login), but a POST instead of a GET.
So I believe you have to make a POST call to the /login endpoint with your authentication details for it to work.

Don't use file extensions when specifying pages in the configuration. The ViewResolver will take care of it. Simply specify
.loginPage("/login").defaultSuccessUrl("/homepage")
.failureUrl("/login?error=true")
.and()
.logout().logoutSuccessUrl("/login");`
And make sure a ViewResolver is configured to append .jsf to the url. The DispatcherServlet will take care of locating the appropriate page.
Also, not to mention, you should have controllers with the appropriate #RequestMappings defined to handle your requests.

Related

adding httpSecurity.csrf().disable() to spring security configuration is allowing unauthenticated endpoint calls

I have the following security configuration for my springboot project
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/test_url_1");
}
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/");
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
now I have another endpoint /test_url_2. Calling which should be redirected to error page for an unauthorized user. If am removing csrf().disable() its working fine and the request is going to default /error page. but on adding csrf().disable() ,I am noticing a very unusual behaviour. once another endpoint ex. /test_url_3 is being called with an jwt header for authorization, next time onwards the endpoint(/test_url_2) is blocked even for unauthorized user, i.e. instead of going to the error page its calling the end point.
I am still new to spring security and spring, and not sure if I am writing some configuration wrong, please help me with the issue.
I didn't get exact meaning of the following sentences:
I am noticing a very unusual behaviour. once another endpoint ex. /test_url_3 is being called with an jwt header for authorization, next time onwards the endpoint(/test_url_2) is blocked even for unauthorized user, i.e. instead of going to the error page its calling the end point.
If you didn't get what exactly CSRF I recommend watching this video: https://youtu.be/uzZzlar-iQI from 1:08:00. If you want to authenticate url1 and don't want to authenticate url2 try the following code instead of using anyRequest().
httpSecurity.csrf().disable()
.authorizeRequests()
.antMatchers('/ur1')
.authenticated()
follow through this URL for more info on CSRF: https://www.baeldung.com/spring-security-csrf

Spring Security: how to recognize, in a public page, that a user is authenticated

I have a simple Spring Boot web application consisting of 2 pages:
a Home Page (freely accessible) at the url https://example.com/
a secured page (requires login for being accessed) at the url https://example.com/secure/page.html
In the Home Page I'm printing the First Name of the visiting user (if he/she is already authenticated) or a sentence saying that the page is visited by an anonymous user.
I'm using Keycloak as far as authentication is concerned.
Here the Spring Security configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secure/**")
.authenticated()
.and()
.csrf().requireCsrfProtectionMatcher(keycloakCsrfRequestMatcher())
.and()
.sessionManagement()
.sessionAuthenticationStrategy(sessionAuthenticationStrategy())
.and()
.addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
.addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
.addFilterBefore(keycloakAuthenticatedActionsFilter(), BasicAuthenticationFilter.class)
.addFilterAfter(keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class)
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
.and()
.logout()
.addLogoutHandler(keycloakLogoutHandler())
.logoutUrl("/sso/logout").permitAll()
.logoutSuccessUrl("/");
}
If the user is already authenticated, the problem is that the Home Page says he is anonymous because the Principal is always null.
But if the user enters the secured page (and Keycloak lets him in because he's already authenticated) when he comes back to the Home, the page contains - correctly - his First Name.
Where is my configuration wrong?
It seems that Spring Security doesn't check the authentication on non secured pages. Is there a way to tell Spring Security to check every page (both secured and non-secured)?
Thanks in advance for your support.
The solution to this problem is to add /** to security context/handling (with permitAll()).
The art is to do it correctly:
Multiple antMatchers in Spring security (First ant matcher wins!!, https://www.google.com/search?q=spring+security+permitall+not+working)
http://blog.florian-hopf.de/2017/08/spring-security.html
So in this case:
http
.authorizeRequests()
.antMatchers("/secure/**").authenticated()
.antMatchers("/**").pernmitAll()
.and()...
...should fill the (anonymous) Principal also in "permitted area" (i.e. /**(!) ...and leave secure/** restricted!;).
To the core/title question (once Principal is filled), i think the answer is already given:
here (verbally): https://stackoverflow.com/a/26117007/592355
and here(with code): https://stackoverflow.com/a/57054816/592355
..if you use Spring Security (JSP) Taglibs isAnonymous() is handy, and otherwise (in default) you just need to check for hasRole('ROLE_ANONYMOUS') (Ref)

Spring OAuth2 security concerns

I am currently implementing Authorization_Code type OAuth2 flow to have single-sign-on (SSO) on my website.
Here is my code that enables it.
#Override
protected void configure(final HttpSecurity http) throws Exception {
// #formatter:off
http.authorizeRequests()
.antMatchers("/login", "/authorize", "/error")
.permitAll()
.anyRequest()
.authenticated()
.and().formLogin().loginPage("https://sso.mywebsite.com").loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/success",true)
.failureUrl("/error").permitAll()
.and()
.csrf()
.disable();
// #formatter:on
}
My concern is described below.
To make a login request (with username and password), sso.mywebsite.com should make a POST request to my oAuth service - http://oauth/perform_login?username=USERNAME&password=PASSWORD.
I tried it with Postman and it works. However, isn't this a security problem to send plain username and password like above in query param? I thought exposing user credential in uri (query param) could get captured by various network sniffing tools.
Is there a way to do this in different method?
As long as you are using HTTPS, your query parameters will be secure.
I am unclear, why your SSO website should make a POST to that URL (and also, why instead of having a POST body, append the parameters via the url). Shouldn't it rather "redirect" to the login page/authorization server or is the code above from your authorization server? It was a bit unclear from your description.

Spring boot and Spring Security, different logon forms to use different success handlers

I have a spring boot/mvc site using spring security.
I have to use ways of logging in,
In the navbar present on each page
and the login page which you are redirected to when attempting to access a restricted resource.
For the navbar i'd like the user to stay on the page after successful login
For the login page i'd like the user to be redirected to the resource they were trying to originally access after login.
I can do each functionality individually
First use case is handled by:
SimpleUrlAuthenticationSuccessHandler handler = new SimpleUrlAuthenticationSuccessHandler();
handler.setUseReferer(true);
Second case is the default functionality.
But i've been unable to make them both work.
Does anyone have any insights on how to achieve this?
You can configure each login page with a different AuthenticationSuccessHandler like described here
https://www.baeldung.com/spring_redirect_after_login
Like:
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/anonymous*").anonymous()
.antMatchers("/login*").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.successHandler(myAuthenticationSuccessHandler())
.and()
.formLogin()
.loginPage("/login2.html")
.loginProcessingUrl("/login2")
.successHandler(mySecondAuthenticationSuccessHandler())
// ...
}

Is a stateless app compatible with formlogin?

I'm struggling for some days with this problem : I have an authentication server with spring security. I use JWT tokens, and as I need my users to be able to logout from the font side, I need not to have a JSESSIONID, so I set the sessionCreationPolicy(SessionCreationPolicy.STATELESS)
Also I need a login form on the authentication server side, which I manage with formLogin().
Unfortunately, if I use those 2 configs at the same time, once the user have submited the login form, he's not redirected back to the front app.
If I drop the SessionCreationPolicy.STATELESS and set the formLogin() part, then the redirection is working, but then I got a session, and logout doesn't work.
If I set SessionCreationPolicy.STATELESS and httpBasic(), then the redirection is working, but of course I don't have the login form.
Is there any way to achieve that?
here the config :
http.cors().and().csrf().disable().
authorizeRequests()
.antMatchers("/token/*").permitAll()
.anyRequest().permitAll()
.and()
.httpBasic()
// .formLogin()
// .loginPage("/login")
// .permitAll()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

Resources