본문으로 건너뛰기

고위험 기능을 위한 연령 보증

일부 권한은 특정 관할권에서 활성화되기 전에 확인된 연령이 필요합니다. 예를 들어 브라질(BR)에서 loot-boxes-paid-cosmetic-only, loot-boxes-paid-gameplay-impacting, targeted-ads, profilingverifiedAgeThreshold 18이 필요합니다. 이러한 권한은 기본적으로 비활성화되어 있으며, 연령 요건에 대해 확인된 것으로 간주되는 플랫폼 신호 또는 전용 연령 보증 Challenge(CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCE)를 통해서만 잠금을 해제할 수 있습니다.

이 페이지의 활용 방법

다음 사항을 이해해야 할 때 이 페이지를 사용하세요:

  • 플레이어가 이미 연령 게이트를 통과했음에도 권한이 여전히 비활성화된 이유
  • POST /session/upgrade가 권한을 즉시 활성화하는지 아니면 Challenge를 반환하는지 여부
  • 임계값을 충족하지만 아직 연령을 확인하지 않은 플레이어를 처리하는 방법
  • 원래 임계값 미만의 연령을 주장한 플레이어를 복구하는 방법

확인된 연령 임계값

verifiedAgeThreshold는 단순히 주장하거나 추정된 연령이 아닌 확인된 연령이 필요하다는 것을 의미합니다.

현재 주요 예시:

  • 브라질(BR): loot-boxes-paid-cosmetic-only, loot-boxes-paid-gameplay-impacting, targeted-ads, profiling은 확인된 연령 18이 필요하고, direct-marketing은 확인된 연령 12가 필요합니다

verifiedAgeThreshold가 있는 권한은:

  • managedBy: GUARDIAN이 될 수 없음
  • 플레이어가 충분히 나이가 들었지만 아직 확인이 필요한 경우 managedBy: PLAYER
  • 플레이어가 임계값 미만인 경우 managedBy: PROHIBITED
참고

현재 이 내용은 위 목록의 브라질 권한에 적용됩니다. 추가 관할권이 확인된 연령 요건을 추가할 경우 동일한 권한 모델이 적용됩니다。

권한 상태 로직

권한에 verifiedAgeThreshold가 있는 경우 Permission 객체에 해당 필드가 포함됩니다:

{
"name": "loot-boxes-paid-gameplay-impacting",
"enabled": false,
"managedBy": "PLAYER",
"verifiedAgeThreshold": 18
}
임계값 대비 플레이어 연령연령 확인 여부managedByenabled
임계값 미만해당 없음PROHIBITEDfalse
임계값 이상아니오PLAYERfalse
임계값 이상예, 확인된 플랫폼 신호를 통해PLAYERtrue
임계값 이상예, 연령 보증을 통해PLAYERtrue

임계값 권한은 managedBy: GUARDIAN이 될 수 없습니다. 보호자 동의로는 이를 잠금 해제할 수 없습니다.

세션의 ageVerification

확인된 플랫폼 신호가 처리되거나 연령 보증 Challenge가 완료되면 세션에 ageVerification 객체가 저장됩니다:

{
"ageVerification": {
"verifiedAge": 18,
"platformName": "apple-ios",
"declarationType": "governmentIDChecked",
"verifiedAt": "2026-03-14T00:00:00Z"
}
}

이 확인은 재사용 가능합니다. 세션에 저장되면 이후 동일하거나 낮은 임계값을 가진 권한에 대한 POST /session/upgrade 호출은 일반적으로 새 Challenge 없이 충족될 수 있습니다.

세션 업그레이드 흐름

POST /session/upgrade는 플레이어가 고위험 권한을 즉시 받을 수 있는지 아니면 먼저 확인이 필요한지를 결정하는 엔드포인트입니다.

세션 업그레이드 API

관련 요청 필드:

필드타입설명
platformAgeSignalPlatformAgeSignal임계값을 즉시 충족할 수 있는 플랫폼 신호
optionsobject연령 보증 경험으로 전달되는 옵션
options.facialAgeEstimation.passIfOverinteger얼굴 연령 추정이 통과해야 하는 최소 연령
options.facialAgeEstimation.failIfUnderinteger얼굴 연령 추정이 실패해야 하는 최대 연령
options.redirectUrlstringChallenge 완료 후 리디렉션 대상

