Skip to content

Scope 레퍼런스

Scope는 공백 구분 문자열입니다 (profile email phone, 콤마 ❌).

표준 Scope

scopeuserinfo 반환 필드비고
profile:basicsub, preferred_name, full_name기본 신원. profile alias 허용, 등록·요청은 profile:basic 권장
emailsub, email, email_verified
phonesub, phone_number별도 동의
addresssub, address, postal_code별도 동의
identity:levelsub, identity_verified_level (0/1/2/3)실명인증 레벨. 신규 앱은 명시 요청 필요 (legacy 앱은 profile에 자동 포함)
openidid_token 발급 + subOIDC 1.0 활성화

identity_verified_level 값: 0 unverified · 1 email_verified · 2 phone_verified · 3 sp_verified. logi는 실명/주민번호 미보유, 정수 플래그만 제공.

커스텀 Scope

네임스페이스 필수 형식 <namespace>:<key> (콜론 1개):

krx_listing:reviewer_role
blog:post.write

User#custom_claims jsonb {namespace: {key: value}} 로 저장, scope 요청 시 id_token/userinfo 에 병합.

앱 등록 시 allowed_scopes

json
{
  "oauth_application": {
    "redirect_uris": ["https://app.example.com/cb"],
    "allowed_scopes": ["profile", "email"]
  }
}

Scope 설정

bash
logi apps edit <id> --add-scope phone
ruby
app = OauthApplication.kept.find_by(name: "your_app")
app.set_scopes!(["openid", "profile", "email", "phone"])

Scope drift 처리

기본 정책은 block 입니다 — 요청 scope 중 allowed_scopes 에 없는 것이 하나라도 있으면 요청 전체가 invalid_scope 로 거절됩니다 (callback-safe redirect). 운영자가 앱 단위로 log_only(미등록 scope silent drop 후 등록된 subset 으로 진행) 또는 alert(log_only + 관리자 알림) 로 완화할 수 있습니다.

케이스기본 (block)log_only / alert
모든 요청 scope 등록됨✅ 진행✅ 진행
일부 미등록invalid_scope⚠️ 미등록 drop, 등록된 것으로 진행
모두 미등록invalid_scopeinvalid_scope
required: true scope 가 effective 에서 누락invalid_scopeinvalid_scope

정책과 무관하게 drift 는 항상 기록됩니다 (로그 + drift record + webhook_url 설정 시 최초 1회 webhook) — block 으로 거절된 경우에도 운영자가 원인을 추적할 수 있습니다.

감지 방법

1. 서버 로그 (client_id 로 grep):

[oauth] scope_drift app_id=4 client_id=logi_xxx policy=block dropped=phone,address kept=profile,email

2. Webhook scope.drift_detected (HMAC-SHA256 서명, (app_id, scope_name) 페어당 1회):

json
{
  "event_type": "scope.drift_detected",
  "application_id": 4,
  "payload": {
    "scope_name": "phone",
    "client_id": "logi_xxx",
    "first_seen_at": "2026-04-29T01:30:00Z",
    "allowed_scopes": ["openid", "profile:basic", "email"]
  }
}

3. 토큰 응답 헤더 X-Logi-Scope-Drift — 최근 7일 내 기록된 drift 이력을 정상 token 응답에 echo. 기본 block 정책에서는 drift 가 포함된 요청 자체가 invalid_scope 로 거절되므로, 이 헤더는 이후의 정상 token 응답(드리프트 없는 요청)에 이력으로 나타납니다:

http
HTTP/1.1 200 OK
X-Logi-Scope-Drift: address,phone
ruby
if drift = res["X-Logi-Scope-Drift"]
  Rails.logger.warn("[logi] scope drift: #{drift}")
end

4. Escalation webhook scope.drift_unresolved — 초기 알림 7일 후에도 drift 진행 중이면 1회 발사.

5. 개발자 대시보드 — Apps 카드에 "Scope drift" 핀, 상세에 drift 테이블.

required 마킹

ruby
app.oauth_application_scopes.create!(oauth_scope: email_scope, required: true)

필수 scope 거부 시 → access_denied.

재인가 UX

사용자가 profile email 동의 이후:

요청 scope동작
동일하거나 축소 (profile)UI 스킵, 즉시 code 발급
확장 (profile email phone)"NEW" 배지 + 추가 동의
Consent revoke 후Consent 화면 재노출

요청 방법

GET /oauth/authorize?...&scope=profile+email+openid&...

공백 구분, URL encoding 시 %20 또는 +. 응답 scope 필드는 실제 부여된 scope 를 echo (사용자가 일부만 동의 가능).

Identity가 제품의 신뢰를 만듭니다.