배경
현재 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 정책에 맞게 정리되어야 합니다.
배경
현재 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에 콜론을 허용하지 않습니다. 따라서 다음 중 하나를 명확히 결정해야 합니다.self_read,self_club_read,self_project_read처럼 정의한다.self:read계열로 정리할 수 있도록 scope 모델/검증 규칙을 조정한다.student:read,club:read,project:read)와 OAuth UserInfo scope가 의미상 충돌하지 않도록 별도 prefix(self,me등)를 사용한다.요구사항
scope파라미터가 없을 때는 클라이언트의 전체 허용 scope가 아니라 기본 UserInfo scope만 요청된 것으로 처리합니다./userinfo응답에 사용자의 동아리 소속 정보를 명확한 필드로 포함합니다./userinfo응답에 사용자의 프로젝트 소속 정보를 명확한 필드로 포함합니다.QueryOauthSessionServiceImpl의 scope 설명 데이터도 함께 정리합니다.완료 조건
scope미입력 authorize 요청이 기본 scope만 요청하도록 변경되어야 합니다./userinfo응답이 부여된 scope에 따라 기본 정보/동아리 정보/프로젝트 정보를 구분해 반환해야 합니다.invalid_scope가 반환되어야 합니다.self:read/self_read표기가 최종 scope 정책에 맞게 정리되어야 합니다.