사용자 인증 정보 관리 API 최신 업데이트

여기에 설명된 일부 업데이트는 Google I/O 세션인 안전하고 원활한 로그인: 사용자 참여도 유지에서 설명합니다.

Chrome 57

Chrome 57에서는 Credential Management API에 이 중요한 변경사항을 도입했습니다.

다른 하위 도메인에서 사용자 인증 정보를 공유할 수 있습니다.

이제 Chrome은 Credential Management API를 사용하여 다른 하위 도메인에 저장된 사용자 인증 정보를 가져올 수 있습니다. 예를 들어 비밀번호가 login.example.com에 저장된 경우 www.example.com의 스크립트는 계정 선택기 대화상자의 계정 항목 중 하나로 비밀번호를 표시할 수 있습니다.

사용자가 대화상자를 탭하여 사용자 인증 정보를 선택할 때 비밀번호가 전달되고 현재 출처에 복사되도록 navigator.credentials.store()를 사용하여 비밀번호를 명시적으로 저장해야 합니다.

비밀번호가 저장되면 정확히 동일한 출처 www.example.com 이상에서 사용자 인증 정보로 사용할 수 있습니다.

다음 스크린샷에서 login.aliexpress.com에 저장된 사용자 인증 정보는 m.aliexpress.com에 표시되며 사용자가 선택할 수 있습니다.

선택한 하위 도메인 로그인 세부정보를 보여주는 계정 선택기

Chrome 60

Chrome 60에서는 Credential Management API에 몇 가지 중요한 변경사항이 도입되었습니다.

기능 감지에 주의가 필요함

비밀번호 기반 및 제휴 사용자 인증 정보에 액세스하는 Credential Management API를 사용할 수 있는지 확인하려면 window.PasswordCredential 또는 window.FederatedCredential를 사용할 수 있는지 확인합니다.

if (window.PasswordCredential || window.FederatedCredential) {
  // The Credential Management API is available
}

이제 PasswordCredential 객체에 비밀번호가 포함됨

Credential Management API는 비밀번호 처리에 보수적인 접근 방식을 취했습니다. JavaScript에서 비밀번호를 숨겨 개발자가 fetch() API 확장 프로그램을 통해 유효성 검사를 위해 PasswordCredential 객체를 서버로 직접 전송해야 했습니다.

하지만 이 접근 방식에는 몇 가지 제한사항이 있습니다. 다음과 같은 이유로 개발자가 API를 사용할 수 없다는 의견이 접수되었습니다.

  • 비밀번호를 JSON 객체의 일부로 전송해야 했습니다.

  • 비밀번호의 해시 값을 서버로 전송해야 했습니다.

보안 분석을 수행한 결과, JavaScript에서 비밀번호를 숨겨도 모든 공격 벡터가 기대만큼 효과적으로 차단되지 않는다는 사실을 확인하여 변경하기로 결정했습니다.

이제 Credential Management API는 반환된 사용자 인증 정보 객체에 원시 비밀번호를 포함하므로 일반 텍스트로 액세스할 수 있습니다. 기존 메서드를 사용하여 사용자 인증 정보(애플리케이션 사용자 인증 정보)를 서버에 전송할 수 있습니다.

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).then(passwordCred => {
    if (passwordCred) {
    let form = new FormData();
    form.append('email', passwordCred.id);
    form.append('password', passwordCred.password);
    form.append('csrf_token', csrf_token);
    return fetch('/signin', {
        method: 'POST',
        credentials: 'include',
        body: form
    });
    } else {

    // Fallback to sign-in form
    }
}).then(res => {
    if (res.status === 200) {
    return res.json();
    } else {
    throw 'Auth failed';
    }
}).then(profile => {
    console.log('Auth succeeded', profile);
});

맞춤 가져오기가 곧 지원 중단됨

맞춤 fetch() 함수를 사용 중인지 확인하려면 fetch() 함수가 credentials 속성의 값으로 PasswordCredential 객체 또는 FederatedCredential 객체를 사용하는지 확인합니다. 예를 들면 다음과 같습니다.

fetch('/signin', {
    method: 'POST',
    credentials: c
})

이전 코드 예와 같이 일반 fetch() 함수를 사용하거나 XMLHttpRequest를 사용하는 것이 좋습니다.

Chrome 60까지 navigator.credentials.get()는 불리언 플래그와 함께 선택적 unmediated 속성을 허용했습니다. 예를 들면 다음과 같습니다.

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    unmediated: true
}).then(c => {

    // Sign-in
});

unmediated: true를 설정하면 브라우저가 사용자 인증 정보를 전달할 때 계정 선택기를 표시하지 않습니다.

이제 플래그가 미디에이션으로 확장됩니다. 사용자 미디에이션은 다음과 같은 경우에 발생할 수 있습니다.

  • 사용자는 로그인할 계정을 선택해야 합니다.

  • 사용자가 navigator.credentials.requireUseMediation() 호출 후에 명시적으로 로그인하려고 합니다.

mediation 값에 다음 옵션 중 하나를 선택합니다.

mediation 부울 플래그와 비교 동작
silent unmediated: true과(와) 같음 계정 선택기를 표시하지 않고 인증 정보가 전달되었습니다.
optional unmediated: false과(와) 같음 이전에 preventSilentAccess()이 호출된 경우 계정 선택 도구를 표시합니다.
required 새로운 옵션 계정 선택 도구를 항상 표시합니다. 사용자가 네이티브 계정 선택기 대화상자를 사용하여 계정을 전환하도록 허용하려는 경우에 유용합니다.

이 예에서는 이전 플래그 unmediated: true와 동일한 계정 선택 도구를 표시하지 않고 사용자 인증 정보가 전달됩니다.

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).then(c => {

    // Sign-in
});

requireUserMediation()에서 preventSilentAccess()로 이름이 변경되었습니다.

get() 호출에서 제공되는 새 mediation 속성과 잘 일치하도록 navigator.credentials.requireUserMediation() 메서드의 이름이 navigator.credentials.preventSilentAccess()로 변경되었습니다.

이름이 변경된 메서드는 계정 선택 도구를 표시하지 않고 사용자 인증 정보를 전달하지 못하도록 합니다(사용자 미디에이션 없이 호출이라고도 함). 이는 사용자가 웹사이트에서 로그아웃하거나 등록을 해제한 후 다음에 방문할 때 자동으로 다시 로그인되지 않도록 하는 데 유용합니다.

signoutUser();
if (navigator.credentials) {
    navigator.credentials.preventSilentAccess();
}

새 메서드 navigator.credentials.create()를 사용하여 사용자 인증 정보 객체를 비동기식으로 만듭니다.

이제 새 메서드 navigator.credentials.create()를 사용하여 사용자 인증 정보 객체를 비동기식으로 만들 수 있습니다. 동기식 접근 방식과 비동기식 접근 방식을 비교해 보세요.

PasswordCredential 객체 만들기

동기화 접근 방식
let c = new PasswordCredential(form);
비동기 접근 방식 (신규)
let c = await navigator.credentials.create({
    password: form
});

또는:

let c = await navigator.credentials.create({
    password: {
    id: id,
    password: password
    }
});

FederatedCredential 객체 만들기

동기화 접근 방식
let c = new FederatedCredential({
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
});
비동기 접근 방식 (신규)
let c = await navigator.credentials.create({
    federated: {
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
    }
});

이전 가이드

Credential Management API의 기존 구현이 있나요? 새 버전으로 업그레이드하는 방법은 이전 가이드 문서를 참고하세요.