Search code examples
angularspring-mvcspring-bootspring-securityspring-web

Cannot logout using spring security 5


I'd like to build admin portal for book management (get, add, delete, update a book). So I began with login/logout feature; the login part works like a charm but I'm facing a problem with logout. When I logout the admin portal keeps the session alive and doesn't kill it and I cannot get any error in log that prove me this issue.

Below a piece of code that response to a post request for logout:

@RequestMapping(value = "/user/logout", method = RequestMethod.POST)
    public ResponseEntity logout(HttpServletRequest request, HttpServletResponse response) {
        SecurityContextHolder.clearContext();

        return new ResponseEntity("Logout Successful !", HttpStatus.OK);
    }

In the client I'm using Angular for sending post request to my local server.Below the logout service:

logout(){
    let url="http://localhost:8090/user/logout";
    const xToken = localStorage.getItem('xAuthToken');
    let headers=new Headers({
      'x-auth-token':xToken,
    });

    return this.http.post(url,{headers:headers});
  }

The xToken variable get the session's token from local Browser storage.

Every time we check if session is kept alive or not in ngOnInit of login component:

ngOnInit() {
    this.login.checkSession().subscribe(
      res=>{
        this.loggedIn=true;
      },
      err=>{
        console.log(err);
        this.loggedIn=false;
      }
    )
  }

The service that is responsible for session's check is detailed below:

checkSession(){
    let url="http://localhost:8090/checkSession";
    const xToken = localStorage.getItem('xAuthToken');
    const basicHeader = 'Basic ' + localStorage.getItem('credentials');
    let headers=new Headers({
      'x-auth-token':xToken,
      'Authorization':basicHeader
    });

    return this.http.get(url,{headers:headers});
  }

For checking the session we request the server:

@RequestMapping("/checkSession")
    public ResponseEntity checkSession() {
        System.out.print("Session Active !");
        return new ResponseEntity("Session Active !", HttpStatus.OK);
    }

basicHeader constant is an authentication scheme that contains an encoded username/password combination stored in browser local storage.

for additional information below how we send credentials to the server:

onSubmit(){
    this.login.sendCredentials(this.credentials.username,this.credentials.password).subscribe(
        res=>{
          console.log(res);
          localStorage.setItem('xAuthToken', res.json().token);
          this.loggedIn=true;
          const encodedCredentials = btoa(this.credentials.username + ':' + this.credentials.password);
          localStorage.setItem("credentials",encodedCredentials);
          location.reload();
        },err=>{
          console.log(err);
        }
    )
  }

Please any help is very appreciated. Thanks in advance for resolving this issue


Solution

  • The logout feature is supported by Spring Security out of the box, it just requires some configuration:

    @EnableWebSecurity
    @Configuration
    public class SecurityConf extends WebSecurityConfigurerAdapter {
    
       @Override
       public void configure(HttpSecurity http) {
    
           http
               .httpBasic().and() // HTTP Basic authorization or whichever
               .authorizeRequests()
               .antMatchers(...).permitAll()
               .anyRequest().authenticated().and()
               ...
               .logout();
       }
    
       ...
    }
    

    The /logout method then accessible at http://localhost:8080/logout via POST method, assuming your app is launched on localhost through 8080 port.

    For more details Spring Security doc