ID 공급업체 측에서 FedCM을 사용하여 ID 솔루션 구현

FedCM 구현에는 ID 공급업체 (IdP)신뢰 당사자 (RP) 모두에 관한 여러 핵심 단계가 포함되어 있습니다. 문서를 참고하여 RP 측에서 FedCM을 구현하는 방법을 알아보세요.

IdPs는 FedCM을 구현하기 위해 다음 단계를 완료해야 합니다.

잘 알려진 파일 만들기

추적 광고주가 API를 악용하는 것을 방지하려면 IdP의 eTLD+1에 있는 /.well-known/web-identity에서 널 파일을 제공해야 합니다.

잘 알려진 파일에는 다음 속성이 포함될 수 있습니다.

속성 필수 설명
provider_urls 필수 IdP 구성 파일 경로 배열입니다. accounts_endpointlogin_url가 지정된 경우 무시되지만 여전히 필요합니다.
accounts_endpoint 권장, login_url 필요
계정 엔드포인트의 URL입니다. 이렇게 하면 각 구성 파일이 동일한 login_urlaccounts_endpoint URL을 사용하는 한 여러 구성을 지원할 수 있습니다.

참고: 이 매개변수는 Chrome 132부터 지원됩니다.
login_url 권장, accounts_endpoint 필요 사용자가 IdP에 로그인할 수 있는 로그인 페이지 URL입니다. 이렇게 하면 각 구성 파일에서 동일한 login_urlaccounts_endpoint를 사용하는 한 여러 구성을 지원할 수 있습니다.

참고: 이 매개변수는 Chrome 132 이상에서 지원됩니다.

예를 들어 IdP 엔드포인트가 https://accounts.idp.example/ 아래에서 제공되는 경우 https://idp.example/.well-known/web-identity에서 IdP 구성 파일과 함께 잘 알려진 파일을 제공해야 합니다. 다음은 잘 알려진 파일 콘텐츠의 예입니다.

  {
    "provider_urls": ["https://accounts.idp.example/config.json"]
  }

IdP는 잘 알려진 파일에 accounts_endpointlogin_url를 지정하여 IdP의 여러 구성 파일을 수용할 수 있습니다.
이 기능은 다음과 같은 경우에 유용할 수 있습니다.

  • IdP는 여러 가지 테스트 및 프로덕션 구성을 지원해야 합니다.
  • IdP는 리전별로 서로 다른 구성 (예: eu-idp.exampleus-idp.example)을 지원해야 합니다.

여러 구성을 지원하려면 (예: 테스트 환경과 프로덕션 환경을 구분) IdP에서 accounts_endpointlogin_url를 지정해야 합니다.

  {
    // This property is required, but will be ignored when IdP supports
    // multiple configs (when `accounts_endpoint` and `login_url` are
    // specified), as long as `accounts_endpoint` and `login_url` in
    // that config file match those in the well-known file.
    "provider_urls": [ "https://idp.example/fedcm.json" ],

    // Specify accounts_endpoint and login_url properties to support
    // multiple config files.
    // Note: The accounts_endpoint and login_url must be identical
    // across all config files. Otherwise,
    // the configurations won't be supported.
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }

IdP 구성 파일 및 엔드포인트 만들기

IdP 구성 파일은 브라우저에 필요한 엔드포인트 목록을 제공합니다. IdP는 하나 이상의 구성 파일과 필요한 엔드포인트 및 URL을 호스팅해야 합니다. 모든 JSON 응답은 application/json 콘텐츠 유형으로 제공되어야 합니다.

구성 파일의 URL은 RP에서 실행된 navigator.credentials.get() 호출에 제공된 값에 따라 결정됩니다.

  const credential = await navigator.credentials.get({
    identity: {
      context: 'signup',
      providers: [{
        configURL: 'https://accounts.idp.example/config.json',
        clientId: '********',
        nonce: '******'
      }]
    }
  });
  const { token } = credential;

