Security Posture: VA OAuth Token Custody¶
Status: Current as of 2026-07-23. Veteran web client: design recorded; build PARKED until VA production access (#00015000) approves and browser-direct CORS is confirmed.
Companion document: SECURITY_POSTURE_DATABASE_ACCESS.md
Audience: counsel, VA API review, security review, future engineers
The claim¶
A veteran's VA OAuth token is held on the veteran's own device and is never in LastVet's custody.
LastVet servers do not receive, store, log, proxy, or transit the veteran's VA OAuth access token or refresh token. The veteran's device authenticates directly with VA Lighthouse, pulls the record, and sends LastVet only the parsed result under the veteran's direction.
This is the architectural property that makes the rest of the consent model meaningful. If LastVet held VA credentials, a compromise of LastVet infrastructure would expose veterans' VA accounts. It does not, because we never have them.
What was stated to the VA, and when¶
On 2026-06-15, following a demonstration call for VA Lighthouse production access (case #00015000), we sent an unprompted correction. On the call we had said VA clinical data is never stored. On review of our own codebase that was inaccurate: VA clinical data is stored, as a veteran-directed encrypted snapshot.
We corrected ourselves in writing the same day and provided a persistence matrix and as-built architecture diagram. The corrected statement was:
- VA clinical data is stored, as a veteran-directed encrypted snapshot
- The device pulls that data using the veteran's own OAuth token
- The token remains in the iOS keychain
- The token never reaches LastVet servers
That statement was accurate when made and remains accurate for the iOS client today.
Current implementation (iOS, shipping)¶
| Property | Implementation |
|---|---|
| Token acquisition | Veteran authenticates directly with VA Lighthouse from the device |
| Token storage | iOS Keychain — hardware-backed, OS-protected, not readable by other apps |
| Token transmission to LastVet | None |
| What LastVet receives | vaPatientId for session exchange; parsed record items for sync |
| Record at rest | Veteran-directed encrypted snapshot in LastVet, under the consent model |
The session-exchange request body contains vaPatientId only. The sync endpoint accepts
normalized record items only. Neither accepts nor stores a VA token.
Planned web client — and how the claim changes¶
A browser-based client is planned for veterans without an iPhone. Android and older devices currently cannot use LastVet at all, which is a real access-equity problem.
Not built as of this document's date. Build is parked until VA production access is approved and browser-direct cross-origin access is confirmed with Lighthouse. The following is the design target, recorded in advance so the posture is stated honestly before it ships rather than described after.
The core property survives¶
VA Lighthouse documents support for public OAuth clients using PKCE (RFC 7636) with no client secret, for both the Patient Health (FHIR) and Service History & Eligibility APIs. A browser can therefore complete the OAuth exchange and call VA APIs directly, without a LastVet proxy. Under this design, LastVet servers still never receive the token.
The strength of the guarantee changes, and this is the honest delta¶
| iOS | Web (planned) | |
|---|---|---|
| Custody | Veteran's device | Veteran's device |
| LastVet server custody | None | None |
| Storage mechanism | iOS Keychain | Browser storage (IndexedDB) |
| Hardware-backed | Yes | No |
| Readable by other apps | No | No |
| Readable by injected script on our origin (XSS) | No | Yes |
Both are device-local. Device-local is not equally strong in both places.
The iOS Keychain is hardware-backed and isolated by the operating system. Browser storage is readable by any script executing on our origin, which makes cross-site scripting the primary threat to token custody on web in a way it is not on iOS.
Accordingly, the claim wording changes from "iOS Keychain" to:
The veteran's VA OAuth token remains on the veteran's own device — in the iOS Keychain on mobile, in browser storage on web — and is never in LastVet's custody.
Mitigations for the web client¶
- Strict Content Security Policy:
default-src 'self', nonce-only scripts, no third-party scripts on authentication or sync pages - No third-party analytics, tracking, or advertising scripts on any LastVet surface (existing policy across all properties)
- Token cleared on sign-out; VA re-authentication prompted on next connect
Known dependency and its risk¶
Browser-direct API calls require VA Lighthouse to permit cross-origin requests from our domain.
As probed on 2026-07-23, VA sandbox and production endpoints return
Access-Control-Allow-Origin: * for both OAuth token endpoints and FHIR resource endpoints.
This behavior is observed, not documented. VA does not publish a CORS policy or a browser/SPA integration guide; their PKCE guidance is framed for native mobile applications. VA could restrict cross-origin access without a documentation change, which would break the browser-direct design.
Consequence: browser-direct is a validated assumption, not a contractual guarantee. It must be re-verified before the web client ships, and confirmed with VA directly as part of the production access relationship.
Fallback design, if browser-direct becomes unavailable¶
If VA requires server-side token exchange or a server-side API proxy, the token would have to transit LastVet infrastructure. In that case:
- A stateless isolated proxy would receive the token in request memory only
- Never persisted, never written to disk, never logged, never placed in a database
- Token present only for the duration of a single request
This would be a material change to the custody claim and would be disclosed to the VA proactively. A compromised proxy could harvest tokens in flight. That is not equivalent to device custody, and it would not be described as though it were.
We would not adopt this design silently.
Summary for external readers¶
| Question | Answer |
|---|---|
| Does LastVet ever hold a veteran's VA OAuth token? | No |
| Where does the token live? | The veteran's device — iOS Keychain today |
| Is VA clinical data stored by LastVet? | Yes — as a veteran-directed encrypted snapshot, under the consent model |
| Is the web client built? | No. Design target only, recorded in advance; build parked until VA production approval |
| Would web change the custody claim? | The token still never reaches LastVet servers. Device-local custody is weaker in a browser than in the iOS Keychain, and we state that plainly |
| Is browser-direct guaranteed? | No. It depends on VA CORS behavior that is observed but not documented |
Revision history¶
| Date | Change |
|---|---|
| 2026-06-15 | Unprompted correction to VA: clinical data is stored as a veteran-directed encrypted snapshot; token remains in iOS Keychain and never reaches LastVet servers. Persistence matrix and architecture diagram provided |
| 2026-07-23 | Document created. Web client custody model recorded in advance of implementation, including the honest security delta between Keychain and browser storage, and the undocumented CORS dependency. Build parked pending VA production access |