인증 서비스 구축: OAuth2 + JWT 기반 토큰 발급

인증 서비스 구축 을 MSA 환경에서 어떻게 구현하는지 알아보자.
MSA 환경에서는 인증을 별도의 전담 서비스로 분리하는 것이 일반적이다.
이 인증 서비스는 로그인 요청을 처리하고, 토큰을 발급하며, 사용자 신원을 검증하는 역할을 담당한다.
이 글에서는 Kotlin과 Spring Boot를 활용해 OAuth2 기반 로그인 요청을 처리하고 JWT(Json Web Token)를 발급하는 인증 서비스를 구축하는 방법을 다룬다.

1. 기술 스택 선택

  • Spring Security: 인증/인가 처리의 핵심 프레임워크
  • OAuth2 Resource Server: JWT 기반 토큰 검증
  • Spring Authorization Server: OAuth2 인증 서버 역할
  • Kotlin + Spring Boot 3.x: 코틀린 기반의 경량화된 마이크로서비스 개발

2. 인증 서비스의 주요 기능

  • 사용자 로그인 인증 처리
  • Access Token(JWT) 발급
  • 리프레시 토큰 저장 및 재발급
  • 토큰 서명 및 검증

3. 기본 설정

의존성 추가 (auth-service/build.gradle.kts)

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.boot:spring-boot-starter-oauth2-authorization-server")
    implementation("com.nimbusds:nimbus-jose-jwt:9.37")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation(project(":common-lib"))
    implementation("jakarta.servlet:jakarta.servlet-api:5.0.0")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

application.yml 예시

spring:
  application:
    name: auth-service
  security:
    oauth2:
      authorization:
        issuer-uri: http://localhost:8081
server:
  port: 8081
jwt:
  secret: mysecret

4. 사용자 인증 처리

Spring Security의 UserDetailsService를 구현하여 사용자 인증 로직을 정의한다.

@Configuration
class AuthorizationServerConfig {
    @Bean
    @Order(1)
    fun authorizationServerSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)
        return http.build()
    }
} 

5. JWT 발급 구성 (OAuth2 인증 서버 기반)

  • OAuth2 인증 서버(Spring Authorization Server) 기반 JWT 발급
    • 인증 서비스는 Spring Authorization Server를 사용해 OAuth2 표준 프로토콜로 JWT(Access Token)를 발급한다.
    • 클라이언트는 /oauth2/token 엔드포인트에 OAuth2 프로토콜에 맞는 요청을 보내 토큰을 발급받는다.
    • JWT는 서버에 등록된 RSA(비대칭키) 등으로 서명되어 발급된다.
  • JWT 발급 과정
    • 클라이언트 등록
      • 인증 서버에 clientId, clientSecret, grant type, redirectUri 등 클라이언트 정보를 등록한다.
    • 토큰 발급 요청
      • 클라이언트는 /oauth2/token 엔드포인트에 grant_type, client_id, client_secret 등 OAuth2 파라미터를 포함해 요청을 보낸다.
      • 예시 (client_credentials 방식)
  • JWT 발급 및 응답
    • 인증 서버는 클라이언트 인증 및 권한 검증 후, JWT(Access Token)를 생성해 응답한다.
    • JWT는 서버의 RSA 개인키로 서명되며, payload에는 sub(사용자), aud(클라이언트), exp(만료), iss(발급자) 등의 정보가 포함된다.
  • JWT 검증
    • 각 마이크로서비스(리소스 서버)는 인증 서버가 제공하는 JWK Set(공개키) 엔드포인트(/.well-known/jwks.json)를 통해 JWT의 서명을 검증한다.
    • Spring Security의 리소스 서버 기능을 사용하면 별도 코드 없이 자동으로 검증된다.
POST /oauth2/token<br>Content-Type: application/x-www-form-urlencoded<br><br>grant_type=client_credentials&client_id=test-client&client_secret=test-secret
{
  "access_token": "eyJraWQiOiJ... (JWT)",
  "token_type": "Bearer",
  "expires_in": 299
}

6. OAuth2 Authorization Server 설정

Spring Authorization Server를 활용해 OAuth2 로그인 흐름을 구성한다. 인가 서버는 토큰 엔드포인트(/oauth2/token)를 제공한다.

@Configuration
class AuthorizationServerConfig {
    @Bean
    fun authorizationServerSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)
        return http.build()
    }
}

7. 로그인 요청과 토큰 발급 흐름

  1. 클라이언트가 /oauth2/token에 사용자 이름과 비밀번호를 POST 요청
  2. 인증 성공 시, JWT Access Token과 Refresh Token 발급
  3. 클라이언트는 이후 요청 시 이 Access Token을 포함해 API 호출
포스트맨으로 토큰을 요청한 결과


인증 서비스는 시스템의 첫 관문이다

인증 서비스는 모든 요청이 통과하는 관문이다.
OAuth2와 JWT를 활용하면 확장성과 보안성을 동시에 확보할 수 있다.
이 구조는 게이트웨이와 연동되어 비인증 요청을 차단하고, 인증된 요청만 백엔드 서비스로 전달하는 기반이 된다.
다음 글에서는 Spring Cloud Gateway를 활용해 인증/비인증 API 라우팅을 어떻게 할 수 있는지 이어서 정리할 예정이다.

이전편 보기
Kotlin과 Spring Boot MSA 프로젝트 구조 설계 및 세팅

참고

자세한 코드는 아래 저장소에서 확인 가능하다.
Github – 저장소

댓글 남기기