Skip to content

[oauth] 사용자 정보 OAuth 권한 범위 세분화 및 기본 권한 범위 정책 개선 #393

Description

@snowykte0426

배경

현재 DataGSM OAuth의 UserInfo 흐름은 기본적으로 단일 권한 범위로 사용자 계정/학생 정보를 반환합니다. 이 구조에서는 OAuth로 로그인한 클라이언트가 사용자의 소속 정보(프로젝트, 동아리 등)를 함께 활용하려면 별도로 OpenAPI 기능을 호출해야 하므로, 클라이언트 구현 복잡도와 유지보수 비용이 커집니다.

논의된 방향은 UserInfo에서 사용할 수 있는 OAuth 권한 범위를 세분화하고, 클라이언트가 필요한 사용자 관련 정보를 OAuth scope만으로 명시적으로 요청할 수 있게 만드는 것입니다.

현재 코드 확인 사항

  • StartOauthAuthorizeFlowServiceImpl에서 authorize 요청의 scope가 없으면 client.scopes 전체를 인가 state에 저장합니다.
  • OauthAuthorizeReqDto 문서도 scope 미입력 시 client의 전체 허용 scope를 사용한다고 설명합니다.
  • datagsm-oauth-userinfo/userinfo는 현재 단일 UserInfo 권한으로 보호됩니다.
  • QueryUserInfoServiceImpl은 계정 정보와 학생 정보를 반환합니다. 현재 코드 기준 학생 DTO에는 일부 동아리 요약 정보도 포함될 수 있지만, 프로젝트 등 사용자의 소속 정보를 scope별로 확장하거나 제한하는 구조는 아닙니다.
  • 코드/테스트/문서에는 self:read 예시가 남아 있고, UserInfo 보안 설정은 DATAGSM_APPLICATION_ID:self_read 형태의 권한을 사용하고 있어 외부 노출 scope 이름 정책도 함께 정리할 필요가 있습니다.

제안

UserInfo 관련 OAuth scope를 단일 self:read에서 목적별 scope로 분리합니다.

예시 후보:

  • 기본 사용자/학생 프로필 조회: self:read, me:read, user:read 중 결정
  • 내 동아리 소속 조회: self:club:read, me:club:read, club:read 중 결정
  • 내 프로젝트 소속 조회: self:project:read, me:project:read, project:read 중 결정

다만 현재 OAuth scope 모델은 실질적으로 <applicationId>:<scopeName> 형태이며, 관리 DTO에서는 scopeName에 콜론을 허용하지 않습니다. 따라서 다음 중 하나를 명확히 결정해야 합니다.

  • 기존 모델을 유지하고 DataGSM first-party scopeName을 self_read, self_club_read, self_project_read처럼 정의한다.
  • 외부에 노출되는 scope 명명 규칙을 self:read 계열로 정리할 수 있도록 scope 모델/검증 규칙을 조정한다.
  • OpenAPI API Key scope(student:read, club:read, project:read)와 OAuth UserInfo scope가 의미상 충돌하지 않도록 별도 prefix(self, me 등)를 사용한다.

요구사항

  • authorize 요청에 scope 파라미터가 없을 때는 클라이언트의 전체 허용 scope가 아니라 기본 UserInfo scope만 요청된 것으로 처리합니다.
  • 기본 UserInfo scope는 기존 동작과 호환되도록 계정/학생 기본 정보를 반환합니다.
  • 동아리 scope가 부여된 경우 /userinfo 응답에 사용자의 동아리 소속 정보를 명확한 필드로 포함합니다.
  • 프로젝트 scope가 부여된 경우 /userinfo 응답에 사용자의 프로젝트 소속 정보를 명확한 필드로 포함합니다.
  • access token/refresh token의 scope 저장 및 down-scope 동작은 기존 OAuth 흐름과 일관되게 유지합니다.
  • 동의 화면에서 scope별 설명이 사용자에게 구분되어 표시되도록 QueryOauthSessionServiceImpl의 scope 설명 데이터도 함께 정리합니다.
  • 기존 클라이언트와의 호환성 영향, migration 방식, scope 이름 변경 여부를 구현 전에 결정합니다.

완료 조건

  • UserInfo용 first-party OAuth scope 이름과 저장 모델이 확정되어 문서화되어야 합니다.
  • scope 미입력 authorize 요청이 기본 scope만 요청하도록 변경되어야 합니다.
  • /userinfo 응답이 부여된 scope에 따라 기본 정보/동아리 정보/프로젝트 정보를 구분해 반환해야 합니다.
  • 허용되지 않은 scope 요청 시 기존처럼 invalid_scope가 반환되어야 합니다.
  • authorization code, token, refresh token, userinfo 흐름에 대한 Kotest 테스트가 추가 또는 수정되어야 합니다.
  • OpenAPI/Swagger 예시의 self:read/self_read 표기가 최종 scope 정책에 맞게 정리되어야 합니다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Fields

    No fields configured for Feature.

    Projects

    Status
    계획됨

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions