認証情報管理 API の最新情報

ここで説明するアップデートの一部は、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 に表示され、ユーザーが選択できるようになっています。

選択したサブドメインのログインの詳細が表示されている Account Chooser

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'
}).the>n(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 を使用することをおすすめします。

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 と等しい Account Chooser を表示せずに認証情報が渡されました。
optional unmediated: false と等しい 以前に preventSilentAccess() が呼び出された場合は、Account Chooser を表示します。
required 新しいオプション 常に Account Chooser を表示します。ユーザーがネイティブの Account Chooser ダイアログを使用してアカウントを切り替えられるようにする場合に便利です。

この例では、アカウント選択ツールを表示せずに認証情報が渡されます。これは、以前のフラグ unmediated: true と同等です。

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

    // Sign-in
});

requireUserMediation() の名前を preventSilentAccess() に変更しました

get() 呼び出しで提供される新しい mediation プロパティに合わせて、navigator.credentials.requireUserMediation() メソッドの名前が navigator.credentials.preventSilentAccess() に変更されました。

名前が変更されたメソッドは、Account Chooser を表示せずに(ユーザーの介入なしに)認証情報を渡すことを防ぎます。これは、ユーザーがウェブサイトからログアウトしたり、登録を解除したりして、次回のアクセス時に自動的にログインしたくない場合に便利です。

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 の既存の実装がある場合は、新しいバージョンにアップグレードするには、移行ガイドのドキュメントをご覧ください。