awesome-hacks
Docs

LDAP認証の基礎

LDAPとは何か、ログイン認証との関係、そして社内システムでよく見るログインID存在チェック→権限チェック→LDAP認証の流れを理解する

最終更新:2026/06/15

TL;DR

  • LDAP はユーザー情報(アカウント・所属・権限)を一元管理するためのプロトコル/ディレクトリサービス
  • LDAP認証とは「LDAPサーバーに問い合わせてパスワードを検証する」行為であり、ログイン認証の1手段
  • 社内システムでは「アプリDB側でID存在確認 → 権限チェック → LDAPでパスワード検証」の順で行うことが多い

LDAPとは何か

LDAP(Lightweight Directory Access Protocol)は、ユーザーアカウントや組織情報を木構造(ディレクトリ)で管理し、検索・認証するためのプロトコル

代表的な実装:

製品概要
Active Directory(Microsoft)企業でもっとも普及しているLDAP互換のディレクトリサービス
OpenLDAPオープンソースのLDAPサーバー
AWS Directory ServiceAWSが提供するマネージド型のディレクトリサービス

ディレクトリ構造

LDAPはデータを「エントリ」の木構造で管理する。ルートから部門・グループ・ユーザーという階層で整理される。

dc=example,dc=com               ← ドメイン(ルート)
  └── ou=People                 ← 組織ユニット(部門)
        └── uid=yamada          ← ユーザーエントリ
              ├── cn: 山田 太郎
              ├── mail: yamada@example.com
              ├── memberOf: ou=dev-team
              └── userPassword: (ハッシュ)

各エントリは DN(Distinguished Name) という一意のパスで識別される。
上記の uid=yamada の DN は uid=yamada,ou=People,dc=example,dc=com となる。


LDAP認証とは何か

「LDAP認証」とは、パスワードの検証を自前のDBではなくLDAPサーバーに委ねること。

通常のDB認証との比較:

比較項目DB認証(自前)LDAP認証
パスワードの保管場所アプリのDBLDAPサーバー(AD等)
アカウント管理アプリごとに独立社内で一元管理
退職時の対応各アプリで無効化が必要LDAPを無効にするだけで全システムに反映
向いているシステム一般公開のWebサービス社内システム・イントラ

LDAP認証の流れ(技術的な詳細)

アプリがLDAPサーバーに問い合わせる際の手順:

1. アプリ → LDAPサーバーへ管理用アカウント(サービスアカウント)でバインド(接続)
2. アプリ → ユーザーの DN を検索(uid=yamada を探す)
3. ユーザーの DN が見つかったら、その DN + 入力パスワードで再バインドを試みる
4. 再バインドが成功 → パスワードが正しい(認証成功)
5. 再バインドが失敗 → 認証失敗(パスワード不一致)

パスワード自体はアプリに届かず、LDAPサーバーが照合した結果だけが返ってくる


社内システムでよくある認証フロー

社内業務システムでは、以下の3段階で認証・認可を行うことが多い。

ログイン画面
  │
  ▼
① ログインID存在チェック(アプリDB)
  │
  ▼
② ログインIDの権限チェック(アプリDB)
  │
  ▼
③ 社内LDAP認証(LDAPサーバー)
  │
  ▼
ログイン成功

① ログインID存在チェック(アプリDB)

アプリ独自のDBを参照し、入力されたログインIDがこのシステムに登録されているかを確認する。

SELECT * FROM users WHERE login_id = :loginId AND deleted_at IS NULL

なぜこのチェックが必要か?
LDAPは全社員のアカウントを管理しているが、このシステムを使える人は限られる場合がある(部署限定・契約ユーザーのみ等)。LDAPに問い合わせる前にシステム固有の登録チェックを挟む。


② ログインIDの権限チェック(アプリDB)

登録済みであることを確認した上で、そのユーザーがこのシステムにアクセスできる状態かを確認する。

確認すべき内容の例:

  • アカウントが有効か(ロックされていないか)
  • アクセス可能な期間内か(有効期限)
  • 必要なロール・権限を持っているか
SELECT role, is_active, expires_at FROM users WHERE login_id = :loginId

なぜLDAP認証の前に行うか?
LDAPへの問い合わせはネットワーク越しの処理になるため、アプリDB側で弾けるものは先に弾くことで不要な外部通信を減らせる。また、エラーメッセージの粒度を細かくしやすい(「このシステムに権限がありません」などのメッセージを返せる)。


③ 社内LDAP認証(LDAPサーバー)

①②を通過したユーザーに対して、入力されたパスワードをLDAPサーバーで検証する。

アプリ → LDAPサーバーへ接続
     → uid=yamada,ou=People,dc=example,dc=com で検索
     → 見つかったDNと入力パスワードでバインド試行
     → 成功 → ログイン完了
     → 失敗 → 認証エラー(パスワードが違う or アカウントがLDAPでロックされている)

パスワードの管理責任がLDAP側にあるため、アプリはパスワードを保存せず、変更・ロック管理もLDAP(Active Directory等)の管理者に委ねられる。


各ステップのエラーハンドリング

ステップ失敗の意味返すべきレスポンス
①ID存在チェックこのシステムに未登録「IDまたはパスワードが違います」(情報を明かさない)
②権限チェック有効期限切れ・ロック等「このアカウントは使用できません」など状況に応じて
③LDAP認証パスワード不一致 or LDAPロック「IDまたはパスワードが違います」

①と③でメッセージを分けると「このIDが登録されているか」が攻撃者に分かってしまうため、通常は①③は同じメッセージにまとめる。


よくある落とし穴

LDAPサーバーがダウンしたときの設計を忘れる
LDAP認証は外部サービスへの依存になる。LDAPが落ちると全員ログイン不能になる。タイムアウト設定・フォールバック・障害時の通知を考慮する。

LDAPへの接続をサービスアカウントなしでやろうとする
匿名バインドを許可していないLDAPサーバーは多い。DN検索のためのサービスアカウント(bind dn / bind password)が必要になるため、認証情報の安全な管理(環境変数・Secrets Manager等)が必要。

ユーザーの入力をそのままLDAPクエリに使う(LDAPインジェクション)
uid=*)(uid=* のような文字列を入力されると、意図しない検索結果が返ることがある。ユーザー入力の特殊文字をエスケープしてからLDAPクエリに組み込む。

LDAPとアプリDBのアカウント状態が乖離する
LDAPで無効化されたのにアプリDB側のユーザーが有効のまま(またはその逆)になりうる。権限チェックをどちら優先にするか・同期の仕組みをどうするかを設計段階で決めておく。


関連