多要素認証(MFA:Multi-Factor Authentication)は、性質の異なる複数の認証要素を組み合わせて本人確認を強くする方式です。この記事では、知識・所有・生体という3つの要素の分類から、TOTP/HOTP・プッシュ通知・FIDO2/WebAuthnといった実装方式の違い、二段階認証との線引き、そしてフィッシング中継攻撃に耐えられる方式の見分け方と採用判断までを、実装者が設計に落とせる粒度で整理します。サーバ側のTOTP検証コードとWebAuthnの登録オプションもそのまま写せる形で載せました。自社の会員基盤や業務システムにMFAを組み込む開発者、認証強化の方式を選定する情シス担当が対象です。
まとめ:MFAは異なる2要素以上で本人確認を固める認証方式と実装の要点
MFAは、知識(パスワード・PIN)、所有(スマホ・セキュリティキー)、生体(指紋・顔)という3系統のうち、種類の違う要素を2つ以上重ねてログインを成立させる仕組みです。パスワードに加えてSMSコードを求める構成が最も普及していますが、SMSやワンタイムパスワードは中継型のフィッシングで突破され得るため、方式ごとに強さが異なる点を実装前に押さえます。
実装の勘所は方式選定にあります。手軽さで選ぶならスマホアプリのTOTPやプッシュ通知、突破されにくさで選ぶなら公開鍵暗号を使うFIDO2/WebAuthn(パスキー)という切り分けになります。FIDO2は認証操作をサイトの正規オリジンに暗号的に縛るため、偽サイトへ誘導する攻撃を原理的に受け付けません。自社サービスへ組み込むなら、まずログイン画面へTOTPかパスキーを足し、機微な操作の前で再認証を挟む二段構えが現実的な設計です。
手を動かす順序も先に示します。TOTPは RFC 6238 の30秒ステップとHMAC計算を写せば実装できます。パスキーは W3C Web Authentication Level 3(2026年8月25日にW3C勧告)の登録・認証オプションを組み立て、サーバ側でオリジンとチャレンジを照合する流れです。本記事の後半に、この2つのコードを載せています。
多要素認証の基本と知識・所有・生体という3つの認証要素の考え方
MFAを理解する近道は、「認証要素」という考え方を押さえることです。要素の種類さえ整理できれば、方式の違いも採用判断もこの分類の上に乗せて考えられます。MFAはより大きな枠組みの一部であり、認証・ID管理の全体像(MFA・SSO・OIDC・IDaaS)から他方式との位置づけを俯瞰できます。
知識・所有・生体の3要素と「異なる要素を重ねる」というMFAの定義
認証要素は大きく3系統に分かれます。本人だけが知っている情報を使う知識要素、本人だけが持つ物を使う所有要素、本人の身体的特徴を使う生体要素です。パスワードやPINは知識、スマホやICカード・セキュリティキーは所有、指紋や顔は生体にあたります(詳しくは生体認証とはを参照)。
MFAの定義は「この3系統のうち、種類の異なる要素を2つ以上組み合わせること」です。パスワードとPINを両方求めても、どちらも知識要素なので多要素にはなりません。異なる系統を重ねることで、片方が漏れてももう片方が壁として残る、という設計思想が土台になります。米国の NIST SP 800-63B(SP 800-63 第4版系・2025年8月時点の公開版)も、認証保証レベルAAL2以上の条件として異なる2要素の提示を置いています。
| 認証要素 | 意味 | 具体例 |
|---|---|---|
| 知識要素 | 本人が知っている情報 | パスワード・PIN・秘密の質問 |
| 所有要素 | 本人が持っている物 | スマホ・セキュリティキー・ICカード |
| 生体要素 | 本人の身体的特徴 | 指紋・顔・虹彩 |
二段階認証・二要素認証との違いを「段階の数」と「要素の種類」で線引き
混同されやすいのが二段階認証(2SV)との違いです。二段階認証は「認証を2回の段階に分ける」ことを指し、パスワードの後にもう一度パスワードを聞く構成も含みます。この場合は知識要素だけの2段階で、要素は1つのままです。一方で多要素認証は「異なる要素を重ねる」ことを条件にするため、二段階かどうかではなく要素の種類が判定軸になります。
二要素認証(2FA)は、要素をちょうど2つ使う多要素認証の一形態です。実務では「パスワード+スマホのコード」が2FAであり同時にMFAでもある、という重なりで理解して問題ありません。段階数と要素数の切り分けは、二段階認証とは?二要素認証・多要素認証との違いと企業の導入判断を解説で導入判断の観点から整理しています。
MFAの実装方式:TOTP・プッシュ通知・FIDO2/WebAuthnの仕組みと差
所有要素をどう実装するかで、MFAの方式は複数に分かれます。実装では、この方式差が利便性と突破されにくさのトレードオフに直結するため、仕組みの理解が選定の前提になります。
TOTP・HOTPの仕組みとワンタイムパスワードを支える共有鍵
スマホの認証アプリで6桁コードを出す方式の中身が、TOTPとHOTPです。生成アルゴリズムやotpauth形式のURI、クロックずれの実装まで踏み込んだ解説はOTPとは?HOTP/TOTPの生成アルゴリズムと実装・SMS OTPの限界を実装視点で解説を参照してください。TOTP(Time-based One-Time Password)は現在時刻と共有鍵からコードを生成し、既定では30秒の区切りで切り替わります。この30秒という既定値と、時刻の起点をUnix時間の0秒に置く決まりは RFC 6238 に書かれています。
HOTP(HMAC-based One-Time Password)はカウンタ値を基にする方式で、TOTPはこのHOTPの時刻版という関係です。6桁を切り出す動的truncationの手順は RFC 4226 の定義がそのまま使われます。どちらもサーバと端末が同じ秘密鍵(シード)を持ち、同じ計算をして値を突き合わせます。QRコード登録の実体は、このシードの受け渡しです。実装ではシードをサーバ側で暗号化保管し、時刻同期のずれを許容する窓(ウィンドウ)を狭めに設定するのが定石になります。方式の種類と選び方はワンタイムパスワードとは?仕組みと種類・企業が選ぶ導入方式を解説にまとめています。
プッシュ通知による承認とMFA疲労攻撃を防ぐ番号照合という対策
プッシュ通知方式は、ログイン時にスマホへ「承認しますか」の通知を送り、タップで認証を通す仕組みです。コードを打ち込む手間がなく利便性は高いものの、攻撃者が連続でログインを試みて通知を浴びせ、ユーザーが根負けして承認してしまうMFA疲労攻撃(プロンプト・ボミング)という手口が知られています。
この対策として広がっているのが番号照合(number matching)です。ログイン画面に表示された数字をスマホ側でも入力させ、通知を漫然と承認できないようにします。Microsoft Entra IDでは番号照合がAuthenticatorの全プッシュ通知で有効となり、テナント側で無効化する選択肢は残っていません。同ドキュメントは、Apple WatchなどウェアラブルではMFA承認が使えなくなる点も明記しています。自前でプッシュ方式を作る場合も、番号照合の有無を選定の必須チェック項目に置く判断が堅実です。
FIDO2/WebAuthnとパスキーが公開鍵暗号で実現する認証
突破されにくさで一段抜けるのがFIDO2です。FIDO2はブラウザ向けのWebAuthnと、認証器と通信するCTAPの組み合わせで成り立つ仕様です。両者の版と関係は FIDO Allianceの仕様一覧で確認できます。仕組みの核は公開鍵暗号で、端末内の安全な領域に秘密鍵を保持し、サーバには公開鍵だけを預けます。ログインのたびにサーバが出す乱数(チャレンジ)に端末が署名を返し、サーバが公開鍵で検証する流れです。
秘密鍵が端末外へ出ないため、サーバ側が漏えいしても認証情報そのものは盗まれません。この署名操作は登録したサイトのオリジンに縛られており、別ドメインの偽サイトでは成立しない設計になっています。パスキー(Passkey)はこのFIDO2認証情報を指し、端末間で同期する同期型と、セキュリティキーに固定する端末束縛型に分かれます。所有要素の端末と、ロック解除のPINや生体を合わせて、1つのパスキーだけでMFA相当の強度を出せる点が特徴です。仕様と導入判断の全体像はFIDO認証・FIDO2とは?仕組みとパスキー・導入判断を解説、利用者側の使い勝手や社内展開の論点はパスキー認証とは?仕組み・パスワードとの違い・企業の導入判断を解説で扱っています。
MFAをコードで実装する手順:TOTP検証とWebAuthn登録の設定値
方式の理屈が分かっても、実際に詰まるのはサーバ側の検証コードです。ここではTOTPとWebAuthnについて、そのまま写して動かせる最小の実装を示します。ライブラリを使う場合も、内部でこの計算と照合が走っていると分かっていれば、パラメータの意味を取り違えずに済みます。
TOTP検証をサーバ側で実装する手順と時刻ずれを許容する窓の決め方
TOTPの検証は、外部依存なしで書けます。共有鍵とUnix時刻からHMAC-SHA1を計算し、下位4バイトを取り出して6桁に丸めるだけです。次のコードは RFC 6238 の既定値(ステップ30秒・6桁・SHA-1)に合わせています。
# RFC 6238 準拠のTOTP生成と検証(Python 3系・標準ライブラリのみ)
import hmac
import hashlib
import struct
import time
def totp(secret, when, step=30, digits=6):
counter = divmod(when, step)[0]
mac = hmac.new(secret, struct.pack("!Q", counter), hashlib.sha1).digest()
offset = mac[19] & 0x0f
value = struct.unpack("!I", mac[offset:offset + 4])[0] & 0x7fffffff
return str(value % (10 ** digits)).zfill(digits)
def verify(secret, entered, window=1):
# 前後1ステップ(計90秒)まで時刻ずれを許容する
now = int(time.time())
for drift in range(-window, window + 1):
candidate = totp(secret, now + drift * 30)
if hmac.compare_digest(candidate, entered):
return True
return False
実装で判断が要るのは window の値です。端末の時計ずれを吸収するために前後1ステップを許容するのが一般的で、この場合は同時に有効なコードが3つ存在します。窓を2や3へ広げると総当たりの成功確率が比例して上がるため、広げる前に「試行回数の上限」を先に入れてください。5回連続で失敗したら当該ユーザーの検証を一定時間止める、という単純な制限が効きます。
もう1点、使用済みコードの再利用防止も忘れがちです。hmac.compare_digest で照合の時間差を潰しても、同じ6桁を30秒以内に再送されれば通ってしまいます。検証に成功したカウンタ値をユーザーごとに保存し、同じ値での再検証を拒否する処理を足してください。
WebAuthn登録オプションの設定値とパスキーを必須にする指定方法
パスキーの登録は、サーバが組み立てたオプションをブラウザの navigator.credentials.create に渡すところから始まります。MDNのWeb Authentication APIの解説にある通り、実装上の分かれ目は3つの設定値に集約されます。
{
"rp": { "id": "example.com", "name": "Issoh Members" },
"user": { "id": "BASE64URL_16BYTE_RANDOM",
"name": "[email protected]",
"displayName": "会員 太郎" },
"challenge": "BASE64URL_32BYTE_RANDOM",
"pubKeyCredParams": [
{ "type": "public-key", "alg": -7 },
{ "type": "public-key", "alg": -257 }
],
"authenticatorSelection": {
"residentKey": "required",
"userVerification": "required"
},
"attestation": "none",
"timeout": 60000
}
rp.id は認証情報を縛るドメインで、ここを間違えると別サブドメインでパスキーが使えません。サービスが id.example.com と shop.example.com にまたがるなら、rp.id は共通の親ドメインに置く設計です。residentKey を required にすると認証器側に鍵が常駐し、ユーザー名の入力なしでログインできる形になります。userVerification を required にすれば、PINか生体によるロック解除が必須になり、所有要素だけの1要素で終わらせない構成を強制できます。
alg の -7 はES256、-257 はRS256を指すCOSEの識別子です。両方を並べておくと、ES256のみ対応の認証器とWindows Helloのような環境の双方を受けられます。attestation は none が既定で、認証器の機種証明を集める必要がなければ変えないのが無難です。集めると個人情報保護の検討事項が増えます。
WebAuthn認証で照合する4項目とオリジン検証を外さない実装手順
登録より事故が起きやすいのは、認証レスポンスの検証側です。WebAuthn Level 3は検証手順を段階で規定していますが、自前実装で抜けやすい箇所は決まっています。次の照合を外すと、MFAを入れたつもりで守りが成立しません。
# 認証レスポンス検証で外してはいけない項目
assert client_data["type"] == "webauthn.get"
assert client_data["challenge"] == stored_challenge # 使い捨て・再利用は拒否
assert client_data["origin"] == "https://www.example.com"
assert auth_data.rp_id_hash == sha256(b"example.com")
assert auth_data.flags.up and auth_data.flags.uv # UP=存在確認 UV=本人確認
assert verify_signature(public_key, auth_data, client_data_hash)
assert sign_count_increased(auth_data.sign_count, stored_count)
要になるのは3行目のオリジン照合です。ここを「文字列に example.com が含まれるか」で済ませると、攻撃者が用意した example.com.evil.test のようなドメインを通してしまいます。完全一致で比較してください。チャレンジも同様で、サーバ側で発行した乱数をセッションに紐づけ、一度使ったら破棄します。
署名カウンタは扱いに注意が必要です。同期型パスキーは複数端末で鍵を共有するため、カウンタが常に0のまま返ってくる実装もあるためです。増加していないことを一律にエラー扱いにすると正規ユーザーが弾かれるので、0が返る認証器は例外として扱い、0以外を返す認証器にだけ増加チェックを適用する分岐にします。クラウド側の実装を確認したい場合は、AWS IAMのMFAドキュメントがパスキーとセキュリティキーの扱いを分けて記述しており、設計時の参照先になります。
耐フィッシングMFAの判定軸とAiTM攻撃で試される方式の強さ
MFAを入れても突破される事例が増えており、「MFAならどれも同等」という前提は成り立ちません。ここでは方式の強さを分ける判定軸を示し、自社の要件に対してどこまでの方式が要るかを判断できるようにします。
中継型フィッシング(AiTM)がSMS・TOTP・プッシュを抜く理由
方式の強さを分けるのが、中継型フィッシング(AiTM:Adversary-in-the-Middle)への耐性です。攻撃者は本物そっくりの偽サイトを挟み、ユーザーが入力したパスワードとワンタイムコードをその場で本物のサイトへ中継します。SMSやTOTPのコード、承認するだけのプッシュ通知は、入力先が偽サイトかどうかを判別できないため、リアルタイムに中継・再送されると突破されます。
これに対しFIDO2/WebAuthnは、署名がアクセス中のオリジンに暗号的に紐づくため、偽ドメイン上では正しい署名が生成されません。攻撃者が値を中継しても検証が通らず、中継型の攻撃が原理的に不成立になります。この「オリジンに縛られるか」が、耐フィッシングと呼べるかどうかの分水嶺です。前章のコードで言えば、3行目と4行目がその保証を担っている箇所にあたります。
| 方式 | 要素 | 中継型フィッシング耐性 |
|---|---|---|
| SMSコード | 所有 | なし(中継で突破され得る) |
| TOTPアプリ | 所有 | なし(中継で突破され得る) |
| プッシュ通知 | 所有 | 限定的(番号照合で緩和) |
| FIDO2/パスキー | 所有+知識/生体 | あり(オリジン縛りで不成立) |
2026年時点の規格動向と耐フィッシング方式を求める規制の基準
規格側の状況は2026年に入って一段固まりました。Web Authentication Level 3 は2026年8月25日付でW3C勧告となり、ブラウザ実装が参照する版がLevel 2から更新されています。自社の実装や社内標準がLevel 2を前提に書かれているなら、参照先を差し替える時期です。
規制・ガイドラインの側も、耐フィッシング方式を基準に据える方向で一致しています。NIST SP 800-63B(2025年8月時点の公開版)は、最高位のAAL3で耐フィッシング認証子を必須と定め、AAL2でも耐フィッシング性を推奨、連邦政府の企業内利用では必須と整理しました。同文書は付録で同期型パスキーがAAL2の各要件をどう満たすかを条文単位で説明しており、パスキー採用の社内説明に転用できます。カード業界のPCI DSS(v4系)も管理系アクセスでのMFAを要件化しています。
これらは版が更新され続けるため、導入時点の最新版を一次情報で確認する運用が前提です。ただし方向性は一貫しており、機微な情報や管理者権限を扱う経路では、TOTPやSMSで足りるという想定を置かない設計が無難でしょう。境界防御を前提にしない考え方の全体像はゼロトラストとは?境界型防御との違い・NIST7原則と導入判断を解説で整理しています。
MFA導入の判断:方式の採用条件と見送るべき場面を切り分ける
方式が出そろったところで、採用判断を条件で言い切ります。全経路に最強の方式を敷くのは費用対効果が崩れやすく、経路の機微さに応じた配分が現実解です。自社サービスへ組み込む設計段階で、ここを判断材料にしてください。
利便性で選ぶTOTPと突破耐性で選ぶパスキーを使い分ける条件
方式は経路のリスクで選び分けます。社内ツールや一般会員向けログインで、まず「パスワードのみ」から一段上げたい段階なら、導入コストの低いTOTPアプリが妥当な出発点です。ユーザー側は手持ちのスマホアプリで完結し、サーバ側も前掲の30行程度で検証まで書けます。プッシュ通知を足すなら番号照合を必須にします。
一方で、管理者アカウント、決済や個人情報を扱う経路、標的型攻撃の想定が要る業務では、中継型に耐えるFIDO2/パスキーを採用条件に置きます。ここでTOTPに留めると、中継型フィッシング一発で多要素の壁が意味を失うためです。管理用アカウントの認証情報が取られて利用者の保存データまで読まれた事例と、MFAを伴わない管理操作をIAMポリシーで拒否する設定例は楽天ドライブの不正アクセスと管理用アカウントを守る認証で扱っています。全ユーザーへ一律強制が難しい場合は、高リスク操作の前だけパスキー再認証を挟む段階適用(ステップアップ認証)で現実的に折り合いをつけます。
MFAを見送る・後回しにすべき場面とリカバリー設計での注意点
逆に、MFAの一律導入を急がない判断が要る場面もあります。認証を伴わない公開情報の閲覧だけのサービスや、外部のIDaaSへ認証を委譲していて自前で認証を持たない構成なら、自SPにMFAを作り込む必要は薄いでしょう。この場合は委譲先のIdPでMFAを効かせ、自SPは委譲先の選定に労力を割く方が筋が通ります。
採用する場合に見落とされがちなのがリカバリー設計です。スマホ紛失やセキュリティキー故障で認証器を失うと、正規ユーザーがロックアウトされます。バックアップコードの発行、複数認証器の登録、本人確認を伴う再登録フローを最初から用意しないと、運用開始後に問い合わせが集中します。パスキーの端末束縛型を使うなら、同期型やローミング認証器との二本立てを設計に含めておく判断が現実的です。自社の会員基盤や業務システムへMFAを組み込む設計・実装は、認証基盤・ID管理システム開発として認証連携ごと受託しています。方式選定とリカバリー設計の段階からご相談ください。
よくある質問
MFAの導入検討でよく挙がる疑問を、実装者の視点で簡潔にまとめます。
多要素認証と二段階認証は同じ意味ですか?
同じではありません。二段階認証は認証を2つの段階に分けることを指し、パスワードを2回聞くような同一要素の構成も含みます。多要素認証は知識・所有・生体という異なる要素を重ねることが条件で、判定軸は段階数ではなく要素の種類です。「パスワード+スマホのコード」は両方に該当します。
MFAはパスワードなしでも実現できますか?
可能です。パスキー(FIDO2)は、認証器という所有要素と、その端末のロック解除に使うPIN(知識)や生体を組み合わせるため、パスワードを使わずに単体でMFA相当の強度を出せる仕組みとなります。実装上は登録オプションの userVerification を required にして、所有要素だけで通らない設定が必要です。パスワードレスと多要素は両立し、むしろ耐フィッシングの観点ではパスワードを外した構成が有利になります。移行が完了するまでのパスワード運用はパスワード管理のベストプラクティスにまとめています。
SMSによるMFAは安全ではないのですか?
「パスワードのみ」よりは確実に強くなりますが、方式としては最も弱い部類です。SIMスワップでの番号乗っ取りや、中継型フィッシングでのコード横取りが成立し得ます。導入の第一歩としては有効でも、管理者権限や機微な情報を扱う経路では、TOTPやFIDO2など、より強い方式への移行を前提に置くのが安全でしょう。
TOTPアプリとセキュリティキーはどちらを選ぶべきですか?
経路のリスクで分けます。一般ログインの底上げなら、導入が軽く追加デバイス不要のTOTPアプリが出発点です。中継型フィッシングの想定が要る管理者や決済経路では、オリジンに縛られて偽サイトで成立しないFIDO2セキュリティキーやパスキーを選びます。全社一律ではなく、経路ごとに方式を変える段階適用が現実的です。選定の材料はパスキー認証とは?仕組み・パスワードとの違い・企業の導入判断を解説にまとめています。
MFAはSSOやSAML/OIDCと併用できますか?
併用が前提になります。SSOは1度のログインを複数サービスで使い回す仕組みで、そのログインの本人確認を強くするのがMFAです。IdP側でMFAを効かせれば、SAMLやOIDCで連携する各サービスにMFAの効果が波及します。認証の連携規格とMFAは競合せず、役割が異なると理解してください。
関連記事
- 二段階認証とは?二要素認証・多要素認証との違いと企業の導入判断を解説:段階と要素の違い、導入可否の判断軸を経営・運用の視点でまとめた判断ハブです。
- ワンタイムパスワードとは?仕組みと種類・企業が選ぶ導入方式を解説:MFAの所有要素で使うOTPの方式と選び方を具体的に整理しています。
- SAMLとは?認証フロー・IdP/SPの仕組みとOAuth・OIDCとの使い分けを実装視点で解説:MFAと組み合わせるSSOのフェデレーション規格。IdP/SPの仕組みを解説しています。
- OIDC(OpenID Connect)とは?仕組み・OAuthとの違いをわかりやすく解説:MFAを効かせたIdPが発行するIDトークンの認証層。新規サービスの認証基盤で選ばれます。
- OAuth 2.0とは?仕組み・認可フローと認証・認可の違いをわかりやすく解説:認証と対になる「認可」の規格。MFAで固めた本人性の先にある権限委譲を扱います。