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

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

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

well-known 파일 만들기

추적기가 API를 악용하지 못하도록 IdP의 eTLD+1/.well-known/web-identity에서 well-known 파일을 제공해야 합니다.

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

속성 필수 설명
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-identityIdP 구성 파일에서도 well-known 파일을 제공해야 합니다. 다음은 잘 알려진 파일 콘텐츠의 예입니다.

  {
    "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() 호출에 제공된 값에 따라 결정됩니다. RP는 모든 ID 공급업체의 구성 파일 URL을 전달합니다.

  // Executed on RP's side:
  try {
    const credential = await navigator.credentials.get({
      identity: {
        providers: [
          {
            // To allow users to sign in with the IdP1 using FedCM, RP specifies the IdP's config file URL:
            configUrl: 'https://idp1.example/foo.json', // first IdP
            clientId: '123',
          },
          // To allow users to sign in with the IdP2 using FedCM, RP specifies the IdP's config file URL.
          // Note that multiple IdPs in a single get() are supported from Chrome 136.
          {
            configUrl: 'https://idp2.example/bar.json', // second IdP
            clientId: '456',
          },
        ],
      },
    });

    const token = credential.token;
    // Get the current IdP's configURL to identify which provider the user is signed in with
    const currentIdpConfigUrl = credential.configURL;
    if (currentIdpConfigUrl === 'https://idp1.example/foo.json') {
      // handle the case where the user signed in with idp1
    } else if (currentIdpConfigUrl === 'https://idp2.example/bar.json') {
      // handle the case where the user signed in with idp2
    }
  } catch (error) {
    // handle error
  }

브라우저는 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입니다.
account_label(선택사항) 이 구성 파일을 사용할 때 반환해야 하는 계정을 결정하는 맞춤 계정 라벨 문자열입니다(예: "account_label": "developer").
IdP는 다음과 같이 맞춤 계정 라벨을 구현할 수 있습니다.

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

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

다음은 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.
    "account_label": "developer",
    "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",
    "supports_use_other_account": true
  }

계정 엔드포인트

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

브라우저가 SameSite=None이 포함된 쿠키가 있지만 client_id 매개변수, Origin 헤더 또는 Referer 헤더는 없는 GET 요청을 전송합니다. 이렇게 하면 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 사용자의 언어 및 환경설정에 따른 전체 이름입니다.

참고: Chrome 141부터는 name, email, username, tel 매개변수 중 하나 이상이 필요합니다. 이전 Chrome 버전에서는 nameemail이 모두 필요합니다.
username 사용자가 선택한 사용자 이름입니다.

참고: Chrome 141부터는 name, email, username, tel 매개변수 중 하나 이상이 필요합니다.
email 사용자의 이메일 주소입니다.

참고: Chrome 141부터는 name, email, username, tel 매개변수 중 하나 이상이 필요합니다. 이전 Chrome 버전에서는 nameemail이 모두 필요합니다.
tel 사용자의 전화번호입니다.

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

