ch4mpy / spring-addons

Ease spring OAuth2 resource-servers configuration and testing
Apache License 2.0
521 stars 84 forks source link

Logout Issue (Invalid CSRF Token) #208

Closed adhik closed 4 months ago

adhik commented 4 months ago

Hi, thanks for your great works here.

I've tried following your tutorial here and so far it worked, except the logout attempt. It gave me Invalid CSRF token response in Chrome.

After debugging, I've found the issue here:

image

It seems the the CSRF token is inside "Cookie" and can't be retrived by using

exchange.getRequest().getHeaders().get(csrfToken.getHeaderName())

maybe it would work by doing this?

exchange.getRequest().getHeaders().getOrEmpty("Cookie").get(csrfToken.getHeaderName())

Other workaround in the frontend (Angular) perhaps to put the X-XSRF-TOKEN from Cookie into the custom header:

logout() {
    lastValueFrom(
      this.http.post(`${environment.baseApiUrl}/logout`, null, {
        headers: {
          'X-POST-LOGOUT-SUCCESS-URI': environment.appUrl,
          'X-XSRF-TOKEN': this.cookie.get('XSRF-TOKEN'),
        },
        observe: 'response',
      })
    )
      .then(resp => {
        const logoutUri = resp.headers.get('Location');
        if (!!logoutUri) {
          window.location.href = logoutUri;
        }
      })
      .finally(() => {
        this.refresh();
      });
  }

but I don't think it is a good idea :smile:

Thanks.


My environment:

ch4mpy commented 4 months ago

If you follow the tutorials strictly, the logout should work in all 3 applications (with CSRF).

Angular automatically adds an X-XSRF-TOKEN header when a CSRF cookie is accessible to Javascript (http-only flag set to false in the cookie). So what you describe as workaround is actually what Angular does for us behind the scene. But Vue for instance don't do it and we have to do something like you propose. This is explained in section 7.4 Logout of the article.

Maybe did you miss the part with csrf: cookie-accessible-from-js in spring-addons client properties for the BFF?

adhik commented 4 months ago

Hi, so it turned out Angular issue since I used absolute URL for ex:

this.http.post(`http://localhost:7080/bff/logout`, null, {
....

Angular didn't include the XSRF-TOKEN from Cookie because of this code here.

So the solution is to use relative URL like the one in your example:

this.http.post(`/bff/logout`, null, {

Thanks :+1:

ch4mpy commented 4 months ago

Yep, that limitation with absolute URLs and CSRF is something to keep in mind when working with Angular :/