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

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

크롬 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에서 비밀번호를 숨겨도 원하는 만큼 효과적으로 모든 공격 경로를 차단하지 못한다는 것을 알게 된 Google은 변경사항을 적용하기로 결정했습니다.

이제 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() 함수를 사용 중인지 확인하려면 함수가 PasswordCredential 객체 또는 FederatedCredential 객체를 credentials 속성 값으로 사용하는지 확인하세요. 예를 들면 다음과 같습니다.

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가 기존에 구현되어 있나요? 이전 가이드 문서를 참고하여 새 버전으로 업그레이드하세요.