Basic 認証ヘッダーをデコードする手順
- 値を Authorization ヘッダー、Basic トークン、または認証情報付き URL に貼り付けます。次のどれでも動作します。
Authorization: Basic YWRtaW46czNjcjN0OnBhc3M=Proxy-Authorization: Basic …Basic YWRtaW46czNjcjN0OnBhc3M=またはトークンだけhttps://user:password@host/path
- 文字コード は自動検出のままにしておき、結果がおかしければ UTF-8 か ISO-8859-1 を指定します。
- ユーザー名 と パスワード を確認し、それぞれコピーできます。怪しい文字があれば デコード後のバイト(16進数) を確認してください。
デコードするのは Basic スキームだけです。Digest や NTLM のヘッダーは形式が異なり、別のスキームとして報告されます。
デコーダーが表示するもの
| 入力 | ユーザー名 | パスワード | 補足 |
|---|---|---|---|
Basic YWRtaW46czNjcjN0OnBhc3M= | admin | s3cr3t:pass | 分割するのは最初のコロンだけで、パスワード内のコロンはそのまま残る。 |
dGVzdDoxMjOj | test | 123£ | UTF-8 として不正なので、自動検出は Latin-1 にフォールバックする。 |
dGVzdDoxMjPCow== | test | 123£ | 同じテキストの UTF-8 バイト列。 |
https://ci-bot:p%40ss@ci.example.com/ | ci-bot | p@ss | URL から取り出し、パーセントデコード済み。 |
Bearer eyJhbGciOi… | エラー:Bearer トークンで、JWT デコーダーへのリンクを表示。 |
自動検出は順番に判定します。純粋な ASCII はどの文字コードでも同じようにデコードされ、有効な UTF-8 になるバイト列は UTF-8 として読み、それ以外は HTTP ヘッダーの従来のデフォルトである ISO-8859-1 として読みます。ここでの Latin-1 は正真正銘の ISO-8859-1 です。Windows-1252 は € などの文字がある 0x80–0x9F の範囲で ISO-8859-1 と異なるため、Windows-1252 のパスワードは制御文字として表示されることがあります。
デコーダーは、= パディングの欠落や URL セーフの - と _ など、いい加減なトークンにも寛容ですが、厳格なサーバーなら拒否するので、その旨を表示します。デコードしてもコロンがまったくないテキストになった場合、その値は user:password の組ではなかったということなので、ツールはそう報告します。
Basic 認証の資格情報が見つかる場所
- ブラウザの開発者ツール。 ネットワークタブでは、すべてのリクエストのヘッダーが
Authorizationも含めて表示されます。 - curl。
curl -vはリクエストを出力するので、-u user:passは> Authorization: Basic …として現れます。 - HAR ファイルやプロキシのキャプチャ。 各リクエストのヘッダーがすべて保存されています。
- サーバーやプロキシの設定。 nginx の
proxy_set_header Authorization "Basic …"のように、ハードコードしたヘッダーでバックエンドへのアクセスを与えている場合です。 - Docker レジストリの資格情報。
~/.docker/config.jsonのauthフィールドはuser:passwordの Base64 です。ファイル全体は dockerconfigjson デコーダー で開けます。 - アプリケーションのログ。 フレームワークが受信したヘッダーを伏せ字にせずに記録している場合です。
どれもエンコードを 1 層かけただけの平文パスワードなので、パスワードそのものとして扱ってください。エンコードが何も守らない理由は、Base64 は暗号化ではない で説明しています。
サーバー側でヘッダーをデコードする
通常はフレームワークがやってくれますが、スクリプトやテストでは小さなパーサーが役に立ちます。
import base64
def parse_basic(header_value):
scheme, _, token = header_value.strip().partition(" ")
if scheme.lower() != "basic":
raise ValueError("not a Basic credential")
user, colon, password = base64.b64decode(token).decode("utf-8").partition(":")
if not colon:
raise ValueError("no colon in the decoded value")
return user, password
print(parse_basic("Basic YWRtaW46czNjcjN0OnBhc3M="))
これは ('admin', 's3cr3t:pass') を出力します。スキーム名は大文字と小文字を区別しないので小文字で比較し、パスワード内のコロンが残るよう、必ず partition か split(":", 1) を使ってください。パスワードの照合には == ではなく、エンコード済みのバイト列に対する hmac.compare_digest など、定数時間の比較を使います。逆方向には Basic 認証ヘッダー生成ツール を使ってください。Base64 のレシピは Python のページ にもっとあります。
よくある質問
Basic 認証のトークンを手作業でデコードするには?
Basic という単語と空白を取り除き、残りを Base64 デコードして最初のコロンで分割します。Linux や macOS なら、echo 'YWRtaW46czNjcjN0OnBhc3M=' | base64 -d で admin:s3cr3t:pass が出力されます。
「これは Basic 認証ではなく Bearer トークンです」とはどういう意味ですか?
ヘッダーが Bearer スキームを使っているので、ユーザー名とパスワードではなくトークンを運んでいます。Bearer トークンは JWT であることが多いので、JWT デコーダー で開いてください。
デコードしたパスワードにおかしな記号が入るのはなぜですか?
バイト列が、読み取りに使ったものとは別の文字コードで書かれていた可能性があります。文字コード を自動検出、UTF-8、ISO-8859-1 の間で切り替え、16進数のバイト列を確認してください。C2 A3 は UTF-8 の £ で、A3 単独なら Latin-1 の £ です。
ログに Basic 認証のヘッダーが残っていました。どうすればよいですか?
パスワードは漏洩したものとして扱い、変更してください。そのうえで漏洩を止めます。プロキシ、Web サーバー、ログ出力ライブラリの設定で、Authorization ヘッダーを伏せ字にしてください。