# 画像を選ばないと通れないログイン

Source: https://easeweb.dev/learn/picture-sign-in
Topics: ページの構造 > ログイン時に、物や画像の識別を求めない (WCAG 3.3.9)
The fix: ログインから画像を外します。画像の段階をメールで届くログイン用のリンクに置き換えるか、そこにパスキーを用意してメールのリンクを横に置きます。こうすれば、物を見分けることも、どれが自分の写真だったか思い出すことも、誰にも求めずに済みます。
Test with: screen reader, keyboard
References: https://www.w3.org/WAI/WCAG22/Understanding/accessible-authentication-enhanced.html https://www.w3.org/WAI/WCAG22/Understanding/accessible-authentication-minimum.html https://www.w3.org/WAI/WCAG22/Techniques/general/G218 https://www.w3.org/TR/turingtest/ https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/parseRequestOptionsFromJSON_static https://www.cl.cam.ac.uk/~jo262/papers/emperor.pdf

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

ある銀行のログインは、メールアドレスとパスワードを求めた後、口座の画面を開く前にもう1つ段階を挟みます。この段階の作り方としてよくあるのは2通りで、どちらも行き着く先は同じです。

1つ目は、ボット対策の確認です。新しいブラウザー、共用のネットワーク、プライバシー保護のツールを使っている人など、確認サービスが疑わしいと判定した訪問者には、「バスが写っている画像をすべて選んでください」の下に9枚の画像が並びます。日本では画像認証とも呼ばれ、たいていはCAPTCHAのサービスが、専用の枠の中に表示します。路面電車を数えるのか分からない人や、写真の端に写ったバスを見落とした人には、新しい画像が並び、もう一度やり直しになります。

2つ目は、本人の写真です。口座を開いたとき、銀行は自分の写真を1枚アップロードさせました。今回は「アップロードした写真を選んでください」の下に、その写真をほかの8枚と並べ、正しい1枚を選んだ人だけを通します。何年も前にアップロードした人や、海辺と庭のどちらの写真だったか覚えていない人は、先へ進めません。

どちらの場合も、通る方法は正しい画像を選ぶことだけです。ログイン用のリンクをメールで受け取るボタンも、パスキーも、ほかの方法もありません。ボット対策の確認では、スクリーンリーダーの利用者には「バスが写っている画像をすべて選んでください、グループ」に続いて「画像1、チェックボックス、チェックなし」と聞こえ、画像9まで同じように続きます。これでは始めることもできません。

## 確認できる問題

達成基準3.3.9「アクセシブルな認証（高度）」はレベルAAAで、WCAG 2.2で新しく加わりました。ログインのどの段階も、認知機能テストを求めてはいけません。ただし、その段階に、テストのいらない別の方法か、テストを通る助けになる仕組みがあれば構いません。AAの3.3.8と同じ基準から、例外を2つ外したものです。AAでは、バスを選ぶような物の識別と、アップロードした写真のように本人がサイトに提供したコンテンツの識別は認められています。AAAでは、どちらも認められません。解説書も、この2種類をどちらも挙げています。認証の段階では、特定の物が写った画像を選ばせることも、本人が提供した画像を選ばせることもできません。

HTMLには、これを妨げるものが何もありません。画像の並びは普通の画像とチェックボックスか、CAPTCHAのサービスの枠でできていて、どちらもログインの画面にそのまま置けます。代替テキストでも解決しません。ボット対策の画像は、答えを教えずに何が写っているかを説明できません。本人がアップロードした写真にも、その横の写真にも、説明を付ける人はいません。仮に付けても、写真を見分けるテストが、説明を覚えておくテストに変わるだけです。一部のCAPTCHAのサービスにあるような音声版を加えても、別の方法にはなりません。3.3.8の解説書によれば、聞き取った内容を入力するのは書き写しで、これもテストだからです。

## 利用者への影響

この段階は、パスワードが合っていた後に出ます。そのため、ログインが求めたことをすべて済ませた人を、支払いのように口座が最も必要なときに止めてしまうことがよくあります。

## 自動チェックとAIの限界