요청 예시 (확인된 플랫폼 신호가 권한을 충족하는 경우):

POST /api/v1/session/upgrade

{
"sessionId": "608616da-4fd2-4742-82bf-ec1d4ffd8187",
"requestedPermissions": [
{ "name": "loot-boxes-paid-gameplay-impacting" }
],
"platformAgeSignal": {
"name": "apple-ios",
"ageLow": 18,
"ageHigh": 25,
"declarationType": "governmentIDChecked"
}
}
{
"session": {
"sessionId": "608616da-4fd2-4742-82bf-ec1d4ffd8187",
"permissions": [
{
"name": "loot-boxes-paid-gameplay-impacting",
"enabled": true,
"managedBy": "PLAYER",
"verifiedAgeThreshold": 18
}
],
"ageVerification": {
"verifiedAge": 18,
"platformName": "apple-ios",
"declarationType": "governmentIDChecked",
"verifiedAt": "2026-03-14T00:00:00Z"
}
}
}

요청 예시 (플레이어가 임계값을 충족하지만 아직 연령 보증이 필요한 경우):

POST /api/v1/session/upgrade

{
"sessionId": "608616da-4fd2-4742-82bf-ec1d4ffd8187",
"requestedPermissions": [
{ "name": "loot-boxes-paid-gameplay-impacting" }
],
"options": {
"redirectUrl": "https://mygame.com/callback"
}
}
{
"session": {
"sessionId": "608616da-4fd2-4742-82bf-ec1d4ffd8187",
"permissions": [
{
"name": "loot-boxes-paid-gameplay-impacting",
"enabled": false,
"managedBy": "PLAYER",
"verifiedAgeThreshold": 18
}
]
},
"challenge": {
"challengeId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCE",
"url": "https://family.k-id.com/session/upgrade/age-assurance?token=..."
}
}

결과 예시 (플레이어가 임계값 미만인 경우):

{
"session": {
"sessionId": "608616da-4fd2-4742-82bf-ec1d4ffd8187",
"permissions": [
{
"name": "loot-boxes-paid-gameplay-impacting",
"enabled": false,
"managedBy": "PROHIBITED",
"verifiedAgeThreshold": 18
}
]
}
}

이 경우 플레이어가 해당 권한을 받을 만큼 나이가 들지 않았기 때문에 Challenge가 반환되지 않습니다.

주요 동작:

  • 요청된 모든 권한은 verifiedAgeThreshold가 있거나 없어야 합니다
  • 플레이어가 임계값 미만인 경우 권한은 PROHIBITED로 유지되고 Challenge가 발급되지 않습니다
  • 확인된 플랫폼 신호는 요청된 일부 또는 모든 권한을 즉시 충족할 수 있습니다
  • 세션의 기존 ageVerification도 요청을 충족할 수 있습니다
  • 해결되지 않은 나머지 권한만 연령 보증 Challenge로 전환됩니다

Challenge 결과 처리

Challenge URL은 https://family.k-id.com/session/upgrade/age-assurance?token=...을 가리킵니다.

플레이어가 이 URL을 열면:

  1. 토큰이 파싱되고 유효성이 검사됩니다.
  2. Challenge가 이미 해결된 경우 플레이어는 완료 페이지로 리디렉션됩니다.
  3. 아직 대기 중인 경우 k-ID의 연령 확인 방법(예: 얼굴 연령 추정 또는 ID 문서 스캔)이 포함된 확인 iframe이 표시됩니다.
  4. 완료 시 결과가 통합으로 다시 전달됩니다.

결과를 받는 세 가지 방법이 있습니다:

옵션 1: postMessage 수신

iframe 또는 webview 통합의 경우, family portal이 부모 창에 Challenge.StateChange 메시지를 게시합니다:

{
"eventType": "Challenge.StateChange",
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"productId": "your-product-id",
"status": "PASS"
}
}
경고

DOM postMessage 이벤트는 UI를 업데이트하는 데 유용하지만 권위 있는 소스가 아닙니다. 서버 측 로직에는 웹훅 또는 폴링 엔드포인트를 사용하세요。

옵션 2: GET /challenge/get-status 폴링

GET /api/v1/challenge/get-status?challengeId=a1b2c3d4-e5f6-7890-abcd-ef1234567890

가능한 상태는 PASS, FAIL, PENDING, IN_PROGRESS입니다.

옵션 3: Challenge.StateChange 웹훅 수신