RP는 구성 파일의 URL을 FedCM API 호출에 전달하여 사용자가 로그인할 수 있도록 합니다.

  // Executed on RP's side:
  const credential = await navigator.credentials.get({
    identity: {
      context: 'signup',
      providers: [{
        // To allow users to sign in with an IdP using FedCM, RP specifies the IdP's config file URL:
        configURL: 'https://accounts.idp.example/fedcm.json',
        clientId: '********',
  });
  const { token } = credential;

브라우저는 Origin 헤더 또는 Referer 헤더가 없는 GET 요청으로 구성 파일을 가져옵니다. 요청에 쿠키가 없으며 리디렉션을 따르지 않습니다. 이렇게 하면 IdP가 요청한 사용자와 연결하려는 RP를 알 수 없게 됩니다. 예를 들면 다음과 같습니다.

  GET /config.json HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Sec-Fetch-Dest: webidentity

IdP는 JSON으로 응답하는 구성 엔드포인트를 구현해야 합니다. JSON에는 다음 속성이 포함됩니다.

속성 설명
accounts_endpoint(필수) 계정 엔드포인트의 URL입니다.
accounts.include (선택사항) 이 구성 파일을 사용할 때 반환해야 하는 계정을 결정하는 맞춤 계정 라벨 문자열입니다(예: "accounts": {"include": "developer"}).
IdP는 다음과 같이 맞춤 계정 라벨을 구현할 수 있습니다.

예를 들어 IdP는 "accounts": {"include": "developer"}가 지정된 "https://idp.example/developer-config.json" 구성 파일을 구현합니다. IdP는 계정 엔드포인트에서 labels 매개변수를 사용하여 일부 계정을 "developer" 라벨로 표시합니다. RP가 "https://idp.example/developer-config.json" 구성 파일이 지정된 navigator.credentials.get()를 호출하면 "developer" 라벨이 있는 계정만 반환됩니다.

참고: 맞춤 계정 라벨은 Chrome 132부터 지원됩니다.
client_metadata_endpoint(선택사항) 클라이언트 메타데이터 엔드포인트의 URL입니다.
id_assertion_endpoint(필수) ID 어설션 엔드포인트의 URL입니다.
disconnect(선택사항) 연결 해제 엔드포인트의 URL입니다.
login_url(필수) 사용자가 IdP에 로그인할 수 있는 로그인 페이지 URL입니다.
branding(선택사항) 다양한 브랜딩 옵션을 포함하는 객체입니다.
branding.background_color(선택사항) '계속...' 버튼의 배경 색상을 설정하는 브랜딩 옵션입니다. 관련 CSS 문법(예: hex-color, hsl(), rgb(), named-color)을 사용합니다.
branding.color(선택사항) '계속...' 버튼의 텍스트 색상을 설정하는 브랜딩 옵션입니다. 관련 CSS 문법(예: hex-color, hsl(), rgb(), named-color)을 사용합니다.
branding.icons(선택사항) 아이콘 객체의 배열입니다. 이러한 아이콘은 로그인 대화상자에 표시됩니다. 아이콘 객체에는 두 가지 매개변수가 있습니다.
  • url (필수): 아이콘 이미지의 URL입니다. SVG 이미지는 지원되지 않습니다.
  • size (선택사항): 애플리케이션에서 정사각형 및 단일 해상도로 가정하는 아이콘 크기입니다. 이 숫자는 수동 모드에서 25px 이상, 활성 모드에서 40px 이상이어야 합니다.
modes FedCM UI가 다양한 모드로 표시되는 방식에 관한 사양을 포함하는 객체입니다.
  • active
  • passive
modes.active 특정 모드에서 FedCM 동작을 맞춤설정할 수 있는 속성이 포함된 객체입니다. modes.activemodes.passive 모두 다음 매개변수를 포함할 수 있습니다.
  • supports_use_other_account: 사용자가 현재 로그인한 계정과 다른 계정으로 로그인할 수 있는지 여부를 지정하는 불리언입니다 (IdP에서 여러 계정을 지원하는 경우).

참고: 다른 계정 사용 기능과 활성 모드는 Chrome 132부터 지원됩니다.
modes.passive

다음은 IdP의 응답 본문 예입니다.

  {
    "accounts_endpoint": "/accounts.example",
    "client_metadata_endpoint": "/client_metadata.example",
    "id_assertion_endpoint": "/assertion.example",
    "disconnect_endpoint": "/disconnect.example",
    "login_url": "/login",
    // When RPs use this config file, only those accounts will be
    //returned that include `developer` label in the accounts endpoint.
    "accounts": {"include": "developer"},
    "modes": {
        "active": {
          "supports_use_other_account": true,
        }
    },
    "branding": {
      "background_color": "green",
      "color": "#FFEEAA",
      "icons": [{
        "url": "https://idp.example/icon.ico",
        "size": 25
      }]
    }
  }

브라우저가 구성 파일을 가져오면 후속 요청을 IdP 엔드포인트로 전송합니다.

IdP 엔드포인트
IDP 엔드포인트

다른 계정 사용

IdP에서 여러 계정을 지원하거나 기존 계정을 대체하는 경우 사용자는 현재 로그인한 계정과 다른 계정으로 전환할 수 있습니다.

사용자가 다른 계정을 선택할 수 있도록 하려면 IdP가 구성 파일에서 이 기능을 지정해야 합니다.

  {
    "accounts_endpoint" : "/accounts.example",
    "modes": {
      "active": {
        // Allow the user to choose other account (false by default)
        "supports_use_other_account": true
      }
      // "passive" mode can be configured separately
    }
  }

계정 엔드포인트

IdP의 계정 엔드포인트는 사용자가 IdP에 로그인한 계정 목록을 반환합니다. IdP에서 여러 계정을 지원하는 경우 이 엔드포인트는 로그인한 모든 계정을 반환합니다.

브라우저가 SameSite=None와 함께 쿠키가 포함된 GET 요청을 전송하지만 client_id 매개변수, Origin 헤더 또는 Referer 헤더는 포함하지 않습니다. 이렇게 하면 IdP가 사용자가 로그인하려는 RP를 알 수 없게 됩니다. 예를 들면 다음과 같습니다.

  GET /accounts.example HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

서버는 요청을 수신하면 다음을 실행해야 합니다.

  1. 요청에 Sec-Fetch-Dest: webidentity HTTP 헤더가 포함되어 있는지 확인합니다.
  2. 세션 쿠키를 이미 로그인한 계정의 ID와 일치시킵니다.
  3. 계정 목록으로 응답합니다.

브라우저는 다음 속성이 있는 계정 정보 배열이 포함된 accounts 속성이 포함된 JSON 응답을 예상합니다.

속성 설명
id(필수) 사용자의 고유 ID입니다.
name(필수) 사용자의 이름 및 성입니다.
email(필수) 사용자의 이메일 주소입니다.
given_name(선택사항) 사용자의 이름입니다.
picture(선택사항) 사용자 아바타 이미지의 URL입니다.
approved_clients(선택사항) 사용자가 등록한 RP 클라이언트 ID 배열입니다.
login_hints(선택사항) IdP에서 계정을 지정하기 위해 지원하는 모든 필터 유형의 배열입니다. RP는 loginHint 속성으로 navigator.credentials.get()를 호출하여 지정된 계정을 선택적으로 표시할 수 있습니다.
domain_hints(선택사항) 계정이 연결된 모든 도메인의 배열입니다. RP는 domainHint 속성으로 navigator.credentials.get()를 호출하여 계정을 필터링할 수 있습니다.
labels(선택사항) 계정이 연결된 맞춤 계정 라벨 문자열 배열입니다.
IdP는 다음과 같이 맞춤 계정 라벨을 구현할 수 있습니다.
  • labels 매개변수를 사용하여 계정 엔드포인트에서 계정 라벨을 지정합니다.
  • 각 라벨에 대해 구성 파일을 만듭니다.

예를 들어 IdP는 "accounts": {"include": "developer"}가 지정된 https://idp.example/developer-config.json 구성 파일을 구현합니다. IdP는 계정 엔드포인트에서 labels 매개변수를 사용하여 일부 계정을 "developer" 라벨로 표시합니다. RP가 https://idp.example/developer-config.json 구성 파일이 지정된 navigator.credentials.get()를 호출하면 "developer" 라벨이 있는 계정만 반환됩니다.

맞춤 계정 라벨은 IdP 서버에서 완전히 유지 관리되고 RP는 사용할 구성 파일만 지정한다는 점에서 로그인 힌트 및 도메인 힌트와 다릅니다.

참고: 맞춤 계정 라벨은 Chrome 132부터 지원됩니다.

응답 본문 예시:

  {
    "accounts": [{
      "id": "1234",
      "given_name": "John",
      "name": "John Doe",
      "email": "john_doe@idp.example",
      "picture": "https://idp.example/profile/123",
      // Ids of those RPs where this account can be used
      "approved_clients": ["123", "456", "789"],
      // This account has 'login_hints`. When an RP calls `navigator.credentials.get()`
      // with a `loginHint` value specified, for example, `exampleHint`, only those
      // accounts will be shown to the user whose 'login_hints' array contains the `exampleHint`.
      "login_hints": ["demo1", "exampleHint"],
      // This account is labelled. IdP can implement a specific config file for a
      // label, for example, `https://idp.example/developer-config.json`. Like that
      // RPs can filter out accounts by calling `navigator.credentials.get()` with
      // `https://idp.example/developer-config.json` config file.
      "labels": ["hr", "developer"]
    }, {
      "id": "5678",
      "given_name": "Johnny",
      "name": "Johnny",
      "email": "johnny@idp.example",
      "picture": "https://idp.example/profile/456",
      "approved_clients": ["abc", "def", "ghi"],
      "login_hints": ["demo2"],
      "domain_hints": ["@domain.example"]
    }]
  }

사용자가 로그인하지 않은 경우 HTTP 401 (승인되지 않음)으로 응답합니다.

반환된 계정 목록은 브라우저에서 사용하며 RP에서는 사용할 수 없습니다.

ID 어설션 엔드포인트

IdP의 ID 어설션 엔드포인트는 로그인한 사용자의 어설션을 반환합니다. 사용자가 navigator.credentials.get() 호출을 사용하여 RP 웹사이트에 로그인하면 브라우저는 SameSite=None 쿠키와 콘텐츠 유형이 application/x-www-form-urlencodedPOST 요청을 다음 정보와 함께 이 엔드포인트로 전송합니다.

속성 설명
client_id(필수) RP의 클라이언트 식별자입니다.
account_id(필수) 로그인하는 사용자의 고유 ID입니다.
disclosure_text_shown 불리언이 아닌 "true" 또는 "false" 문자열을 반환합니다. 다음의 경우 결과는 "false"입니다.
  • RP의 클라이언트 ID가 계정 엔드포인트의 응답에 포함된 approved_clients 속성 목록에 포함되어 공개 텍스트가 표시되지 않은 경우
  • 브라우저에서 approved_clients가 없는 상태에서 이전에 가입 순간을 감지했기 때문에 정보 공개 텍스트가 표시되지 않은 경우
  • fields 매개변수에 세 필드('이름', '이메일', '사진') 중 하나 이상이 포함되지 않은 경우(예: fields=[ ] 또는 fields=['name', 'picture']). 이는 공개 문자열에 항상 세 필드가 모두 포함되기를 기대하는 이전 IdP 구현과의 하위 호환성을 위해 필요합니다.
is_auto_selected RP에서 자동 재인증이 실행되면 is_auto_selected"true"을 나타냅니다. 그 외의 경우에는 "false"입니다. 이렇게 하면 더 많은 보안 관련 기능을 지원하는 데 도움이 됩니다. 예를 들어 인증 시 명시적인 사용자 중재가 필요한 더 높은 보안 등급을 선호하는 사용자도 있습니다. IdP가 이러한 미디에이션 없이 토큰 요청을 수신하면 요청을 다르게 처리할 수 있습니다. 예를 들어 RP가 mediation: required를 사용하여 FedCM API를 다시 호출할 수 있도록 오류 코드를 반환합니다.
fields(선택사항) RP가 IdP와 공유해야 하는 사용자 정보 ('name', 'email', 'picture')를 지정하는 문자열 배열입니다.
browser는 다음 예와 같이 POST 요청에 지정된 필드를 나열하는 fields, disclosure_text_shown, disclosure_shown_for를 전송합니다.

참고: Fields 매개변수는 Chrome 132부터 지원됩니다.
params(선택사항) 맞춤 키-값 매개변수를 추가로 지정할 수 있는 유효한 JSON 객체입니다. 예를 들면 다음과 같습니다.
  • scope: RP가 요청해야 하는 추가 권한이 포함된 문자열 값입니다(예: "drive.readonly calendar.readonly").
  • nonce: 이 특정 요청에 대한 응답이 발행되도록 RP에서 제공한 임의의 문자열입니다. 재전송 공격을 방지합니다.
  • 기타 맞춤 키-값 매개변수
브라우저가 POST 요청을 전송하면 params 값이 JSON으로 직렬화된 후 퍼센트로 인코딩됩니다.

참고: Parameters API는 Chrome 132 이상에서 지원됩니다.

HTTP 헤더 예:

  POST /assertion.example HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

  // disclosure_text_shown is set to 'false', as the 'name' field value is missing in 'fields' array
  // params value is serialized to JSON and then percent-encoded.
  account_id=123&client_id=client1234&disclosure_text_shown=false&is_auto_selected=true&params=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&disclosure_text_shown=true&fields=email,picture&disclosure_shown_for=email,picture

서버는 요청을 수신하면 다음을 실행해야 합니다.

  1. CORS (교차 출처 리소스 공유)를 사용하여 요청에 응답합니다.
  2. 요청에 Sec-Fetch-Dest: webidentity HTTP 헤더가 포함되어 있는지 확인합니다.
  3. Origin 헤더를 client_id에 의해 결정된 RP 출처와 일치시킵니다. 일치하지 않으면 거부합니다.
  4. account_id를 이미 로그인한 계정의 ID와 일치시킵니다. 일치하지 않으면 거부합니다.
  5. 토큰으로 응답합니다. 요청이 거부되면 오류 응답으로 응답합니다.

IdP는 토큰을 발급하는 방법을 결정할 수 있습니다. 일반적으로 RP가 토큰의 진위를 확인할 수 있도록 계정 ID, 클라이언트 ID, 발급자 출처, nonce와 같은 정보로 서명됩니다.

브라우저는 다음 속성이 포함된 JSON 응답을 예상합니다.

속성 설명
token 토큰은 인증에 관한 클레임을 포함하는 문자열입니다.
continue_on 다단계 로그인 흐름을 사용 설정하는 리디렉션 URL입니다.

반환된 토큰은 RP가 인증을 검증할 수 있도록 브라우저에서 RP에 전달됩니다.

  {
    // IdP can respond with a token to authenticate the user
    "token": "***********"
  }

계속 진행 기능

IdP는 ID 어설션 엔드포인트 응답에 리디렉션 URL을 제공하여 다단계 로그인 흐름을 사용 설정할 수 있습니다. 이는 IdP가 추가 정보나 권한을 요청해야 하는 경우에 유용합니다. 예를 들면 다음과 같습니다.

  • 사용자의 서버 측 리소스에 액세스할 수 있는 권한입니다.
  • 연락처 정보가 최신 상태인지 확인
  • 자녀 보호 기능을 클릭합니다.

ID 어설션 엔드포인트는 ID 어설션 엔드포인트의 절대 경로 또는 상대 경로가 포함된 continue_on 속성을 반환할 수 있습니다.

  {
    // In the id_assertion_endpoint, instead of returning a typical
    // "token" response, the IdP decides that it needs the user to
    // continue on a popup window:
    "continue_on": "https://idp.example/continue_on_url"
  }

응답에 continue_on 매개변수가 포함된 경우 새 팝업 창이 열리고 사용자를 지정된 경로로 이동합니다. 사용자가 continue_on 페이지와 상호작용한 후에는 IdP가 원래 navigator.credentials.get() 호출의 약속을 확인할 수 있도록 토큰을 인수로 전달하여 IdentityProvider.resolve()를 호출해야 합니다.

  document.getElementById('example-button').addEventListener('click', async () => {
    let accessToken = await fetch('/generate_access_token.cgi');
    // Closes the window and resolves the promise (that is still hanging
    // in the relying party's renderer) with the value that is passed.
    IdentityProvider.resolve(accessToken);
  });

그러면 브라우저에서 팝업을 자동으로 닫고 API 호출자에게 토큰을 반환합니다. 상위 창 (RP)과 팝업 창 (IdP)이 통신하는 유일한 방법은 일회성 IdentityProvider.resolve() 호출입니다.
사용자가 요청을 거부하면 IdP는 IdentityProvider.close()를 호출하여 창을 닫을 수 있습니다.

  IdentityProvider.close();

Continuation API가 작동하려면 명시적인 사용자 상호작용 (클릭)이 필요합니다. Continuation API가 다양한 미디에이션 모드에서 작동하는 방식은 다음과 같습니다.

  • 패시브 모드:
    • mediation: 'optional' (기본값): Continuation API는 페이지 또는 FedCM UI의 버튼을 클릭하는 등의 사용자 동작으로만 작동합니다. 사용자 동작 없이 자동 재인증이 트리거되면 팝업 창이 열리지 않고 약속이 거부됩니다.
    • mediation: 'required': 항상 사용자에게 상호작용을 요청하므로 Continuation API가 항상 작동합니다.
  • 활성 모드:
    • 사용자 활성화는 항상 필요합니다. Continuation API는 호환됩니다.

어떤 이유로든 사용자가 팝업에서 계정을 변경한 경우 (예: IdP에서 '다른 계정 사용' 기능을 제공하거나 위임 케이스인 경우) resolve 호출은 다음과 같은 작업을 허용하는 선택적 두 번째 인수를 사용합니다.

  IdentityProvider.resolve(token, {accountId: '1234');

오류 응답 반환

id_assertion_endpoint는 두 가지 선택사항 필드가 있는 'error' 응답을 반환할 수도 있습니다.

  • code: IdP는 OAuth 2.0 지정 오류 목록(invalid_request, unauthorized_client, access_denied, server_error, temporarily_unavailable)에서 알려진 오류 중 하나를 선택하거나 임의의 문자열을 사용할 수 있습니다. 후자인 경우 Chrome은 일반 오류 메시지로 오류 UI를 렌더링하고 코드를 RP에 전달합니다.
  • url: 사용자에게 오류에 관한 추가 정보를 제공하기 위해 오류에 관한 정보가 포함된 사람이 읽을 수 있는 웹페이지를 식별합니다. 이 필드는 브라우저가 내장 UI에서 풍부한 오류 메시지를 제공할 수 없으므로 사용자에게 유용합니다. 예: 다음 단계 링크 또는 고객 서비스 연락처 정보 사용자가 오류 세부정보 및 해결 방법을 자세히 알아보려면 브라우저 UI에서 제공된 페이지를 방문하면 됩니다. URL은 IdP configURL와 동일한 사이트여야 합니다.
  // id_assertion_endpoint response
  {
    "error" : {
      "code": "access_denied",
      "url" : "https://idp.example/error?type=access_denied"
    }
  }

맞춤 계정 라벨

맞춤 계정 라벨을 사용하면 IdP가 라벨로 사용자 계정에 주석을 달 수 있으며 RP는 특정 라벨의 configURL를 지정하여 특정 라벨이 있는 계정만 가져오도록 선택할 수 있습니다. 이는 RP가 특정 기준에 따라 계정을 필터링해야 하는 경우에 유용합니다. 예를 들어 "developer" 또는 "hr"와 같은 역할별 계정만 표시하는 경우입니다.

navigator.credentials.get() 호출에서 도메인 힌트로그인 힌트 기능을 지정하여 유사한 필터링을 할 수 있습니다. 하지만 맞춤 계정 라벨은 구성 파일을 지정하여 사용자를 필터링할 수 있습니다. 이는 여러 configURL이 사용되는 경우에 특히 유용합니다. 맞춤 계정 라벨은 로그인 또는 도메인 힌트와 같이 RP가 아닌 IdP 서버에서 제공된다는 점에서 다릅니다.

"developer""hr" 계정을 구분하려는 IdP를 생각해 보세요. 이를 위해 IdP는 "developer""hr"의 두 가지 configURL을 각각 지원해야 합니다.

  • 개발자 구성 파일 https://idp.example/developer/fedcm.json에는 "developer" 라벨이 있고 엔터프라이즈 구성 파일 https://idp.example/hr/fedcm.json에는 다음과 같이 "hr" 라벨이 있습니다.
  // The developer config file at `https://idp.example/developer/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "accounts": {
      // Account label
      "include": "developer"
    }
  }
  // The hr config file at `https://idp.example/hr/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "accounts": {
      // Account label
      "include": "hr"
    }
  }
  • 이러한 설정으로 well-known 파일에는 여러 configURL을 허용하기 위해 accounts_endpointlogin_url가 포함되어야 합니다.
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • 공통 IdP 계정 엔드포인트 (이 예에서는 https://idp.example/accounts)는 각 계정에 할당된 라벨이 배열에 포함된 labels 속성이 포함된 계정 목록을 반환합니다.
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "labels": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "labels": ["hr"]
    }]
  }