예를 들어 IdP는 "account_label": "developer"가 지정된 https://idp.example/developer-config.json 구성 파일을 구현합니다. IdP는 계정 엔드포인트에서 label_hints 매개변수를 사용하여 일부 계정에 "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.
      "label_hints": ["enterprise", "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-urlencoded이 포함된 쿠키와 함께 POST 요청을 다음 정보와 함께 이 엔드포인트로 전송합니다.

속성 설명
client_id(필수) RP의 클라이언트 식별자입니다.
account_id(필수) 로그인하는 사용자의 고유 ID입니다.
disclosure_text_shown 불리언이 아닌 "true" 또는 "false" 문자열이 반환됩니다. 다음의 경우 결과는 "false"입니다.
  • RP의 클라이언트 ID가 계정 엔드포인트의 응답에 있는 approved_clients 속성 목록에 포함되어 있어 공개 텍스트가 표시되지 않은 경우
  • 브라우저에서 과거에 approved_clients 없이 가입 순간을 관찰하여 공개 텍스트가 표시되지 않은 경우
  • fields 매개변수에 'name', 'email', 'picture'의 세 필드가 모두 포함되지 않는 경우(예: fields=[ ] 또는 fields=['name', 'picture']) 이는 이전 구현과의 하위 호환성을 위해 필요합니다.

    참고: Chrome 141부터는 disclosure_text_shown 값이 "false"인 경우에도 공개 텍스트가 표시될 수 있습니다. 공개 텍스트가 표시되었는지 확인하려면 disclosure_shown_for 값을 확인하세요.
disclosure_shown_for RP가 IdP에서 요청하는 데이터를 사용자에게 알리기 위해 공개 텍스트에 브라우저가 사용자에게 표시한 필드를 나열합니다.
is_auto_selected RP에서 자동 재인증이 실행되면 is_auto_selected"true"을 나타냅니다. 그 외의 경우에는 "false"입니다. 이는 더 많은 보안 관련 기능을 지원하는 데 유용합니다. 예를 들어 일부 사용자는 인증 시 명시적인 사용자 중재가 필요한 더 높은 보안 등급을 선호할 수 있습니다. IdP가 이러한 미디에이션 없이 토큰 요청을 수신하면 요청을 다르게 처리할 수 있습니다. 예를 들어 RP가 mediation: required로 FedCM API를 다시 호출할 수 있도록 오류 코드를 반환합니다.
fields(선택사항) RP가 IdP에 공유하도록 요청한 사용자 정보를 지정하는 문자열 배열입니다. 다음 필드는 선택적으로 지정할 수 있습니다.
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
브라우저는 다음 예와 같이 POST 요청에 지정된 필드를 나열하는 fields, disclosure_text_shown, disclosure_shown_for를 전송합니다.

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

참고: 매개변수 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&fields=email,picture&disclosure_shown_for=email,picture

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

  1. CORS (교차 출처 리소스 공유)로 요청에 응답합니다.
  2. 요청에 Sec-Fetch-Dest: webidentity HTTP 헤더가 포함되어 있는지 확인합니다.
  3. client_id에 의해 결정된 RP 출처에 대해 Origin 헤더를 일치시킵니다. 일치하지 않으면 거부합니다.
  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 호출자에게 반환합니다. 일회성 IdentityProvider.resolve() 호출은 상위 창 (RP)과 팝업 창 (IdP)이 통신할 수 있는 유일한 방법입니다.
사용자가 요청을 거부하면 IdP는 IdentityProvider.close()를 호출하여 창을 닫을 수 있습니다.

  IdentityProvider.close();

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

  • passive 모드:
    • mediation: 'optional' (기본값): 연속 API는 페이지 또는 FedCM UI의 버튼을 클릭하는 등의 사용자 동작에서만 작동합니다. 사용자 동작 없이 자동 재인증이 트리거되면 팝업 창이 열리지 않고 프로미스가 거부됩니다.
    • mediation: 'required': 항상 사용자에게 상호작용을 요청하므로 연속 API가 항상 작동합니다.
  • 활성 모드:
    • 사용자 활성화는 항상 필요합니다. 연속 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",
    "account_label": "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",
    "account_label": "hr"
  }
  • 이러한 설정에서는 여러 configURL을 허용하기 위해 well-known 파일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)는 각 계정에 대해 배열에 할당된 라벨이 있는 label_hints 속성을 포함하는 계정 목록을 반환합니다.
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "label_hints": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "label_hints": ["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',
      },
    }
  });

따라서 사용자가 로그인할 수 있는 계정 ID는 4567뿐입니다. 123의 계정 ID는 사용자가 이 사이트의 IdP에서 지원하지 않는 계정을 제공받지 않도록 브라우저에 의해 자동으로 숨겨집니다.

추가 고려사항:

  • 라벨은 문자열입니다. label_hints 배열 또는 account_label 필드에서 문자열이 아닌 값을 사용하는 경우 해당 값은 무시됩니다.
  • 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. client_id에 의해 결정된 RP 출처에 대해 Origin 헤더를 일치시킵니다. 일치하지 않으면 거부합니다.
  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 대화상자에는 다음 이미지와 같이 로그인을 제안하는 메시지가 표시됩니다.

IdP에 로그인하도록 제안하는 FedCM 대화상자
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인 경우 IdP의 계정 엔드포인트에 요청하지 않고 FedCM이 자동으로 실패합니다.
unknown(기본) unknown 상태는 IdP가 로그인 상태 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로 설정됩니다.

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

  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를 최신 상태로 유지합니다.
환경을 설정하고 구현을 디버그하는 방법을 알아봅니다.