사용자 인증 정보 관리 API를 사용한 로그인 흐름 간소화

고급 사용자 환경을 제공하려면 사용자가 웹사이트에 인증할 수 있도록 지원하는 것이 중요합니다. 인증된 사용자는 전용 프로필을 사용하여 서로 상호작용하거나, 기기 간에 데이터를 동기화하거나, 오프라인 상태에서 데이터를 처리할 수 있습니다. 이러한 작업은 계속해서 늘어납니다. 하지만 비밀번호를 만들고 기억하고 입력하는 것이 특히 모바일 화면에서 번거로워 최종 사용자가 여러 사이트에서 동일한 비밀번호를 재사용하는 경우가 많습니다. 물론 이는 보안 위험이 있습니다.

Chrome 최신 버전 (51)은 Credential Management API를 지원합니다. W3C의 표준 트랙 제안으로, 개발자가 브라우저의 인증 관리자에 프로그래매틱 방식으로 액세스할 수 있도록 지원하고 사용자가 더 쉽게 로그인할 수 있도록 도와줍니다.

Credential Management API란 무엇인가요?

Credential Management API를 사용하면 개발자가 비밀번호 사용자 인증 정보와 제휴 사용자 인증 정보를 저장하고 검색할 수 있으며 다음 3가지 함수를 제공합니다.

  • navigator.credentials.get()
  • navigator.credentials.store()
  • navigator.credentials.requireUserMediation()

개발자는 이 간단한 API를 사용하여 다음과 같은 강력한 작업을 수행할 수 있습니다.

  • 사용자가 한 번의 탭으로 로그인할 수 있도록 지원하세요.
  • 사용자가 로그인하는 데 사용한 제휴 계정을 기억합니다.
  • 세션이 만료될 때 사용자를 다시 로그인합니다.

Chrome 구현에서는 사용자 인증 정보가 Chrome의 비밀번호 관리자에 저장됩니다. 사용자가 Chrome에 로그인하면 여러 기기에서 사용자의 비밀번호를 동기화할 수 있습니다. 동기화된 비밀번호는 원활한 교차 플랫폼 환경을 위해 Android용 비밀번호 스마트 잠금 API를 통합한 Android 앱과도 공유할 수 있습니다.

사이트와 인증 관리 API 통합

웹사이트에서 Credential Management API를 사용하는 방법은 아키텍처에 따라 다를 수 있습니다. 단일 페이지 앱인가요? 페이지 전환이 있는 기존 아키텍처인가요? 로그인 양식이 상단 페이지에만 있나요? 로그인 버튼이 어디에나 있나요? 사용자가 로그인하지 않고 웹사이트를 의미 있게 탐색할 수 있나요? 팝업 창 내에서 제휴가 작동하나요? 아니면 여러 페이지에 걸친 상호작용이 필요한가요?

모든 경우를 포괄하는 것은 거의 불가능하지만, 이제 전형적인 단일 페이지 앱을 살펴보겠습니다.

  • 상단 페이지는 등록 양식입니다.
  • '로그인' 버튼을 탭하면 사용자가 로그인 양식으로 이동합니다.
  • 등록 양식과 로그인 양식 모두 ID/비밀번호 사용자 인증 정보 및 제휴(예: Google 로그인 및 Facebook 로그인)의 일반적인 옵션이 있습니다.

Credential Management API를 사용하면 다음과 같은 기능을 사이트에 추가할 수 있습니다.

  • 로그인 시 계정 선택기 표시: 사용자가 '로그인'을 탭하면 네이티브 계정 선택기 UI가 표시됩니다.
  • 사용자 인증 정보 저장: 로그인에 성공하면 나중에 사용할 수 있도록 사용자 인증 정보 정보를 브라우저의 비밀번호 관리자에 저장할지 묻습니다.
  • 사용자 자동 다시 로그인 허용: 세션이 만료되면 사용자가 다시 로그인하도록 허용합니다.
  • 자동 로그인 조정: 사용자가 로그아웃하면 다음 방문 시 자동 로그인을 사용 중지합니다.

데모 사이트샘플 코드를 통해 이러한 기능을 경험해 볼 수 있습니다.

로그인 시 계정 선택기 표시

사용자가 '로그인' 버튼을 탭하고 로그인 양식으로 이동하는 사이 navigator.credentials.get()을 사용하여 사용자 인증 정보를 가져올 수 있습니다. Chrome에는 사용자가 계정을 선택할 수 있는 계정 선택기 UI가 표시됩니다.

