IT'S DO
728x90

JWT와 OAuth 2.0을 이용한 sso와 비슷한 통합 인증 처리 방식을 구현하고 나서 정리하기 위해서 작성 되었다.

 

 

여러 방식 중에 두가지 방식을 보면 

 

1.  A 시스템에서 B 시스템의 api를 사용하고 싶을때 (Header 기반 인증 방식)

authentication의 header에 담아서 이용 .

헤더를 통해 JWT를 전달하는 것은 API 호출과 같은 서버 간 통신에서 주로 사용됨. (주로 사용하는 방식)

 

ex)

 # A 시스템 (http://localhost:8081)

@PostMapping("/authenticate")
public ResponseEntity<String> authenticate(@RequestParam String username) {
    // JWT 생성
    String jwtToken = jwtService.generateToken(username);
    return ResponseEntity.ok(jwtToken);
}

 

HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(jwtToken); // Authorization 헤더에 JWT 추가

HttpEntity<?> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
    "http://localhost:8082/api/protected",
    HttpMethod.GET,
    requestEntity,
    String.class
);

System.out.println("Response: " + response.getBody());

=> B 시스템꺼 호출

 

# B 시스템 (http://localhost:8082)

@RestController
@RequestMapping("/api")
public class ProtectedApiController {

    @GetMapping("/protected")
    public ResponseEntity<Map<String, Object>> getProtectedData(Authentication authentication) {
        if (authentication == null || !authentication.isAuthenticated()) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("error", "Unauthorized"));
        }

        String username = authentication.getName(); // JWT의 sub 클레임
        return ResponseEntity.ok(Map.of(
            "message", "Access granted to protected resource",
            "username", username
        ));
    }
}

위처럼 header에서 담아서 토큰을 보내고 해당 토큰을 oauth2ResourceServer을 통해 검증 받고 나서 B의 api의 내용을 a system에다가 호출 하게끔 해준다. 

 

 

 # process

    1. Spring Security의 oauth2ResourceServer 설정이 헤더에서 JWT를 자동으로 추출.


    2. JwtDecoder를 사용하여 JWT를 검증:


    3. 서명 검증: 토큰이 위조되지 않았는지 확인.


    4. 만료 검증: exp 클레임 확인.


    5. 검증이 성공하면, JWT의 클레임 정보를 바탕으로 Authentication 객체를 생성.

 

    6. A  시스템에서 해당 api 사용

 

 

# 헤더 기반 인증의 장점
   보안 강화: JWT는 요청마다 Authorization 헤더에 추가되므로, 쿠키의 CSRF 공격을 방지할 수 있다.
   명확한 인증 흐름: JWT는 인증 정보를 클라이언트가 명시적으로 전달하기 때문에, 여러 시스템 간의 인증이 명확히

   구분 된다.
   유연성: 클라이언트가 원하는 방식으로 헤더를 설정해 다양한 API 호출에 활용할 수 있다.

 

 

# 헤더 기반 인증의 실무 활용
    API 호출: A 시스템에서 발급받은 JWT를 사용해 B 시스템의 API를 호출할 때 주로 사용됨.
   서버 간 통신: 마이크로서비스 구조에서, A 시스템의 서버가 B 시스템의 서버로 API를 호출할 때 헤더에 JWT를 포함.
   브라우저 사용 제한: 브라우저가 아닌 API 클라이언트(예: Postman, Java 클라이언트 등)가 주로 사용.


 

2. cookie에 jwt를 담아서 사용하는 방식. (LIKE SSO)

 

    # process

      1. OAuth 2.0을 통한 JWT 발급:
       A 시스템에서 사용자를 인증하고 JWT를 발급합니다. 
       JWT는 issuer, subject, claims 등을 포함하여 A 시스템에서 서명된 토큰 (JwtEncoder 도 사용)

 

      2. JWT를 사용한 인증 연계:
      B 시스템은 A 시스템에서 발급된 JWT를 받아 이를 검증(JwtDecoder 및 JWK 설정)
       JWT를 디코드하여 사용자 정보(username, roles, businessId 등)를 추출하고, 이를 통해 Spring Security 컨텍스트에          인증 정보를 설정합니다.

 

       3. 쿠키 기반 JWT 전달:
       A 시스템에서 발급된 JWT를 클라이언트 브라우저의 쿠키에 저장(JWT_TOKEN).
       리디렉션 후에도 B 시스템에서 클라이언트가 전달한 JWT 쿠키를 통해 인증

 

       4. B 시스템에서 인증 보호:
       /menu와 같은 경로는 인증된 사용자만 접근 가능하도록 설정.
       JWT를 사용하여 B 시스템에서 독립적으로 사용자 인증 및 권한 확인.

 

 

=> 이렇게 사용하는 이유가 A 시스템에서 B 시스템으로 이동되는 redirect 메뉴가 있을시에, redirect에는 header을 담지 못하기 때문에 사용한다.

 

 

# cookie에 jwt의 장점
  SSO 구현: 한 번의 로그인(A 시스템)으로 B 시스템에서도 인증된 사용자로 접근 가능.  
  분산 인증: A 시스템과 B 시스템은 서로 독립적이면서도 JWT를 통해 연계.
  확장 가능성: 추가 시스템(C, D 등)을 연결하기 쉬움. 각 시스템은 JWT 검증만 추가하면 됨.
  보안성: JWT 서명을 통해 토큰 위조를 방지. HTTPS 환경에서 쿠키로 안전하게 전달.

 

 

# 실무 

이 구조도 실무에서 많이 사용한다고 한다.

A 시스템 JWT 발급 => B 시스템 이를 검증하고 사용자 인증.

마이크로서비스 또는 시스템 간 인증 연계에 적합한 방식.

 

경험상 공기업에서 많이 썼다.

 

 

profile

IT'S DO

@멋진놈

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!