k-ID는 Challenge 상태가 변경될 때마다 구성된 엔드포인트로 Challenge.StateChange 웹훅 이벤트를 게시합니다:

{
"eventType": "Challenge.StateChange",
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"productId": 11472,
"status": "PASS",
"sessionId": "608616da-4fd2-4742-82bf-ec1d4ffd8187"
}
}
필드설명
data.idPOST /session/upgrade가 반환한 challengeId
data.statusPASS, FAIL 또는 IN_PROGRESS
data.sessionIdPASS 시 존재: 새로 고쳐진 세션을 가져오는 데 사용

웹훅은 실시간으로 전달되고 폴링이 필요 없기 때문에 서버 측 처리에 권장되는 방법입니다. 전체 필드 참조 및 상태 수명 주기는 Challenge.StateChange를 참조하세요.

결과 이후

  • PASS 이후, GET /session/get을 가져와 새로 고쳐진 권한을 사용하세요. 임계값 권한이 이제 활성화되고 세션에 ageVerification이 포함되어야 합니다.
  • FAIL 이후, 권한은 비활성화 상태로 유지됩니다. 플레이어는 나중에 POST /session/upgrade를 다시 호출하여 재시도할 수 있습니다.

임계값 미만의 연령을 입력한 플레이어를 위한 복구 흐름

때로는 플레이어가 고위험 권한의 임계값 미만으로 주장된 연령을 입력하여 PROHIBITED 권한을 갖게 되는 경우가 있습니다. 이 경우 세션에 이미 플레이어가 해당 기능을 사용하기에 너무 어리다고 표시되어 있기 때문에 일반적인 session/upgrade 흐름으로는 문제를 해결할 수 없습니다.

이 복구 흐름은 다음을 위한 것입니다:

  • 플레이어 관리 세션
  • 아직 연결된 승인자가 없는 보호자 관리 세션

세션이 보호자 관리이고 이미 승인자가 연결된 경우에는 적합하지 않습니다.

복구 단계

  1. 플레이어를 AgeKit+의 연령 이의 신청으로 안내합니다. 적절한 jurisdictioncriteria와 함께 POST /age-verification/perform-age-appeal를 호출합니다. 반환된 URL을 iframe 또는 webview에 표시하여 플레이어가 연령 확인을 완료할 수 있도록 합니다. 아직 세션을 무효화하지 마세요: 이의 신청이 실패하면 플레이어는 기존 세션을 유지하고 VPC를 다시 거칠 필요가 없습니다.
  2. 연령 이의 신청 결과를 처리합니다. DOM 이벤트, 웹훅 또는 GET /age-verification/get-status를 통해 결과를 수신합니다.
    • 성공 시: 이의 신청은 플레이어의 확인된 연령을 증명하는 verificationId를 생성합니다.
    • 실패 시: 기능은 금지된 상태로 유지됩니다. 플레이어는 원래 주장된 연령으로 유지되고 기존 세션이 보존됩니다.
  3. 세션을 무효화합니다. 성공적인 이의 신청 후, 플레이어가 새로 시작할 수 있도록 서버 측에서 sessionId를 삭제합니다. 세션 무효화 엔드포인트는 향후 릴리스에서 계획되어 있습니다. 지금은 클라이언트 측에서 세션을 제거하는 것으로 충분합니다.
  4. k-ID 신호로 연령 게이트 흐름을 다시 시작합니다. 이의 신청의 verificationIdk-id 플랫폼 신호로 전송합니다.
POST /api/v1/age-gate/check

{
"jurisdiction": "BR",
"platformAgeSignal": {
"name": "k-id",
"verificationId": "<verificationId from age appeal>"
}
}

k-ID는 verificationId에서 확인된 연령을 확인합니다. 확인된 연령이 verifiedAgeThreshold를 충족하거나 초과하면 고위험 권한이 활성화된 상태로 세션이 생성됩니다.

순차적 권한 업그레이드

각 임계값 권한은 독립적으로 추적됩니다:

  • 하나의 권한을 업그레이드해도 다른 권한이 자동으로 업그레이드되지 않습니다
  • 각 권한은 여전히 POST /session/upgrade를 통해 요청되어야 합니다
  • 세션에 ageVerification이 있으면 동일하거나 낮은 임계값을 가진 이후 권한은 종종 다른 Challenge 없이 충족될 수 있습니다