Automate Canvas API token refresh by replaying institutional IDP login (CAS/SAML) with RSA-encrypted credentials.
Entry URL → CAS/IDP (lck + authChainCode) → RSA encrypt password → authExecute
→ loginToken (JWT) → authnEngine → SSO ticket → Canvas session → create API token
→ (optional) delete old tokens by purpose → output NEW_TOKEN=xxx
The script handles the full IDP chain: cookie juggling, JavaScript-redirect handoff, CSRF extraction, and Canvas API token CRUD.
cd scripts/
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
Dependencies: requests, beautifulsoup4, pycryptodome, python-dotenv.
Copy .env.example to .env and fill in:
cp scripts/.env.example scripts/.env
Required fields:
ELEARNING_USERNAME — student/staff IDELEARNING_PASSWORD — passwordOptional (defaults to Fudan eLearning):
ELEARNING_ENTRY_URL — CAS entry pointELEARNING_IDP_BASE_URL — IDP base URLELEARNING_ENTITY_ID — SP entity IDELEARNING_TOKEN_PURPOSE — label for created tokens (default: "OpenClaw Auto Refresh Token")ELEARNING_CLEANUP_OLD_TOKENS — auto-delete old tokens with same purpose (default: false)# Full flow: login → create token → cleanup old tokens
cd scripts && .venv/bin/python elearning_login.py --cleanup-old-tokens
# Debug mode (verbose HTTP logs + save debug artifacts)
cd scripts && .venv/bin/python elearning_login.py --debug --cleanup-old-tokens
# Dry-run: only test up to public key fetch (no login)
cd scripts && .venv/bin/python elearning_login.py --dry-run --debug
On success, the script prints NEW_TOKEN= to stdout.
For agents that call Canvas API, implement a lazy-refresh pattern:
GET /api/v1/users/self — check HTTP status only (don't read body)NEW_TOKEN=, save to file, retryKey rules:
.env contains credentials — never commit to git (.env is gitignored by default)debug_output/ may contain session cookies and encrypted payloads — sanitize before sharing| Limitation | Impact | Mitigation |
|---|---|---|
| --- | --- | --- |
| CAPTCHA/rate-limiting | Script cannot solve human verification | Alert user, manual intervention needed |
| MFA/2FA | Requires interactive flow not supported by requests | Not supported; alert user |
| IDP interface changes | JSON field names or HTML structure may change | Debug output (--debug) captures raw responses for diagnosis |
| Public key format changes | Script supports PEM, Base64-DER, modulus+exponent | If new format appears, extend parse_public_key_payload() |
Run with --debug to save artifacts to debug_output/:
| Symptom | Check |
|---|---|
| --- | --- |
未能从入口响应中解析到 lck | debug_output/entry_response.html — look for context_CAS_... |
queryAuthMethods 未找到 userAndPwd | debug_output/query_auth_methods.json — check moduleCode field |
未从 authExecute 提取到 loginToken | debug_output/auth_execute.json — check code/message |
未拿到关键会话 Cookie | Check auth_execute.json for errors, authn_engine_response.html for CAPTCHA |
| Token API returns 401/422 | debug_output/cookies.txt for _csrf_token / _normandy_session |
| Cleanup fails | debug_output/cleanup_summary.json for failed entries |
The IDP flow is based on a common CAS/SAML pattern used by many Chinese universities. To adapt:
.env: ELEARNING_ENTRY_URL, ELEARNING_IDP_BASE_URL, ELEARNING_ENTITY_ID--dry-run first to verify lck/authChainCode extractionpick_auth_chain_code() in auth_session.pyencrypt_password_rsa() and parse_public_key_payload()Tested with: Fudan University (id.fudan.edu.cn → elearning.fudan.edu.cn).
共 1 个版本