{"document_version":"2026-10-21","issuer":"https:\/\/one.tapee.ac.th","protocol":"tapee-one-confidential-sso","standard_oidc_provider":false,"guide":"https:\/\/one.tapee.ac.th\/developers\/ai-guide.md","requires":["confidential_backend","registered_https_callback","server_side_session","registered_client_id_and_secret","current_program_permission"],"authorize":{"method":"GET","url":"https:\/\/one.tapee.ac.th\/sso\/authorize","authentication":"One browser session","query":{"client_id":{"type":"string","max_length":100},"state":{"type":"string","min_length":32,"max_length":128,"pattern":"^[A-Za-z0-9_-]+$"}},"success":"redirect to registered callback with code and state","code_ttl_seconds":60,"code_single_use":true,"throttle_per_minute":60},"token":{"method":"POST","url":"https:\/\/one.tapee.ac.th\/api\/sso\/token","body_required":["client_id","client_secret","code"],"accept":"application\/json","content_types":["application\/x-www-form-urlencoded","application\/json"],"success_status":200,"response":{"access_token":{"type":"opaque_string"},"token_type":{"value":"Bearer"},"expires_in":{"value":3600}},"throttle_per_minute":120},"introspect":{"method":"POST","url":"https:\/\/one.tapee.ac.th\/api\/sso\/introspect","body_required":["client_id","client_secret","token"],"accept":"application\/json","content_types":["application\/x-www-form-urlencoded","application\/json"],"success_status":200,"active_response_fields":{"active":"boolean true","sub":"string","name":"string","email":"string","email_verified":"boolean","program_id":"integer","exp":"unix_timestamp_integer"},"inactive_response":{"active":false},"required_before_every_protected_request":true,"allow_only_if_active_strictly_true":true,"failure_policy":"deny; use 503 for verification dependency failures","throttle_per_minute":600,"throttle_note":"Middleware keys may be shared by clients using the same source IP. These are not guaranteed per-user quotas.","applies_to":"sessions authenticated through One; direct login uses existing local authorization"},"errors":{"401":"invalid client credentials or inactive client","403":"invalid\/expired\/replayed code or access denied","422":"validation failure","429":"rate limited"},"launch_callback_query":{"start":"1"},"identity_key":["issuer","sub"],"automatic_account_linking":{"implemented_by":"downstream backend after successful token introspection","first_link":"email_verified strictly true; lowercase and trim email; exactly one active existing local account with the same university email","persist":"issuer + sub -> existing local user id, with unique constraints, transaction and audit","existing_link":"use stable issuer + sub mapping; never remap automatically when email changes","conflict":"deny automatic linking for duplicate emails or an account linked to another subject","local_permissions":"preserve existing local roles and ownership; One access alone does not grant local Admin","no_match":"show account-not-linked guidance; do not invent or merge accounts"},"not_provided":["oidc_discovery","jwks","id_token","jwt_validation","refresh_token","public_token_revocation_endpoint","roles_or_groups_in_introspection","public_permission_administration_api","public_telegram_send_api"],"logout":{"local":"clear local app session only","one":"One logout removes the user's central codes\/tokens; enforce at next introspection"},"launch":{"method":"POST","path":"\/programs\/{id}\/launch","authentication":"One browser session, CSRF, active account and current program permission","success_status":200,"response":"Same-origin HTML handoff page; self-hosted JavaScript performs top-level GET to the registered HTTPS callback with start=1","fallback":"Visible anchor to the same registered callback if JavaScript is disabled"},"login_modes":{"one":"additional SSO login; preserve existing direct email\/password and configured Google login","direct":"verify local credentials and enforce local account status, roles and scopes; no One token required","one_session":"introspect before every protected request; never silently fall back to direct authentication","revocation":"One revocation affects One sessions; suspend the local account to block direct login too"}}