GWT Keycloak logout redirection - spring

So I'm struggling with the integration between Keycloak and GWT.
I do have a AsyncCallBackHandler where I do handle the 403 exception and then redirect to logout when session expires.
My problem is the following :
I tried the Window.Location.replace("sso/logout") which gives me 502 for some reason when redirecting to login, but works fine with the logout button
I tried the Window.Location.replace("http://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri"), it redirects fine to login page, but the problem is when logging in again, I get a weird behaviour like a file gets downloaded and login button gets disabled...
Not sure what I'm doing wrong, any help would be appreciated.
if (ex.getStatusCode() == HttpStatus.SC_FORBIDDEN) {
Window.Location.replace("sso/logout");
}
Configuration on Spring security side is the following :
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout()
.addLogoutHandler(keycloakLogoutHandler())
.deleteCookies("JSESSIONID")
.logoutSuccessUrl("/sso/login");

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).

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

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.

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.

Disabling spring security for google login in application

I have a spring boot application with default level spring security and i am using auth.userDetailsService(customuserservice) for the user authentication part. Apart from that we are using Google login button. My configuration file is
`http
.authorizeRequests()
.antMatchers("/","/securitylogin").permitAll()
.antMatchers("/SecondMainPage")
.hasAnyRole("SUPERADMIN","ADMIN","USER")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/securitylogin") //login
.usernameParameter("username") //optional
.passwordParameter("password") //optional
.defaultSuccessUrl("/loggedin")
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.permitAll();`
Authentication part is working as expected but not the Google login part. After the Google login i am getting the email and fetching his details from the server and redirecting to one controller but the controller his reloading n number of times. I dont know why the single method is getting reloaded again and again.
http.antMatcher("/loginwithgoogle/**").anonymous();
If i use the above line the Google login part is working fantastically but the normal login authentication is not getting access.
web.ignoring().antMatchers(HttpMethod.POST, "/loginwithgoogle");
I tried the above one too but the same controller is reloading again and again for n number of times. Please help me to move on further. Anything else am i missing or am i going in the wrong way??
Actually i tried the same thing before but no idea why i didnt getting succeeded but the following thing works for me and updated the same if it helps for anyone.
http
.authorizeRequests()
.antMatchers("/loginwithgoogle/**").anonymous() //works this order
.anyRequest().authenticated() // with this line too
.antMatchers("/","/securitylogin").permitAll()
i dont know whether there is seperate order will be there or not but i tried the anonymous() seperately but didnt worked. The above is working perfectly.
UPDATE 11.09.2018
The Google login is working perfectly but roles are not working (ie) User can able to access the admin pages and exception handling is not working correctly.

Multiple antMatchers in Spring security

I work on content management system, that has five antMatchers like the following:
http.authorizeRequests()
.antMatchers("/", "/*.html").permitAll()
.antMatchers("/user/**").hasRole("USER")
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/admin/login").permitAll()
.antMatchers("/user/login").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable();
which suppose to mean that the visitors can see all site at root path (/*), and users can see only (/user), admin can see only (/admin), and there are two login pages one for users and another for admin.
The code seems to work fine, except the admin section - it doesn't work but return access denied exception.
I believe that the problem is in the order of your rules:
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/admin/login").permitAll()
The order of the rules matters and the more specific rules should go first. Now everything that starts with /admin will require authenticated user with ADMIN role, even the /admin/login path (because /admin/login is already matched by the /admin/** rule and therefore the second rule is ignored).
The rule for the login page should therefore go before the /admin/** rule. E.G.
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")

Resources