Search code examples
reactjsspringcookiesspring-security

in response, cookie is in header but not in application why


enter image description here i use spring and react. And I request login to server. In response, the cookie is sent from spring. enter image description here As you see, not in the application.

enter image description here And i send request that need authentication to the server. but there is no cookie in request

While, I send request that use oauth2 then the cookie exist in application and work well.

i dont know why this happens

i attach my code

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {

        ClientDetails clientDetails = (ClientDetails) authResult.getPrincipal();
        //provider의 결과로 여기에 저장됨

        String username = clientDetails.getUsername();

        Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
        Iterator<? extends GrantedAuthority> iterator = authorities.iterator();
        GrantedAuthority auth = iterator.next();
        String role = auth.getAuthority();

        TokenDto token = jwtUtil.createJwt(username, role,"false");

        refreshTokenService.save(token,username);
        response.addCookie(createCookie(CookieType.Authorization.name(),token.getAccessToken()));
        response.addCookie(createCookie(CookieType.Refresh.name(), token.getRefreshToken()));
        response.getWriter().write("success");
    }

    private Cookie createCookie(String key, String value) {
        Cookie cookie = new Cookie(key, value);
        cookie.setMaxAge(60 * 5);
        cookie.setSecure(true);
        cookie.setPath("/");
        cookie.setHttpOnly(true);

        return cookie;
    }

this is the process when login that not use oauth2 success

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {


        CustomOauth2Client oauth2Client = (CustomOauth2Client) authentication.getPrincipal();

        System.out.println(oauth2Client);
        String username = oauth2Client.getUsername();

        Collection<? extends GrantedAuthority> authorities = oauth2Client.getAuthorities();
        Iterator<? extends GrantedAuthority> iterator = authorities.iterator();
        GrantedAuthority auth = iterator.next();
        String role = auth.getAuthority();

        TokenDto token = jwtUtil.createJwt(username, role,"true");

        refreshTokenService.save(token,username);
        response.addCookie(createCookie(CookieType.Authorization.name(),token.getAccessToken()));
        response.addCookie(createCookie(CookieType.Refresh.name(), token.getRefreshToken()));
        response.getWriter().write("success");
        response.sendRedirect("http://localhost:3000/");
    }

    private Cookie createCookie(String key, String value) {
        Cookie cookie = new Cookie(key, value);
        cookie.setMaxAge(60 * 5);
        cookie.setSecure(true);
        cookie.setPath("/");
        cookie.setHttpOnly(true);

        return cookie;
    }

this is the process when login that use oauth2 success

please help me


Solution

  • We don't have enough details to be sure, but maybe your React app is reached by the browser from port 3000 and the Spring one from another port (let's say 8080).

    In your picture, you are showing cookies from localhost:3000, when cookies set by Spring one are most probably set elsewhere (localhost:8080 or something).

    Unless you use a reverse proxy for your browser to reach both from the same socket (host and port), the cookies set by React and Spring will remain separate and each server will get only its own cookies.

    As a side note, your solution seems over-complicated and uselessly fragile:

    • sending tokens to the frontend weakens it: even if the Secure and HttpOnly flags are set, the refresh token will be sent with every https request, which greatly increases the chances that it is intercepted over the network (for instance, look at BREACH attacks for secrets protected with SSL but not rotated frequently enough, which is the case of refresh tokens)
    • sending tokens can make sense only if you want a stateless server (server that can't save tokens in session). In my opinion, this comes with way too much compromises on security for little savings, and anyway, you need sessions for oauth2Login to work, so...
    • this custom cookies writing and reading adds a lot of Java configuration

    Maybe you should have a look at this alternative solution I wrote for Baeldung (tokens in a session maintained by Spring Cloud Gateway, the TokenRelay filter replacing session cookie with Bearer access token on routes to resource servers).