ここで説明する更新の一部は、Google I/O セッション「セキュアでシームレスなログイン: ユーザー エンゲージメントの維持」で説明されています。
Chrome 57
Chrome 57 では、Credential Management API にこの重要な変更が導入されました。
別のサブドメインから認証情報を共有できます
Chrome で Credential Management API を使用して、別のサブドメインに保存されている認証情報を取得できるようになりました。たとえば、パスワードが login.example.com
に保存されている場合、www.example.com
のスクリプトは、Account Chooser ダイアログでアカウント アイテムの 1 つとしてパスワードを表示できます。
navigator.credentials.store()
を使用してパスワードを明示的に保存する必要があります。これにより、ユーザーがダイアログをタップして認証情報を選択すると、パスワードが現在のオリジンに渡され、コピーされます。
パスワードが保存されると、www.example.com
以降はまったく同じオリジンで認証情報として使用できるようになります。
次のスクリーンショットでは、login.aliexpress.com
に保存されている認証情報情報が m.aliexpress.com
に表示され、ユーザーが選択できるようになっています。
Chrome 60
Chrome 60 では、Credential Management API に重要な変更がいくつかあります。
カスタム
fetch()
関数はパスワードの取得に不要になったため、まもなくサポート終了となります。navigator.credentials.get()
がブール値フラグunmediated
の代わりに列挙型mediation
を受け入れるようになりました。新しいメソッド
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 から隠してもすべての攻撃ベクトルを期待したほど効果的に防ぐことはできないと判断し、変更を加えることにしました。
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()
関数を使用しているかどうかを判断するには、credentials
プロパティの値として PasswordCredential
オブジェクトと FederatedCredential
オブジェクトのどちらを使用しているかを確認します。次に例を示します。
fetch('/signin', {
method: 'POST',
credentials: c
})
前のコードサンプルで示した通常の fetch()
関数を使用するか、XMLHttpRequest
を使用することをおすすめします。
navigator.credentials.get()
が列挙型メディエーションを受け入れるようになりました
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 |
新しいオプション | Account Chooser を常に表示する。 ユーザーがネイティブの Account Chooser ダイアログを使用してアカウントを切り替えられるようにする場合に役立ちます。 |
この例では、前のフラグ 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 がすでに実装されている場合、新しいバージョンへのアップグレードについては、移行ガイドのドキュメントをご覧ください。