アカウント変更とセッションの失効
無効化要求とアプリ側への反映を、それぞれの保存状態から確認します。
説明
IdPのアカウント、アプリへ同期した利用者、既存のセッションは別の状態です。IdP側で無効化したとき、どこへいつ反映するかによってアクセスが止まる時点が変わります。
固定の台帳で、無効化前、IdP側の変更後、同期後を比較します。セッション単独の期限と緊急用経路の記録も確認します。
無効化要求とアプリ側への反映を、それぞれの保存状態から確認します。
1三つの保存状態を読む
directoryがIdP、app_userがアプリ、sessionがログイン状態です。
from sp11 import *
from sp02 import show三つの保存状態を読む
db=connect()
show(db,"SELECT * FROM directory ORDER BY id")
show(db,"SELECT * FROM app_user")
show(db,"SELECT * FROM session")u7は両側で有効、s7は200まで有効です。emergencyはアプリの通常同期対象に含めていません。
2変更前のアクセスを確かめる
アプリは自身の利用者状態も参照します。
print(access変更前のアクセスを確かめる(db,'s7',120))editorとして利用できます。この結果は固定アプリモデルの認可条件です。
3IdP側だけを無効にする
変更世代も2へ進めます。
db.execute("UPDATE directory SET active=0,version=2 WHERE id='u7'")
print(accessIdP側だけを無効にする(db,'s7',130))
show(db,"SELECT d.active AS idp,a.active AS app FROM directory d JOIN app_user a USING(id)")IdPは0、アプリは1で、まだeditorです。別データベースへの変更が自動的に同時反映されるわけではありません。
4同期差分をアプリへ反映する
世代の進んだu7の状態を更新します。
db.execute("UPDATE app_user SET active=(SELECT active FROM directory WHERE id='u7'),version=2 WHERE id='u7'")
print(access同期差分をアプリへ反映する(db,'s7',140))
show(db,"SELECT id,active,version FROM app_user")アプリ側も0となりdeniedです。実際のSCIM連携では同期処理の成否とアプリで読み直した状態を照合します。
5残ったセッションを調べる
アカウント無効化でアクセスは止まりましたが、セッション行も確認します。
show残ったセッションを調べる(db,"SELECT id,active,expires FROM session")
db.execute("UPDATE session SET active=0 WHERE subject='u7'")
show(db,"SELECT id,active FROM session")行自体は有効のまま残っていたため明示的に失効させました。アカウントを再有効化した際の古いセッション再利用も考慮します。
6再有効化しても古いセッションを復活させない
アプリ利用者だけを有効に戻します。
db.execute("UPDATE app_user SET active=1,version=3 WHERE id='u7'")
print(access再有効化しても古いセッションを復活させない(db,'s7',150))deniedのままです。利用者の復帰と古いセッションの再開は分けて管理できます。
7緊急用経路の操作を監査する
固定の緊急操作を記録します。
db.execute("INSERT INTO audit VALUES (150,'emergency','break-glass','reviewed access')")
show緊急用経路の操作を監査する(db,"SELECT * FROM audit")通常同期から外れた経路も、利用した主体・時刻・結果を残します。通常の無効化と同じ範囲に自動で含まれるとは考えず、別に棚卸しします。
まとめ
IdP、同期先、セッションの保存状態を分けます。
同期の完了後にアプリ側を読み直します。
緊急用経路も監査と棚卸しの対象にします。
操作履歴と解説を振り返れます。
Python 3.15 / 固定ID・認可条件・SQLite
from sp11 import *
from sp02 import show
db=connect()
show(db,"SELECT * FROM directory ORDER BY id")
show(db,"SELECT * FROM app_user")
show(db,"SELECT * FROM session")id | active | role | version emergency | 1 | admin | 1 u7 | 1 | editor | 1 id | active | role | version u7 | 1 | editor | 1 id | subject | expires | active s7 | u7 | 200 | 1
print(access(db,'s7',120))editor
db.execute("UPDATE directory SET active=0,version=2 WHERE id='u7'")
print(access(db,'s7',130))
show(db,"SELECT d.active AS idp,a.active AS app FROM directory d JOIN app_user a USING(id)")editor idp | app 0 | 1
db.execute("UPDATE app_user SET active=(SELECT active FROM directory WHERE id='u7'),version=2 WHERE id='u7'")
print(access(db,'s7',140))
show(db,"SELECT id,active,version FROM app_user")denied id | active | version u7 | 0 | 2
show(db,"SELECT id,active,expires FROM session")
db.execute("UPDATE session SET active=0 WHERE subject='u7'")
show(db,"SELECT id,active FROM session")id | active | expires s7 | 1 | 200 id | active s7 | 0
db.execute("UPDATE app_user SET active=1,version=3 WHERE id='u7'")
print(access(db,'s7',150))denied
db.execute("INSERT INTO audit VALUES (150,'emergency','break-glass','reviewed access')")
show(db,"SELECT * FROM audit")t | subject | route | result 150 | emergency | break-glass | reviewed access
演習完了