Search code examples
javaspring-bootoauth-2.0gitlabvaadin24

Ask for credentials on logout with gitlab Oauth2, vaadin 24 and spring-boot


I'm having trouble implementing the logout functionality in my Vaadin 24 application. I'm using OAuth2 with GitLab as the login provider. The login process itself works fine: I have a custom page with a typical Login with GitLab button. When the user clicks it for the first time, they are redirected to GitLab's login page. After entering their credentials, they are successfully redirected to my home page.

The issue arises when a user logs out. If they try to log in again, instead of being redirected to GitLab's login page and asked to enter their credentials, they are taken directly back to the home page without having to log in again. I need the application to force the user to reauthenticate with GitLab after logging out.

My first attempt looks like this:

@Configuration
public class SecurityConfig extends VaadinWebSecurity {

@Override
    public void configure (HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth ->{
            auth.requestMatchers("/login").permitAll();
            auth.requestMatchers("/register").permitAll();
            auth.requestMatchers("/oauth2/**").permitAll();
        })
        .csrf(csrf -> {
            csrf.disable();
        })
        .oauth2Login(o2 ->{
            o2.loginPage("/login");
            o2.successHandler(new SimpleUrlAuthenticationSuccessHandler("/home"));
        })
        .logout(logout -> logout
            .logoutUrl("/logout")
            .logoutSuccessUrl("/")
            .invalidateHttpSession(true)
            .clearAuthentication(true)
            .addLogoutHandler(new SecurityContextLogoutHandler()));
        
        super.configure(http);
    }

}

In vaadin I use an Anchor

Icon icon = new Icon("vaadin", "power-off");
icon.setColor("white");
        
Anchor anchor = new Anchor("/logout", icon);
anchor.setRouterIgnore(true);

When I do this, vaadin tries to navigate to the 'logout' page, which do not exists. Then I tried to 'manually' logout adding a controller that looks like this:

@Controller
public class AppController{
    
    @RequestMapping("/logout")
    public void exit(HttpServletRequest request, HttpServletResponse response) {
        new SecurityContextLogoutHandler().logout(request, null, null);
        try {
            response.sendRedirect(request.getHeader("referer"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

With this last approach, the user is redirected to my custom login page, but when the Login with Gitlab button is clicked, the user is not asked for their credentials.

Any suggestions?


Solution

  • The new login is silent because you still have a valid session on Github. This is just what SSO is about.

    What you are asking seems to be RP-Initiated Logout: also end the session on the authorization server when ending the session on your Spring client with oauth2Login. But:

    • ending Github user session would be pretty aggressive (users probably don't want to be disconnected from Github when they log out from your app)
    • that would require Github to act as an OpenID Provider with an end_session_endpoint

    You should use your own OpenID Provider: Keycloak, Spring authorization server, Auth0, Amazon Cognito, etc. and implement social login there (put it in front of Github and other social identity providers). All these options have this "Login with ..." feature. That way, you'll be able to end a user session on your authorization server without ending his session on the social identity provider.

    Some other benefits of using your own authorization server:

    • you can use access tokens on your REST APIs configured as resource server (you shouldn't and can't easily / efficiently use Github access tokens for that purpose)
    • you can manage user data (roles for instance)
    • you can manage tokens format and content (use JWT access tokens with the private claims you need for access control)
    • you can control login flows: is multi-factor enabled and how (OTP via app, text message, email, etc.), can users use remeber-me cookies, should super-fast registration and login flows like "magic-links" be enabled, ...

    I wrote a tutorial to get started with Keycloak and Spring on Baeldung.