SAML認証はシングルサインオンを実現するためのプロトコルの一種です。
そもそもシングルサインオンとは 特定のサービスでのログインにより紐づけられた他の複数のサービスを利用できるようにする仕組みのことです。
たとえばある会社でMicrosoft Officeを中心に据えている場合、Microsoftが提供するEntraIDでのログインで、事前に紐づけられた他のサービスにログインできるような仕組みを整えれます。
ここで、EntraIDのような認証基盤のことを IdP と呼び、
SAMLなどの標準プロトコルを介して、連携された社内アプリへ個別にパスワードを入力することなくアクセスできるようになります。
ここで、連携された社内アプリのことをSP と呼びます。
各略称について
- IdP : Identity Provider : 共通の認証基盤
- SP : Service Provider : それを利用するアプリ
SAMLの実装方法は6種類あります。
- HTTP Redirect Binding
- HTTP POST Binding
- HTTP Artifact Binding
- SAML SOAP Binding
- Reverse SOAP (PAOS) Binding
- SAML URI Binding
6種類あるとは言いましたが、実際に業務で使うのはHTTP Redirect BindingとHTTP POST Bindingの2種類です。
HTTP Redirect Bindingの流れ手順
HTTP Redirect Bindingは名前の通りリダイレクトを繰り返す方式です。
ざっくり言うと以下の流れの通りで、IdPとSPを一往復しています。
ユーザーがSPにアクセス -> IdPへリダイレクト -> さらにSPへリダイレクトされ、トークンが付与されている。
各フェーズを説明します。
- アクセスとリクエスト
- ユーザーがブラウザで SP にアクセスします。
- SPは「このユーザーはまだログインしていない」と判断し、SAML認証リクエスト(AuthnRequest)を作成します。
- SPはそのリクエストをURLのクエリパラメータに含め、IdPのログイン画面へHTTP Redirect(302応答)させます。
- ここは各アプリケーション(SP)で実装が必要。
- IdPでの認証
- ブラウザはIdPのログイン画面に飛ばされます。
- ID・パスワードの入力などによりIdPで認証を行います。
- このフェーズで、仮に他のSPでIdPの認証が完了していた場合は認証済みであるとし、必要な情報を速やかに渡してSPへリダイレクトされます。
- 渡す方法は SPのエンドポイントにトークンなどをクエリパラメータに(つまりurlの末尾に?や&で繋げるやつ)乗せる方法です。
- ログイン完了
- SPはブラウザを介してSAMLレスポンスを受け取る
- このトークンには「このユーザーが誰であるか」を証明するための重要な情報が入っており、
「このユーザーが誰であるか」を証明するための重要な情報であるだけでなく、トークンの偽造は実質的に不可能である。(ユーザーが手作業で偽の情報を仕込んだSAMLレスポンスを作成し、SPを突破してログインすることは事実上不可能)
- ただし、トークンが偽造されていないかどうかのチェックの実装は必要
Keycloakによる実演
keycloakによるSAML対応サンプルアプリ
手順
ソースコードは以下から取得します。
git clone https://github.com/minegishirei/keycloak_sample.git
1. 実行環境用意
./run.sh を実行すると、keycloak/SAML使用サンプルサービスが実行されます。
2. Keycloakの基本設定
ここではIdPであるKeycloakの設定を行います。


- 左上メニューから Create Realm を開き、Nameを demo にして作成します。
ここで、Realm はリアムと呼び、ユーザー、資格情報、ロール、グループなどをひとまとめにして管理するための独立した認証・認可の領域のことを指します。
このRealmには複数のSPを対応させることができ、SSOの境界はこのRealmであることからSSOの最小単位はRealmであると言えます。

- Users メニューからユーザー testuser を追加し、Credentials タブでパスワードを設定します。


3. サンプルアプリ登録
SAML対応サンプルアプリをKeycloakへ登録します。
- Realm「demo」内の Clients > Create client をクリックします。

ここでのClientとはKeycloak独自の用語で SAMLプロトコルにおけるSPに該当します。
- Client type に SAML、Client ID に my-python-sp と入力して進みます


この /saml/acs は以下のようなコードで実装しました。
このエンドポイントに対しては POSTリクエストを受信するもので、IdPが認証成功の証明をPOSTで送り返してくる宛先 として機能します。
from onelogin.saml2.auth import OneLogin_Saml2_Auth
SAML_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'saml')
def init_saml_auth(req):
auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH)
return auth
def prepare_flask_request(request):
return {
'https': 'on' if request.scheme == 'https' else 'off',
'http_host': request.host,
'script_name': request.path,
'get_data': request.args.copy(),
'post_data': request.form.copy()
}
@app.route('/saml/acs', methods=['POST'])
def saml_acs():
req = prepare_flask_request(request)
auth = init_saml_auth(req)
auth.process_response()
errors = auth.get_errors()
if not errors:
session['samlUserdata'] = auth.get_attributes()
session['samlNameId'] = auth.get_nameid()
return redirect('/')
else:
return f"認証エラー: {', '.join(errors)}", 400
このコードにおいて OneLogin_Saml2_Auth は以下のことを実施しています。
- SAML設定ファイルの自動読み込み
- リクエストデータの解析と検証
- XML署名の検証と改ざん防止
- 有効期限(タイムスタンプ)のチェック
このオブジェクトを利用し、メイン関数にて以下のチェックプロセスを実施しています。
auth.process_response() : 署名検証・有効期限チェック・エラー判定を実施。何かあればここで例外が発生
auth.get_errors() : 署名エラー、期限切れなどがあれば返却される
問題なければ auth.get_attributes() / auth.get_nameid() を使ってKeycloakに登録されているユーザーのメールアドレス、名前、IDといった属性情報を安全に取り出せるようになります。
SAMLの設定ファイルは以下のとおりです。
{
"strict": false,
"debug": true,
"sp": {
"entityId": "my-python-sp",
"assertionConsumerService": {
"url": "http://localhost:5001/saml/acs",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
},
"singleLogoutService": {
"url": "http://localhost:5001/saml/sls",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
},
"idp": {
"entityId": "http://localhost:8080/realms/demo",
"singleSignOnService": {
"url": "http://localhost:8080/realms/demo/protocol/saml",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"singleLogoutService": {
"url": "http://localhost:8080/realms/demo/protocol/saml",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"x509cert": ""
},
"security": {
"authnRequestsSigned": false,
"logoutRequestSigned": false,
"logoutResponseSigned": false,
"wantMessagesSigned": false,
"wantAssertionsSigned": false
}
}
アプリからKeycloakへログインしに行くために使われます。
idp セクションのURLに注目してみると、 realms/demoというパスが含まれており、 Keycloakの中に demo という名前の Realm が作られていること。
そのRealm内のSAMLエンドポイントに対して、このPythonアプリが認証を依頼しにいくこと。この2点がわかります。
ちなみに末尾の /protocol/saml はSAMLプロトコルで決められたエンドポイントです。
urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect もSAMLで決められたプロトコルで、これこそが HTTPリダイレクト を表します。
これらの情報は、Keycloakからリダイレクトされた情報をどこで受け取るかを指定するために使われます。
bindingの urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST もSAMLで決められたプロトコルで、これこそが HTTP-POST バインディング を表します。
AuthnRequests signedをオフに
タブ : Signature and Encryption を確認し Client signature required をオフにする。


注意 : この設定は本番環境では行わないでください。
4. 動作確認

page:https://minegishirei.hatenablog.com/entry/2026/08/19/063437