사용자가 로그인할 계정을 선택할 수 있는 계정 선택기 UI가 표시됩니다.
사용자가 로그인할 계정을 선택할 수 있도록 계정 선택기 UI가 표시됩니다.

비밀번호 사용자 인증 정보 객체 가져오기

계정 옵션으로 비밀번호 사용자 인증 정보를 표시하려면 password: true를 사용합니다.

navigator.credentials.get({
    password: true, // `true` to obtain password credentials
}).then(function(cred) {
    // continuation
    ...

비밀번호 사용자 인증 정보로 로그인

사용자가 계정을 선택하면 확인 함수가 비밀번호 사용자 인증 정보를 수신합니다. fetch()를 사용하여 서버에 전송할 수 있습니다.

    // continued from previous example
}).then(function(cred) {
    if (cred) {
    if (cred.type == 'password') {
        // Construct FormData object
        var form = new FormData();

        // Append CSRF Token
        var csrf_token = document.querySelector('csrf_token').value;
        form.append('csrf_token', csrf_token);

        // You can append additional credential data to `.additionalData`
        cred.additionalData = form;

        // `POST` the credential object as `credentials`.
        // id, password and the additional data will be encoded and
        // sent to the url as the HTTP body.
        fetch(url, {           // Make sure the URL is HTTPS
        method: 'POST',      // Use POST
        credentials: cred    // Add the password credential object
        }).then(function() {
        // continuation
        });
    } else if (cred.type == 'federated') {
        // continuation

제휴 사용자 인증 정보를 사용하여 로그인

사용자에게 제휴 계정을 표시하려면 ID 제공업체 배열을 사용하는 federatedget() 옵션에 추가합니다.

비밀번호 관리자에 여러 계정이 저장된 경우
비밀번호 관리자에 여러 계정이 저장된 경우
navigator.credentials.get({
    password: true, // `true` to obtain password credentials
    federated: {
    providers: [  // Specify an array of IdP strings
        'https://accounts.google.com',
        'https://www.facebook.com'
    ]
    }
}).then(function(cred) {
    // continuation
    ...

사용자 인증 정보 객체의 type 속성을 검사하여 PasswordCredential(type == 'password')인지 또는 FederatedCredential (type == 'federated')인지 확인할 수 있습니다. 사용자 인증 정보가 FederatedCredential인 경우 포함된 정보를 사용하여 적절한 API를 호출할 수 있습니다.

    });
} else if (cred.type == 'federated') {
    // `provider` contains the identity provider string
    switch (cred.provider) {
    case 'https://accounts.google.com':
        // Federated login using Google Sign-In
        var auth2 = gapi.auth2.getAuthInstance();

        // In Google Sign-In library, you can specify an account.
        // Attempt to sign in with by using `login_hint`.
        return auth2.signIn({
        login_hint: cred.id || ''
        }).then(function(profile) {
        // continuation
        });
        break;

    case 'https://www.facebook.com':
        // Federated login using Facebook Login
        // continuation
        break;

    default:
        // show form
        break;
    }
}
// if the credential is `undefined`
} else {
// show form
사용자 인증 정보 관리 흐름 차트

사용자 인증 정보 저장

사용자가 양식을 사용하여 웹사이트에 로그인하면 navigator.credentials.store()를 사용하여 사용자 인증 정보를 저장할 수 있습니다. 사용자에게 저장할지 묻는 메시지가 표시됩니다. 사용자 인증 정보 유형에 따라 new PasswordCredential() 또는 new FederatedCredential()를 사용하여 저장할 사용자 인증 정보 객체를 만듭니다.

Chrome에서 사용자에게 사용자 인증 정보 (또는 페더레이션 제공자)를 저장할지 묻습니다.
Chrome에서 사용자에게 사용자 인증 정보 (또는 페더레이션 제공자)를 저장할지 묻습니다.

양식 요소에서 비밀번호 사용자 인증 정보 만들기 및 저장

다음 코드는 autocomplete 속성을 사용하여 양식의 요소를 PasswordCredential 객체 매개변수에 자동으로 매핑합니다.

HTML html <form id="form" method="post"> <input type="text" name="id" autocomplete="username" /> <input type="password" name="password" autocomplete="current-password" /> <input type="hidden" name="csrf_token" value="******" /> </form>

자바스크립트

var form = document.querySelector('\#form');
var cred = new PasswordCredential(form);
// Store it
navigator.credentials.store(cred)
.then(function() {
    // continuation
});

제휴 사용자 인증 정보 만들기 및 저장

// After a federation, create a FederatedCredential object using
// information you have obtained
var cred = new FederatedCredential({
    id: id,                                  // The id for the user
    name: name,                              // Optional user name
    provider: 'https://accounts.google.com',  // A string that represents the identity provider
    iconURL: iconUrl                         // Optional user avatar image url
});
// Store it
navigator.credentials.store(cred)
.then(function() {
    // continuation
});
로그인 흐름 다이어그램

사용자가 자동으로 다시 로그인하도록 허용

사용자가 웹사이트를 떠났다가 나중에 다시 돌아오면 세션이 만료되었을 수 있습니다. 사용자가 다시 방문할 때마다 비밀번호를 입력하도록 하지 마세요. 사용자가 자동으로 다시 로그인하도록 허용합니다.

사용자가 자동으로 로그인하면 알림이 표시됩니다.
사용자가 자동으로 로그인하면 알림이 표시됩니다.

사용자 인증 정보 객체 가져오기

navigator.credentials.get({
    password: true, // Obtain password credentials or not
    federated: {    // Obtain federation credentials or not
    providers: [  // Specify an array of IdP strings
        'https://accounts.google.com',
        'https://www.facebook.com'
    ]
    },
    unmediated: true // `unmediated: true` lets the user automatically sign in
}).then(function(cred) {
    if (cred) {
    // auto sign-in possible
    ...
    } else {
    // auto sign-in not possible
    ...
    }
});

코드는 '로그인 시 계정 선택기 표시' 섹션에서 본 코드와 비슷해야 합니다. 유일한 차이점은 unmediated: true를 설정한다는 점입니다.

이렇게 하면 함수가 즉시 확인되고 사용자를 자동으로 로그인할 사용자 인증 정보가 제공됩니다. 몇 가지 조건이 있습니다.

  • 사용자가 자동 로그인 기능을 확인하고 환영 메시지를 받았습니다.
  • 사용자가 이전에 Credential Management API를 사용하여 웹사이트에 로그인한 적이 있습니다.
  • 사용자에게 출처에 저장된 사용자 인증 정보가 하나만 있습니다.
  • 사용자가 이전 세션에서 명시적으로 로그아웃하지 않았습니다.

이러한 조건 중 하나라도 충족되지 않으면 함수가 거부됩니다.

사용자 인증 정보 객체 흐름 다이어그램

자동 로그인 미디에이션

사용자가 웹사이트에서 로그아웃하면 사용자가 자동으로 다시 로그인되지 않도록 하는 것은 개발자의 책임입니다. 이를 위해 Credential Management API는 미디에이션이라는 메커니즘을 제공합니다. navigator.credentials.requireUserMediation()를 호출하여 미디에이션 모드를 사용 설정할 수 있습니다. 출처에 대한 사용자의 미디에이션 상태가 사용 설정되어 있는 한 navigator.credentials.get()와 함께 unmediated: true를 사용하면 이 함수가 undefined로 확인됩니다.

자동 로그인 미디에이션

navigator.credentials.requireUserMediation();
자동 로그인 흐름 차트

FAQ

웹사이트의 JavaScript가 원시 비밀번호를 가져올 수 있나요? 아니요. 비밀번호는 PasswordCredential의 일부로만 가져올 수 있으며 어떤 방법으로도 노출될 수 없습니다.

Credential Management API를 사용하여 ID의 숫자 3개 세트를 저장할 수 있나요? 현재는 그렇게 할 수 없습니다. 사양에 관한 의견을 보내주시면 대단히 감사하겠습니다.

iframe 내에서 인증 관리 API를 사용할 수 있나요? 이 API는 최상위 컨텍스트로 제한됩니다. iframe에서 .get() 또는 .store()를 호출하면 효과 없이 즉시 확인됩니다.

비밀번호 관리 Chrome 확장 프로그램을 인증 관리 API와 통합할 수 있나요? navigator.credentials를 재정의하고 Chrome 확장 프로그램에 연결하여 get() 또는 store() 사용자 인증 정보를 사용할 수 있습니다.

리소스

Credential Management API에 대해 자세히 알아보려면 통합 가이드를 확인하세요.