이번 프로젝트에서는 서비스에서 인증/인가가 필요했고, 해당 서비스는 gRPC로 제공하고 있었습니다.
우선 급한대로 gRPC Controller에서 Request Header에 있는 Token 정보를 꺼내서, 해당 Token이 가지고 있는 Role을 가져와서 처리하도록 했습니다.
즉, 새로운 API가 생길 때 마다, Controller 시작 지점에 인증/인가 함수를 호출하도록 처리 했고, 불필요한 중복 코드로 느껴졌습니다.
또한, 비즈니스 코드에 불필요한 인증/인가가 있다보니, 이를 앞단에서 처리하여 Interceptor처럼 구성하고, 인증/인가와 서비스 로직을 분리하고 싶었습니다.
이에, 어떻게 처리할 수 있는지 알아보고, Spring Security + gRPC Authentication을 적용하는 과정을 알아보았습니다.
우선 gRPC 가 어떻게 Security를 제공하는지 확인이 필요합니다.
공식 문서 : https://yidongnan.github.io/grpc-spring-boot-starter/en/server/security.html

공식 문서에서 spring-security를 기본적으로 제공하기 때문에 어노테이션으로 application에 security 설정이 가능하다고 나와 있습니다.

저희는 우선 jwt로 토큰을 관리하기 때문에 BearerAuthenticationReader로 처리할 예정입니다.

추가로 여러 인증을 Composite하게 처리하려면 다음과 같다고 합니다.
CompositeGrpcAuthenticationReader는 여러 인증 방식 중 하나를 선택하여 추출.
토큰 추출 성공: 추출된 자격 증명은 AuthenticationManager로 가서 유효성 검증을 받습니다.
유효하면 성공, 아니면 실패(예외).
토큰 추출 실패 (null 반환): 인증되지 않은 상태로 요청이 계속 진행됩니다.
강제 인증 실패 (예외 던지기): AuthenticationException을 던져 무조건 인증 실패를 유발하고 요청을 막습니다.
저희는 우선 jwt 토큰 기반의 인증/인가 처리를 할 예정이며, 필요에 따라 Basic 도 추가할 수 있는 상황이었습니다.
그렇기 때문에 위 내용을 숙지하고 넘어갑니다.

Spring Security에서 처리하는 방법처럼 authenticationManager에서 Jwt 토큰으로 처리하는 provider를 등록합니다.
이후, spring-boot-starter-grpc에서 제공하는 GrpcAuthencationReader에 등록합니다.

gRPC 에서 security 체크는 다음과 같이 처리합니다.
securityMetadataSource를 bean으로 등록하면 되는데, ManualMetadataSource()를 통해 source를 생성한 후 인증, 인가 처리를 할 method에 인증/인가 속성을 추가하면 됩니다.
밑에 보면 AccessDecisionManager를 통해 어떻게 처리할 지 나오는데 어떤 속성이 있는지 궁금하여 찾아보았습니다.
주요 AccessDecisionManager 속성
1. AffirmativeBased (찬성 기반)동작 방식: 하나의 Voter라도 접근을 ACCESS_GRANTED로 투표하면 접근을 허용합니다.
2. ConsensusBased (합의 기반)동작 방식: 찬성표(GRANTED)와 거부표(DENIED)를 비교하여 다수결로 결정합니다.
3. RoleVoter (만장일치 기반)동작 방식: 모든 Voter가 접근을 승인해야 최종적으로 접근을 허용합니다.
AccessDecisionManager는 등록된 하나 이상의 AccessDecisionVoter에게 이 정보를 전달하여 투표를 요청하여 위 속성에 맞게 반환합니다.
여기까지 Spring에서 gRPC Authentication 및 Authorization을 처리하는 방법이었습니다.
이제 이것을 실제로 코드에 적용하고 잘 동작하는지 확인하겠습니다.
실제 적용 과정은 다음 블로그에서 작성해보도록 하겠습니다.