여기에 설명된 일부 업데이트는 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
에 표시되며 사용자가 선택할 수 있습니다.
![선택한 하위 도메인의 로그인 세부정보가 표시된 계정 선택기](https://developer.chrome.com/static/blog/credential-management-updates/image/account-chooser-showing-s-369ff3f4bb61e.png?authuser=8&hl=ko)
Chrome 60
Chrome 60의 Credential Management API에 몇 가지 중요한 변경사항이 도입되었습니다.
커스텀
fetch()
함수는 더 이상 비밀번호를 가져올 필요가 없으므로 곧 지원 중단됩니다.navigator.credentials.get()
가 이제 불리언 플래그unmediated
대신 enummediation
를 허용합니다.requireUserMediation()
의 이름이preventSilentAccess()
(으)로 변경되었습니다.새 메서드
navigator.credentials.create()
는 사용자 인증 정보 객체를 비동기식으로 만듭니다.
기능 감지에 주의가 필요합니다.
비밀번호 기반 사용자 인증 정보와 제휴 사용자 인증 정보에 액세스하기 위한 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
를 사용하는 것이 좋습니다.
이제 navigator.credentials.get()
가 enum 미디에이션을 허용합니다.
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가 기존에 구현되어 있나요? 이전 가이드 문서를 참고하여 새 버전으로 업그레이드하세요.