京都大学の SSO (KULASIS / KULMS / MyKULINE / PandA) を単一のセッションで叩くための Python クライアントです。初回のサービスアクセス時に必要な IdP ウォークが遅延実行され、それ以降は通常の HTTP クライアントとして使えます。
uv add kuauthfrom kuauth import KyotoUAuth, KULASIS, KULMS, MyKULINE, PandA
auth = KyotoUAuth(
username="a0XXXXXX",
password="your-password",
# onetime_password="424242", # 手元の 6 桁コードを 1 回だけ使う
otp_callback=lambda: input("OTP: "), # 対話的スクリプト
# totp_secret="JBSWY3DPEHPK3PXP", # cron / CI など無人実行
)
print(KULASIS(auth).get("/student/la/top").text) # 教務 (Shift_JIS 自動デコード)
print(KULMS(auth).get("/portal").text) # Sakai LMS
print(MyKULINE(auth).get("/opac/opac_search/").text) # 図書館 OPAC
print(PandA(auth).get("/portal").text) # 旧 LMS (ECS CAS)
auth.close()特定サービス向けの認証済みセッション cookie だけ欲しい場合は service.cookies() を使います。必要に応じて対象サービスのセッションを確立したうえで、そのサービスに送られる cookie を httpx.Cookies として返します。返り値は共有 cookie jar そのものではなく、対象サービス向けに切り出したコピーです。
from kuauth import KyotoUAuth, KULASIS
auth = KyotoUAuth(
username="a0XXXXXX",
password="your-password",
totp_secret="JBSWY3DPEHPK3PXP",
)
cookies = KULASIS(auth).cookies()
print(dict(cookies.items()))
auth.close()OTP が必要かどうかは、アクセスする SP によって変わります。
| Service | Base URL | 認証経路 | OTP |
|---|---|---|---|
| KULASIS | https://www.k.kyoto-u.ac.jp |
auth.iimc (SimpleSAMLphp) | 必要 |
| KULMS | https://lms.gakusei.kyoto-u.ac.jp |
auth.iimc (SimpleSAMLphp) | 必要 |
| MyKULINE | https://kuline.kulib.kyoto-u.ac.jp |
authidp1 (Java Shib IdP) | 不要 |
| PandA | https://panda.ecs.kyoto-u.ac.jp |
ECS CAS | 不要 |
OTP は実際に OTP フォームに到達した時点で初めて解決されます。つまり、MyKULINE や PandA しか使わないスクリプトでは totp_secret 等の指定は省略できます。KULASIS / KULMS を叩く場合のみ、下記のいずれかを渡してください。
| 引数 | 用途 |
|---|---|
onetime_password="424242" |
手元の 6 桁コードを 1 回だけ使う |
otp_callback=lambda: input("OTP: ") |
対話的スクリプト |
totp_secret="JBSWY3DPEHPK3PXP" |
cron / CI など無人実行 |
TOTP シークレットは 京大の多要素認証マニュアル に従って認証アプリを登録する際の QR に埋め込まれた otpauth://totp/...?secret=XXXX&... の secret パラメータです。登録後は QR が再表示されないので、登録画面で控えておくか、一度アプリを解除して再登録してください。
KUMOI (Microsoft 365) はテナント admin consent が必要なため、スコープ外です。
個別エンドポイントのラッパメソッドは持たない設計です。HAR ファイルから URL とフォーム構造を特定すれば、KULASIS(auth).post(...) などを使って呼び出し側で任意のページを叩けます。
KyotoUAuth はパスワード / TOTP シークレット / 事前生成 OTP を bytearray で保持し、close() または with ブロック終了時にゼロで上書きしてから参照を捨てます。Python の str は immutable なので「完璧に消す」ことは原理的に不可能ですが、マスタコピーの寿命が明示的に短くなるので、コアダンプ・スワップ経由の事故確率は下がります。
auth = KyotoUAuth("a0XXXXXX", "secret", totp_secret="JBSWY3DPEHPK3PXP")
print(auth) # KyotoUAuth(username='a0XXXXXX', password=<redacted>, totp_secret=<redacted>, ...)
auth.close()
auth.password # RuntimeError: closed__repr__ は常にマスクされるので、print(auth) / f"{auth}" / トレースバックの locals dump 経由でクレデンシャルが流れることはありません。username だけは IdP に EPPN として渡る情報なのでマスク対象外です。
クレデンシャルをどこから取ってくるか (環境変数 / OS キーチェーン / vault など) はライブラリのスコープ外で、呼び出し側の責任です。keyring から取りたい場合の例:
import keyring
from kuauth import KyotoUAuth
# 事前に: python -m keyring set kuauth a0XXXXXX
# python -m keyring set kuauth-totp a0XXXXXX (KULASIS / KULMS を使う場合)
auth = KyotoUAuth(
"a0XXXXXX",
keyring.get_password("kuauth", "a0XXXXXX"),
totp_secret=keyring.get_password("kuauth-totp", "a0XXXXXX"),
)uv run pytest tests/unit -q # ネットワーク不要
uv run pytest tests/replay -q # respx でモックした E2E実 IdP と実サービスを叩く統合テストは KUAUTH_LIVE=1 を指定しない限り、すべてスキップされます。実行するには以下の環境変数をセットしてください。
KUAUTH_TOTP_SECRET は KULASIS / KULMS のテストに必要です。省略すると auth_with_totp を使うテストだけがスキップされます (MyKULINE / PandA は走ります)。
# bash / Git Bash
KUAUTH_LIVE=1 \
KUAUTH_USERNAME=a0XXXXXX \
KUAUTH_PASSWORD=... \
KUAUTH_TOTP_SECRET=JBSWY3DPEHPK3PXP \
uv run pytest tests/integration -q# PowerShell
$env:KUAUTH_LIVE="1"
$env:KUAUTH_USERNAME="a0XXXXXX"
$env:KUAUTH_PASSWORD="..."
$env:KUAUTH_TOTP_SECRET="JBSWY3DPEHPK3PXP"
uv run pytest tests/integration -qMIT — see LICENSE.