Ubisam-MobileGit/tasks/002a-oauth-protocol-core.md

3.0 KiB
Raw Permalink Blame History

TASK-002A: Implement the OAuth PKCE protocol core

Status: complete Owner: Codex Reviewer: Claude

Outcome

Provide a deterministic, Android-independent OAuth authorization contract that generates fresh PKCE/state values, requests only approved read scopes, and strictly validates callbacks before any authorization code can be exchanged.

Writable paths

  • app/src/main/java/com/ubisam/ubgitea/core/auth/protocol/
  • app/src/test/java/com/ubisam/ubgitea/core/auth/protocol/
  • docs/decisions/002-oauth-security.md
  • tasks/002-oauth-spike.md
  • tasks/002a-oauth-protocol-core.md
  • tasks/002b-oauth-android-integration.md

Acceptance criteria

  • A fresh cryptographically random verifier and state are generated for every authorization attempt.
  • PKCE uses SHA-256 and unpadded Base64 URL encoding with method S256.
  • Authorization requests use HTTPS, the registered client ID and redirect URI, and only approved read scopes.
  • Callback validation requires an exact redirect scheme, host, effective port, and path.
  • Callback validation rejects missing, duplicated, mismatched, or expired state before accepting code or error parameters.
  • Missing, blank, or duplicated codes and malformed query encoding are rejected.
  • OAuth denial is represented separately from malformed callbacks.
  • No client secret, token, Android type, or logging appears in the protocol package.
  • Focused tests cover URL construction, freshness, PKCE vectors, scope, redirect validation, state, expiry, denial, code, and malformed input.

Security and privacy

This package must remain pure and must never persist or log authorization codes, tokens, verifier values, or state values.

Required checks

./gradlew assembleDebug
./gradlew testDebugUnitTest
./gradlew lintDebug

Evidence

Recorded on 2026-08-25 using JDK 17 and Android SDK 36:

  • Focused OAuth protocol tests — 21 tests, 0 failures, 0 errors.
  • ./gradlew assembleDebug — passed.
  • ./gradlew testDebugUnitTest — passed; 43 tests across 9 suites, 0 failures, 0 errors.
  • ./gradlew lintDebug — passed.
  • Sensitive-pattern scan excluding generated and Git metadata — no assigned client secret, token, password, or private-key value found.
  • git diff --check — passed.
  • Automatic string representations for transaction, request, authorization code, and denial results redact sensitive values.
  • Actual browser, App Link, token exchange, Keystore, and identity verification remain in TASK-002B.

Review findings

  • P2 verifier grammar — fixed by enforcing the RFC 7636 unreserved ASCII character set and 43–128 character length; adversarial tests added.
  • P2 callback pollution/encoding — fixed by rejecting conflicting response keys and duplicate recognized parameters, and using strict UTF-8 percent decoding; adversarial tests added.
  • P3 time arithmetic overflow — fixed with saturating comparison boundaries and Long.MIN_VALUE/Long.MAX_VALUE tests.
  • Independent re-review confirmed all findings closed with no remaining P0-P3 findings.