RP가 "hr" 사용자의 로그인을 허용하려면 navigator.credentials.get() 호출에서 configURL https://idp.example/hr/fedcm.json을 지정하면 됩니다.

  let { token } = await navigator.credentials.get({
    identity: {
      providers: [{
        clientId: '1234',
        nonce: '234234',
        configURL: 'https://idp.example/hr/fedcm.json',
      },
    }
  });

따라서 사용자는 4567의 계정 ID만 사용하여 로그인할 수 있습니다. 123의 계정 ID는 브라우저에 의해 자동으로 숨겨지므로 사용자가 이 사이트의 IdP에서 지원하지 않는 계정을 제공받지 못합니다.

  • 라벨은 문자열입니다. labels 배열 또는 include 필드에 문자열이 아닌 항목이 포함된 경우 무시됩니다.
  • configURL에 라벨이 지정되지 않으면 모든 계정이 FedCM 계정 선택 도구에 표시됩니다.
  • 계정에 라벨이 지정되지 않은 경우 configURL에서도 라벨을 지정하지 않은 경우에만 계정 선택 도구에 표시됩니다.
  • 패시브 모드에서 요청된 라벨과 일치하는 계정이 없는 경우 (도메인 힌트 기능과 유사) FedCM 대화상자에 로그인 메시지가 표시되어 사용자가 IdP 계정에 로그인할 수 있습니다. 활성 모드의 경우 로그인 팝업 창이 직접 열립니다.

엔드포인트 연결 해제

IdentityCredential.disconnect()를 호출하면 브라우저는 SameSite=None가 포함된 쿠키와 콘텐츠 유형이 application/x-www-form-urlencoded인 교차 출처 POST 요청을 다음 정보와 함께 이 연결 해제 엔드포인트로 전송합니다.

속성 설명
account_hint IdP 계정에 대한 힌트입니다.
client_id RP의 클라이언트 식별자입니다.
  POST /disconnect.example HTTP/1.1
  Host: idp.example
  Origin: rp.example
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x123
  Sec-Fetch-Dest: webidentity

  account_hint=account456&client_id=rp123

서버는 요청을 수신하면 다음을 실행해야 합니다.

  1. CORS (교차 출처 리소스 공유)를 사용하여 요청에 응답합니다.
  2. 요청에 Sec-Fetch-Dest: webidentity HTTP 헤더가 포함되어 있는지 확인합니다.
  3. Origin 헤더를 client_id에 의해 결정된 RP 출처와 일치시킵니다. 일치하지 않으면 거부합니다.
  4. account_hint를 이미 로그인한 계정의 ID와 일치시킵니다.
  5. RP에서 사용자 계정의 연결을 해제합니다.
  6. 식별된 사용자 계정 정보를 JSON 형식으로 브라우저에 응답합니다.

응답 JSON 페이로드의 예는 다음과 같습니다.

  {
    "account_id": "account456"
  }

대신 IdP에서 브라우저가 RP와 연결된 모든 계정의 연결을 해제하기를 원하는 경우 계정 ID와 일치하지 않는 문자열(예: "*")을 전달합니다.

클라이언트 메타데이터 엔드포인트

IdP의 클라이언트 메타데이터 엔드포인트는 RP의 개인정보처리방침, 서비스 약관, 로고 아이콘과 같은 신뢰 당사자의 메타데이터를 반환합니다. RP는 개인정보처리방침 및 서비스 약관 링크를 IdP에 사전에 제공해야 합니다. 이러한 링크는 사용자가 아직 IdP로 RP에 등록하지 않은 경우 로그인 대화상자에 표시됩니다.

브라우저는 쿠키 없이 client_id navigator.credentials.get를 사용하여 GET 요청을 보냅니다. 예를 들면 다음과 같습니다.

  GET /client_metadata.example?client_id=1234 HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Accept: application/json
  Sec-Fetch-Dest: webidentity

서버는 요청을 수신하면 다음을 실행해야 합니다.

  1. client_id의 RP를 확인합니다.
  2. 클라이언트 메타데이터로 응답합니다.

클라이언트 메타데이터 엔드포인트의 속성에는 다음이 포함됩니다.

속성 설명
privacy_policy_url(선택사항) RP 개인정보처리방침 URL
terms_of_service_url(선택사항) RP 서비스 약관 URL입니다.
icons(선택사항) 객체 배열(예: [{ "url": "https://rp.example/rp-icon.ico", "size": 40}])

브라우저는 엔드포인트에서 JSON 응답을 예상합니다.

  {
    "privacy_policy_url": "https://rp.example/privacy_policy.html",
    "terms_of_service_url": "https://rp.example/terms_of_service.html",
    "icons": [{
          "url": "https://rp.example/rp-icon.ico",
          "size": 40
      }]
  }

반환된 클라이언트 메타데이터는 브라우저에서 사용하며 RP에서는 사용할 수 없습니다.

로그인 URL

이 엔드포인트는 사용자가 IdP에 로그인할 수 있도록 하는 데 사용됩니다.

로그인 상태 API를 사용하면 IdP는 사용자의 로그인 상태를 브라우저에 알려야 합니다. 그러나 세션이 만료되는 경우와 같이 상태가 동기화되지 않을 수 있습니다. 이러한 시나리오에서 브라우저는 idp 구성 파일login_url로 지정된 로그인 페이지 URL을 통해 사용자가 IdP에 동적으로 로그인하도록 허용할 수 있습니다.

FedCM 대화상자에는 다음 이미지와 같이 로그인을 제안하는 메시지가 표시됩니다.

A
IdP에 로그인하라는 제안을 하는 FedCM 대화상자

사용자가 계속 버튼을 클릭하면 브라우저에서 IdP 로그인 페이지의 팝업 창을 엽니다.

FedCM 대화상자 예시
IdP 로그인 버튼을 클릭한 후 표시되는 대화상자 예시입니다.

대화상자는 퍼스트 파티 쿠키가 있는 일반 브라우저 창입니다. 대화상자 내에서 발생하는 모든 상황은 IdP에 따라 다르며 RP 페이지에 교차 출처 통신 요청을 실행할 수 있는 창 핸들은 없습니다. 사용자가 로그인하면 IdP는 다음을 실행해야 합니다.

  • Set-Login: logged-in 헤더를 전송하거나 navigator.login.setStatus("logged-in") API를 호출하여 사용자가 로그인했음을 브라우저에 알립니다.
  • IdentityProvider.close()를 호출하여 대화상자를 닫습니다.
사용자가 FedCM을 사용하여 IdP에 로그인한 후 RP에 로그인합니다.

브라우저에 사용자의 로그인 상태 알림

로그인 상태 API는 웹사이트, 특히 IdP가 브라우저에 IdP의 사용자 로그인 상태를 알리는 메커니즘입니다. 이 API를 사용하면 브라우저가 IDP에 대한 불필요한 요청을 줄이고 잠재적인 타이밍 공격을 완화할 수 있습니다.

IdP는 사용자가 IdP에 로그인했거나 모든 IdP 계정에서 로그아웃했을 때 HTTP 헤더를 전송하거나 JavaScript API를 호출하여 사용자의 로그인 상태를 브라우저에 전달할 수 있습니다. 각 IdP (구성 URL로 식별됨)의 경우 브라우저는 로그인 상태를 나타내는 3-상태 변수를 유지하며 가능한 값은 다음과 같습니다.

  • logged-in
  • logged-out
  • unknown(기본)
로그인 상태 설명
logged-in 사용자의 로그인 상태가 logged-in로 설정되면 FedCM을 호출하는 RP가 IdP의 계정 엔드포인트에 요청을 전달하고 FedCM 대화상자에 사용 가능한 계정을 사용자에게 표시합니다.
logged-out 사용자의 로그인 상태가 logged-out인 경우 FedCM을 호출하면 IdP의 계정 엔드포인트에 요청하지 않고도 자동으로 실패합니다.
unknown(기본) unknown 상태는 IdP가 Login Status API를 사용하여 신호를 보내기 전에 설정됩니다. 상태가 unknown이면 브라우저가 IdP의 계정 엔드포인트에 요청을 전송하고 계정 엔드포인트의 응답을 기반으로 상태를 업데이트합니다.

사용자가 로그인했음을 알리려면 최상위 탐색 또는 IdP 출처의 동일 사이트 하위 리소스 요청에서 Set-Login: logged-in HTTP 헤더를 전송합니다.

  Set-Login: logged-in

또는 최상위 탐색의 IdP 출처에서 JavaScript 메서드 navigator.login.setStatus('logged-in')를 호출합니다.

  navigator.login.setStatus('logged-in')

사용자의 로그인 상태가 logged-in로 설정됩니다.

사용자가 모든 계정에서 로그아웃되었음을 알리려면 최상위 탐색의 Set-Login: logged-out HTTP 헤더를 전송하거나 IdP 출처에서 동일 사이트 하위 리소스 요청을 전송합니다.

  Set-Login: logged-out

또는 최상위 탐색의 IdP 출처에서 JavaScript API navigator.login.setStatus('logged-out')를 호출합니다.

  navigator.login.setStatus('logged-out')

사용자의 로그인 상태가 logged-out로 설정됩니다.

unknown 상태는 IdP가 로그인 상태 API를 사용하여 신호를 보내기 전에 설정됩니다. 브라우저가 IdP의 계정 엔드포인트에 요청을 보내고 계정 엔드포인트의 응답을 기반으로 상태를 업데이트합니다.

  • 엔드포인트가 활성 계정 목록을 반환하면 상태를 logged-in로 업데이트하고 FedCM 대화상자를 열어 해당 계정을 표시합니다.
  • 엔드포인트에서 계정을 반환하지 않으면 상태를 logged-out로 업데이트하고 FedCM 호출을 실패로 처리합니다.

사용자가 동적 로그인 흐름을 통해 로그인하도록 허용

IdP가 계속해서 사용자의 로그인 상태를 브라우저에 알리더라도 세션이 만료되는 경우와 같이 동기화되지 않을 수 있습니다. 로그인 상태가 logged-in인 경우 브라우저는 계정 엔드포인트에 사용자 인증 정보가 포함된 요청을 전송하려고 하지만 세션을 더 이상 사용할 수 없으므로 서버는 계정을 반환하지 않습니다. 이러한 시나리오에서 브라우저는 팝업 창을 통해 사용자가 IdP에 동적으로 로그인하도록 허용할 수 있습니다.

다음 단계

RP에 FedCM을 구현하고 JavaScript SDK를 배포합니다. 자체 구현이 필요하지 않으므로 RP를 최신 상태로 유지합니다.
환경을 설정하고 구현을 디버그하는 방법을 알아봅니다.