画像には代替テキストがあり、チェックボックスとラジオボタンには凡例の付いたグループがあり、「次へ」ボタンにも名前があります。そのため、axeなどの自動チェックはこの段階を合格にします。この段階はパスワードの後に出るうえ、ボット対策の確認は疑わしい訪問者にしか画像を見せないため、ログインのページを調べてもどちらも見つかりません。ログインしないEaseWebの診断は、2つを確認の依頼として挙げます。1つは、ログインのフォームの中に置かれたreCAPTCHAやhCaptchaのような画像認証のサービスです。もう1つは、ログインの画面で、画像について尋ねる問いの下に、文字のない画像だけの選択肢が4つ以上並んでいるものです。画像が出るか、その横にテストのいらない方法があるかは、人が実際にログインして確かめる必要があります。AIのコードアシスタントは、ログインを守るよう頼まれると、画像認証や本人の写真による確認を持ち出すことがあります。さらにアクセシブルにするよう頼むと、音声版を加えて済ませかねず、テストはそのまま残ります。

## 修正前：バスの写った画像をすべて選ぶ

```html
<form action="/sign-in/check" method="post">
  <p>Signing in as sam@example.com</p>
  <fieldset>
    <legend>Select every picture with a bus</legend>
    <label>
      <input type="checkbox" name="picture" value="1">
      <img src="/check/1.jpg" alt="Picture 1">
    </label>
    …
  </fieldset>
  <button type="submit">Continue</button>
</form>
```

`…` は、1枚目と同じ形の残り8枚の画像です。CAPTCHAのサービスが並べる画像も、ページの中に描くかサービスの枠の中に描くかにかかわらず、中身はこのマークアップと変わりません。

- 先へ進むには、画像の中からバスを見分けるしかありません。
- 代替テキストでは、答えを明かさずに、それぞれの画像に何が写っているかを伝えられません。
- この段階には、ほかの方法がありません。

## 修正前：口座を開いたときにアップロードした写真

```html
<form action="/sign-in/check" method="post">
  <p>Signing in as sam@example.com</p>
  <fieldset>
    <legend>Choose the photo you uploaded</legend>
    <label>
      <input type="radio" name="picture" value="1">
      <img src="/check/1.jpg" alt="Photo 1">
    </label>
    …
  </fieldset>
  <button type="submit">Continue</button>
</form>
```

`…` は、残り8枚の写真です。本人がアップロードした1枚と、銀行がその横に並べた7枚です。1つ目の修正前の例とは、求めるものが違います。

- 先へ進むには、口座を開いたときにアップロードした写真を選び出すしかありません。
- アップロードした写真には誰も説明を付けていないため、どれも「写真1」から「写真9」と読まれ、スクリーンリーダーの利用者にはどれが自分の写真か分かりません。
- この段階には、ほかの方法がありません。

## 修正後：画像の代わりに、メールで届くログイン用のリンク

```html
<form action="/sign-in/email-link" method="post">
  <p>Signing in as sam@example.com</p>
  <button type="submit">Email me a sign-in link</button>
</form>
```

1. 画像とその問いを外します。見分けるものも、思い出すものも残りません。
2. フォームの送信先を変えます。サーバーは口座のメールアドレスにリンクを送り、そのリンクでログインが済みます（達成方法G218）。
3. ボタンには、押すと何が起きるかを表す「Email me a sign-in link」という名前を付けます。

これで2つの修正前の例が直り、3.3.9を満たします。メールを開き、期限が切れる前にリンクを開く必要があるため、次の画面で、リンクをどこに送ったか、いつまで使えるかを伝えてください。

## 修正後：パスキーと、その横にメールのリンク

```html
<form action="/sign-in/email-link" method="post">
  <p>Signing in as sam@example.com</p>
  <button type="button" id="passkey">Use a passkey</button>
  <button type="submit">Email me a sign-in link</button>
</form>
```

```js
const passkey = document.querySelector('#passkey');
passkey.addEventListener('click', async () => {
  const options = await fetch('/sign-in/passkey-options').then((response) => response.json());
  const credential = await navigator.credentials.get({
    publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options)
  });
  const result = await fetch('/sign-in/passkey', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(credential.toJSON())
  });
  if (result.ok) location.assign('/account');
});
```

1. 画像とその問いを外します。
2. 「Use a passkey」ボタンを加えます。押すと、スクリプトがサーバーにチャレンジを求め、それを `navigator.credentials.get()` に渡します。端末が指紋、顔、画面ロックのいずれかを求め、サーバーは返ってきた応答を確かめます。
3. この端末にパスキーがない人のために、「Email me a sign-in link」ボタンを横に残します。

