Spring MVC based application is not landing to default success url while trying to access it using https url but working fine on http based url - spring

While running the spring mvc based application on http, it is working fine but once the application is moved to https based configuration, we are not able to get successful landing url page. The url which are non authenticated is working fine but the authenticated urls are not reachable even after providing correct login credentials.
Please help me with the missing configurations/issues to resolve this problem.
The application is deployed over Jboss server.
Below are the configurations done as part of application.
protected void configure(HttpSecurity http) throws Exception {
System.out.println("I am configure");
http.csrf().disable();
// The pages does not require login
http.authorizeRequests().antMatchers("/login", "/logout", "/resetPassword", "/forgotPassword", "/change-password", "/confirm-account", "/registerPage", "/registerwithemail", "/resources/**", "/logoutSuccessful", "/login/**").permitAll();
http.authorizeRequests().antMatchers("/**").authenticated();
http.authorizeRequests().antMatchers("/home").authenticated();
http.authorizeRequests().antMatchers("/").authenticated();
// /userInfo page requires login as USER or ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers("/userInfo").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers("/admin").access("hasRole('ROLE_ADMIN')");
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will throw.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/403");
http.headers().frameOptions().sameOrigin();
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginPage("/login")//
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.defaultSuccessUrl("/home", true)// userInfo (Changed to) home
.failureUrl("/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
// For Remember-me
.and().rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).tokenValiditySeconds(86400)
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/logoutSuccessful").invalidateHttpSession(true).deleteCookies("JSESSIONID", "remember-me");
}
if there is any channel security for http/https is required, please let me know about the configurations as I'm also traversing internally to different module using ip and port based http url.

Related

Is there any implementation of OIDC Session Management and Logout mechanism in Spring Authorization Server for implementing Single Sing On?

I am trying to implement Single Sing On using Spring Authorization Server which is based on oAuth2 and OIDC for Authorization and Authentication respectively, but as per the Spring Authorization Server feature list OIDC support is not fully integrated. Mainly the session management and logout part, I couldn't find. Also if there's any workaround for implementing sso and logout?
Feature List URL: https://docs.spring.io/spring-authorization-server/docs/current/reference/html/overview.html
These features are still on the backlog but are not scheduled yet (as of the time of this writing). See #58 and #266 respectively to follow progress on these features.
Given that there are a number of pieces to the specifications for both of these features, I imagine it would be a bit of a hassle to attempt a fully spec-compliant implementation of them as extensions to SAS (though I'm sure it's possible). Instead, you might pick a minimal subset of the logout feature as a way to get started.
Using Spring Security configuration, you can configure a logout endpoint in a custom way. Here's some pseudocode to get you started:
#Bean
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.logout((logout) -> logout
.logoutRequestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/logout", "GET"),
new AntPathRequestMatcher("/logout", "POST")
))
.addLogoutHandler((request, response, authentication) -> {
// Logic to validate an id_token_hint, client_id, etc.
// Throw exception in case of invalid request
})
.logoutSuccessHandler((request, response, authentication) -> {
// Get state and calculate redirect for logout success back to client
// http://127.0.0.1:8080/logout?success&state=...
// new SimpleUrlLogoutSuccessHandler()...
})
);
return http.build();
}
This assumes validation of some kind is implemented to prevent CSRF, denial of service, etc. You might also choose to add a logout confirmation page as a separate endpoint of the auth server that redirects to the logout endpoint when the user clicks a "Confirm" button, etc.
To use this, you simply redirect from your client application to the logout confirmation page, which redirects to the logout endpoint on confirm, which then redirects back to the client (which can then log out of the client automatically).

how to make custom login with token in JSF with Spring Security

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");

Spring Boot/Security - Custom 404 page

I have created a custom 404 error page in my Spring Boot app, I also use Spring Security and I have an authentication entry point with a number of authorised URL's (error page included in that list).
What I'm finding is that if I enter a URL that doesn't exist the authentication entry point intercepts the request as it isn't an authorised URL and I end up back at my login page instead of the custom 404 error page. Any ideas?
Basic example of what I have in the security config
http
.csrf().disable()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
.and()
.authorizeRequests().antMatchers("/login", "/error-404")
Here is what Spring Security will do when you invoke /invalid-url
If /invalid-url is secure (default)
Store the request (/invalid-url -> session)
Invoke authentication entry point
Redirect to /login
User will authenticate
Upon successful authentication, redirect to stored request /invalid-url
Page not found - redirect to error handler
If /invalid-url is not secure
Page not found - redirect to error handler
So basically, you'd need to declare all your non secure URLs if you want the second flow, directly go to 404 page
.mvcMatchers("/login", "/error-404/**", "/invalid-url/**").permitAll()
Obviously doing this:
.anyRequests().permitAll()
as the last statement will solve your use case, it is also dangerous. You have then explicitly map out any endpoint that must be secured. And if you forget one, that endpoint will be left exposed.

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);
}
//...
}

Spring 4 MVC + Security login page redisplayed

I am implementing the security for my web application. The below are different event that takes place in authentication.
1) Successful login takes the users to the "dasboard" page.
2) Failure will take to the login page with the error.
3) The unauthenticated user access the secured page directly, redirected to the login, success takes to the dashboard, failure to the login with error.
4) The unauthenticated user access the secured page directly, redirected to the login, success takes to the dashboard, failure to the login with error.
The problem,
1) The user is successfully authenticated, views the dashboard page. Again he navigates directly to the login page, login is displayed. But, why should it? Should it not, by default, redirect to the dashboard? Should I need to check in my login controller if the user has already logged-in and redirect to dashboard or any configuration I am missing?
2) I have 3 role of users, super admin, admin and user. Can I redirect to different pages based on different role of users? If so how? If not how can this be implemented?
3) Based on the configuration I should be able to switch between LDAP auth or DB. If the app needs to be authenticated, in future, with ldap shall I inject the auth provider based on configuration? How do configure multiple authenticators?
Please share your wisdom/docs/links on "this is how it should be done" spring-security
My WebSecurityConfig.java
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin()
.loginPage("/login").loginProcessingUrl("/authenticate")
.defaultSuccessUrl("/dashboard").failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password")
.permitAll().and().logout().logoutUrl("/logout").permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
AuthenticationProvider authenticationProvider = new CustomAuthenticationProvider();
auth.authenticationProvider(authenticationProvider);
}
1) As you said this can be easily done in your login controller. Just send a redirect instead of the login page if you know that the user is already logged in.
2) I think you mean the redirect after the user logged in, are you?
This can be achieved using a custom AuthenticationSuccessHandler. Maybe this question can give you more details.
3) You can configure multiple AuthenticationProviders (e.g. one for LDAP and one for DB) using an ProviderManager AuthenticationManager. An option would be to configure the AuthenticationProviders during startup in your java config based on the given environment or configuration values.
1) Create session when the user login.and always check that login session on you login page...if session is caught ,redirect to dashboard,....if session in null let it live on login page...
2) Create sessions according to the which user is login, for example if "super user" logins, create session of "superUser"....and vice-versa...
Now check that session,if session has value of superUser,redirect it to desired page for super user....and vice versa...
In both of these using session is good choice.

Resources