使い方
- ユーザー名とパスワードを入力します。
- 生成された Authorization ヘッダーをクライアントにコピーするか、curl コマンドを使ってリクエストをテストします。
- 既存のヘッダーを読み取るには、「既存のヘッダーをデコード」欄に貼り付けます。ユーザー名とパスワードが表示されます。
HTTP Basic 認証の仕組み
Basic 認証は RFC 7617 で定義されています。保護されたリソースにアクセスすると、サーバーは 401 Unauthorized と WWW-Authenticate: Basic realm="..." ヘッダーを返します。クライアントはユーザー名とパスワードをコロンでつなぎ、その結果を Base64 でエンコードして、リクエストのたびに送信します。
Authorization: Basic base64(username ":" password)
# RFC 7617 の例:ユーザー "Aladdin"、パスワード "open sesame"
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
ブラウザはこのやり取りを自動で処理し、ログインダイアログを表示します。一方、スクリプトや API クライアントは、チャレンジを待たずに最初のリクエストでヘッダーを送信するのが一般的です。2 つの値はコロンで区切られるため、ユーザー名にコロンを含めることはできません。パスワードには含めてもかまいません。サーバーはチャレンジに charset="UTF-8" を追加して、ASCII 以外の文字を含む認証情報を UTF-8 で送るよう示すことができます。
Base64 は暗号化ではありません
ヘッダーは一見すると意味のない文字列に見えますが、目にした人なら誰でも、このページのデコーダーや任意の Base64 デコーダーを使って数秒でパスワードを復元できます。Basic 認証を使ってよいのは、TLS によって通信中のヘッダーが暗号化される HTTPS 上だけです。また、次の点にも注意してください。
- 認証情報はリクエストのたびに送信されるため、暗号化されていない HTTP リクエストが 1 回あるだけで漏えいします。
- プロキシ、ロードバランサー、デバッグツールは、記録しないよう設定しない限り、
Authorizationヘッダーをログに残すことがあります。 - ブラウザは入力された認証情報を閉じるまで記憶しており、ログアウトする標準的な方法はありません。
公開 API には、失効させることができる API トークンや OAuth のほうが適しています。Basic 認証は、社内ツール、ステージングサイト、TLS を介したサーバー間通信では今でも妥当な選択肢です。
コードからヘッダーを送信する
# curl はヘッダーを自動で生成します
curl -u 'user:password' https://api.example.com/
// JavaScript の fetch(btoa は Latin-1 の文字しか扱えません)
fetch(url, { headers: { Authorization: 'Basic ' + btoa('user:password') } })
# Python の requests
requests.get(url, auth=('user', 'password'))
https://user:password@host/ のように URL に認証情報を埋め込むのは避けてください。この形式は RFC 3986 で非推奨とされており、ブラウザの履歴やサーバーのログに残るうえ、最近のブラウザでは制限されています。
よくある質問
Basic 認証ヘッダーをデコードするにはどうすればよいですか?
ヘッダーを「既存のヘッダーをデコード」欄に貼り付けると、すぐにユーザー名とパスワードが表示されます。どの Base64 デコーダーでも同じ結果が得られます。だからこそ、このヘッダーは必ず HTTPS 上でのみ送信する必要があります。
パスワードにコロンを含めることはできますか?
はい。サーバーはデコードした値を最初のコロンで分割するため、それより後ろはすべてパスワードとして扱われます。ただし、ユーザー名にはコロンを含めることができません。
HTTP Basic 認証は安全ですか?
強力で使い回しのないパスワードを HTTPS 上で使えば、通信中の認証情報は保護されます。ただし、認証情報はリクエストのたびに送信され、トークンのように有効期限が切れることもありません。暗号化されていない HTTP では絶対に使わないでください。
アクセント付きの文字や日本語などを含むパスワードでログインに失敗するのはなぜですか?
charset="UTF-8" を宣言できます。宣言がない場合、古いサーバーは ISO-8859-1 を想定し、異なるバイト列を比較してしまうことがあります。パスワードはどこかに送信されますか?
いいえ。ヘッダーはブラウザ内の JavaScript で生成され、何も送信されません。それでも、生成した curl コマンドを他の人と共有するときは、テスト用の認証情報を使ってください。