How logout from spring oauth2 with Google auth

125 Views Asked by At

I have react app which build is added in spring app and whole app is autehnticated with spring oauth2 using google.So when I am opening /logout but it is not doing logout , it is redirecting home page so how to do that. I have written this to clear cookies but didn't work

return httpSecurity
                .sessionManagement(session ->
                        session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
                                .sessionFixation().migrateSession()
                                .maximumSessions(1)
                                .expiredUrl("/login?expired"))
                .authorizeHttpRequests(auth -> {
                            auth.anyRequest().authenticated();
                        }
                )
                .csrf(csrf -> {
                    csrf.disable();
                })
                .oauth2Login(withDefaults())
                .logout((logout) -> {
                    logout.logoutUrl("/logout");
                    logout.invalidateHttpSession(true);
                    logout.logoutSuccessUrl("/");
                    logout.clearAuthentication(true);
                    logout.deleteCookies("auth_code", "JSESSIONID", "refreshToken", "Authorization")
                    ;

                })
                .build();
1

There are 1 best solutions below

0
ch4mp On

Your users have two sessions: one on your Spring OAuth2 client with oauth2Login and a different one on Google authorization server. The Logout you implemented ends the user session on your Spring OAuth2 client, not the one at Google.

The consequence is that when a user logs in your Spring app again, the authorization code flow completes silently: user is redirected to Google authorization server, as (s)he has an active session there (and already accepted to grant your Spring OAuth2 client with the scopes it request), (s)he's redirected back to your client with an authorization code, and without being prompted for credentials.

You probably feel like this behavior is an issue because you configured your Spring app as follow:

  • a single OAuth2 client registration with authorization-code in your application properties
  • kept the default Spring Security login page which automatically redirects to the authorization server when there is a single registration with authorization-code
  • kept the spring-boot-starter-oauth2-client default which is to answer 302 redirect to login to unauthorized requests to protected resources, when 401 Unauthorized is probably a better option for single-page and mobile applications which have content accessible to unauthorized users and a "Login" button

If you change any of the points above, you'll notice that your users are actually logged out from your Spring app.

If you choose to change the configuration for unauthorized requests response status from 302 to 401, you'll have to implement some user status in your SPA (this will be useful for route guards, displaying "Login" or "Logout" button, ...). This is a simple task if you add an endpoint accessible to anonymous and returning some data about the Authentication in Spring security context. And by the way, when calling it after logout, you'll see that user is actually logged out from your app (user is anonymous and there are no more OAuth2 tokens in session).

If you really want to log users out from Google, you can:

  • redirect them to Google Logout page and expect them to click "Logout" there
  • have look at RP-Initiated Logout

But it would probably be a very bad experience for the users to have their Google session ended just because they want to quit your app. What I'd do is using an authorization server of my own with Google as identity provider. I'd then configure RP-Initiated Logout in Spring, which would end sessions on Spring client and then on my authorization server, but leaving user's Google session alive.

There are quite a few options for such an authorization server:

  • standalone like Keycloak
  • cloud offers (Auth0, Amazon Cognito, Okta, Azure,...)
  • do it yourself with spring-authorization-server, which is reasonable in the case where you need just "Login with ..." (no need to create login & registration forms, user database, etc.)

PS

oauth2Login relies on sessions and sessions are exposed to CSRF attacks. Disabling CSRF protection in a SecurityFilterChain with oauth2Login is not reasonable.