これで2つの修正前の例が直り、3.3.9を満たします。解説書は、パスキーの土台であるWeb Authenticationを、ユーザー名とパスワードの代わりに端末で認証する方法として挙げています。端末のロック解除は、サイトが課すテストではありません。ただし、使えるのは、あらかじめその口座のパスキーを作った人だけです。そのため、メールのリンクを横に残します。

## どの方法を選ぶか

どちらも3.3.9を満たし、どちらもテストを避ける道を足すのではなく、全員からテストを取り除きます。サイトにまだパスキーがなければ、メールのリンクだけを使います。フォーム1つとボタン1つで済み、ページに新しく作るものはありません。パスキーに対応しているサイトでは、パスキーを加えます。パスキーを持つ人はページを離れずに1回で済み、それ以外の人はメールのリンクで通れます。方針で必須のCAPTCHAのサービスのように、画像の段階を変えられない場合は、画像の横にメールのリンクを置いても満たします。3.3.9は、横に別の方法があるテストを認めているからです。その形は[CAPTCHAのガイド](/ja/learn/captcha)にあります。

## 実装の判断

画像が、パスワードを次々に試すプログラムを止めるためだけにあったのなら、その段階は置き換えずに外せます。アカウントごと、接続元ごとの試行回数の制限が、本人にテストを課さずにサーバーで同じ役目を果たします。[パズルを解く以外に通れないCAPTCHA](/ja/learn/captcha)を参照してください。

パスワードを打つ前に確かめてもらうために、銀行が表示するだけのセキュリティ画像は、ログインが何も判定しないため、この基準の言うテストにはあたりません。効果もあまりありません。2007年の銀行利用者の調査では、自分の口座を使った25人のうち23人が、画像が消えていてもパスワードを入力しました。アップロードした写真を複数の中から選ばせることが、3.3.9の認めない段階です。3.3.8の解説書は、こうした個人のコンテンツは推測で当てられることがあると注意しています。この例なら9分の1です。本人がアップロードしたのではなく、銀行が用意した画像から選んだものなら、もっと早く不適合になります。3.3.8の例外は本人が提供したコンテンツだけが対象のため、それを選び出させるだけで、AAの3.3.8に適合しません。[貼り付けを受け付けないパスワード欄](/ja/learn/password-paste)と同じ基準です。

メールのリンクは1回だけ、短い時間だけ使えるようにし、送ったことを伝える画面に、その両方を書いてください。携帯電話のショートメッセージで届くコードも2段階目の方法の1つですが、手で入力するのは書き写しです。[貼り付けられないワンタイムコードの入力欄](/ja/learn/one-time-codes)で扱う、貼り付けと自動入力が必要です。

パスキーはほかの方法と並べて用意し、唯一の方法にはしないでください。指紋や顔を使えない人もいます。EN 301 549の5.3は、1つの生体的特徴だけを利用者の識別に使わないよう求めています。パスキーは端末の画面ロックのPINでも使えます。パスキーの作成は、ログインの途中ではなく、ログインを済ませた後に勧めると、ログインそのものを短く保てます。

ログインのほかの部分にも同じ注意が必要です。貼り付けを拒むパスワード欄は3.3.8に適合しません。[貼り付けを受け付けないパスワード欄](/ja/learn/password-paste)を参照してください。

## 修正の確認

1. 画像が出ていた段階までログインを進め、メールのリンクと、ある場合はパスキーで、画像を1枚も選ばずにログインを済ませる。
2. スクリーンリーダーを使い、またキーボードだけで、その段階が用意する方法のすべてにたどり着いて使い、それぞれが名前で読まれるか確認する。
3. 新しいブラウザーかプライベートウィンドウ（ボット対策の確認にとって判定の手がかりが最も少ない環境）からログインし、避ける方法のない画像の段階が出ないか確認する。

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。ログイン、そのボット対策、2段階目の方法を変更した際は、再度確認します。

## 制限

このサンプルは、どのログインでも同じ結果になることを保証するものではありません。3.3.9はレベルAAAで、ほとんどの法律や方針は求めていません。しかし、この基準が守る人は、AAを満たすログインでも画像で締め出されている人です。対象はログインで、アカウントの作成や復旧は含みません。ただし、そこに画像の段階があれば、同じ人が止まります。メールのリンクはメールを確認できる人の、パスキーはパスキーを持つ人の助けにしかならないため、ログインの方法は複数用意してください。ボット対策の確認が疑った訪問者にだけ出るものも含め、利用者が頼る道具でログイン全体を確認してください。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
