Auth Framework


Auth Framework 코드를 보고 이해하기 위한 글 2026.03.27 Main branch(cbebe6bd229ee296d31cafd9118567d11840a8e7)을 보고 분석

AI의 로드맵 (Notion) 을 보고 순서대로 분석해봄

0. Background


가장 기본이 되는 Framework Backoffice, Partner backoffice, partner auth는 auth-framework을 gradle로 import함.

Auth 구조를 설계하신 분의 공식 문서를 보면, Backoffice, Partner Auth는 거의 비슷한 구조로 공통된 부분을 AuthFramework로 추출하시고,

resource/META-INF.spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports을 통해 PluggableAutoConfiguration 을 import 한다. => 그러면 이 부분이 ComponentScan을 통해 com.bucketplace.auth.pasf package을 전부 import 하면서, auth framework을 backoffice, partner auth에서 다 가져온다.

추가적으로 PluggableAuthConfigurationProperties, OAuthFeatureConfigurationProperties 이 두 프로퍼티도 spring application.yaml에서 가져온다.

1. Auth Plugins / Provider


  • AuthPlugin.kt

    • getDescriptor - Plugin의 Descriptor을 정의. 이것으로 어떤 플러그인 구현체를 선택할지 결정. 그리고 그 구현체가 내부적으로 LDAP / DB을 사용함.
    • verifyAndGetUser - loginId, systemName, password
    • getTwoFactorFeature
    • 이 부분은 Partner auth와 관련된 부분으로 보여 잠시 패스..
  • AuthPluginProvider.kt

    • AuthPlugin 을 Properties 로 가져와서 맵핑해주는 곳.
  • AuthAdminPlugins.kt

    • Admin 의 할 수 있는 역할 수행
    • 우리가 일반적으로 생각할 수 있는 사이트 운영자의 회원관리 정보
  • AuthAdminPluginsProvider.kt

    • 위의 AuthPluginProvider와 동일하게 Properties 을 가져와서 맵핑.
    • Properties 도 동일함.

2. GrpcService


  • GRpc 서비스가 Spring MVC의 Controller라고 이해할 수 있음.
  • path나 req / res는 proto에 정의됨. protos/bauth.proto 에 정의되어 있음. 예를 들어
// com.bucketplace.pasf.bauth.grpc
// BackofficeAuthGrpcService
  
@Component  
@GRpcService  
class BackofficeAuthGrpcService(  
    private val backofficeAuthAuthorityManager: BackofficeAuthAuthorityManager,  
    private val adminService: AdminService,  
    private val userService: UserService,  
    private val userRoleService: UserRoleService,  
    private val backupService: BackupService,  
    private val piiLogger: PIILogger,  
) : BackofficeAuthServiceGrpcKt.BackofficeAuthServiceCoroutineImplBase() {  
	// Login endpoint는 proto에 정의
    override suspend fun login(request: LoginReq): LoginRes {  
        val result =  
            runCatching {  
                loginRes {  
                    accessToken = adminService.login(request.loginId, request.password)  
                }  
            }  
        piiLogger.log(  
            accessType = AccessType.AUTHORIZATION,  
            accessResult = if (result.isSuccess) AccessResult.SUCCESS else AccessResult.FAILURE,  
            target = request.loginId,  
        )  
  
        return result.getOrThrow()  
    }  
    override suspend fun refresh(request: RefreshReq): RefreshRes {  
        return refreshRes {  
            accessToken = adminService.refresh(request.accessToken)  
        }  
    }
    //...
}

// bauth.proto
  
service BackofficeAuthService {  
  // Backoffice Auth 웹 콘솔 사용자 인증  
  rpc Login (LoginReq) returns (LoginRes) {  
    option (google.api.http) = {  
      post: "/v1/admin/login"  
      body: "*"  
    };  
  }  
  
  // Backoffice Auth 웹 콘솔 인증 토큰 갱신  
  rpc Refresh (RefreshReq) returns (RefreshRes) {  
    option (google.api.http) = {  
      post: "/v1/admin/refresh"  
      body: "*"  
    };  
  }
  // ...
}
🔒 Admin 로그인