Skip to content

change expiresAt to be nullable and do default check with at for backward compatibility with mobile apps#127

Open
kf7mxe wants to merge 5 commits into
version-5from
tb/backwardCompatProofExpiresAt
Open

change expiresAt to be nullable and do default check with at for backward compatibility with mobile apps#127
kf7mxe wants to merge 5 commits into
version-5from
tb/backwardCompatProofExpiresAt

Conversation

@kf7mxe

@kf7mxe kf7mxe commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

made expiresAt nullable and do default check with at for backward compatibility with mobile apps

@UnknownJoe796 UnknownJoe796 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Review (commit c2e4045)## PR #127 Review: Make expiresAt nullable for backwards compatibility

Overall this is a reasonable compatibility shim, but there's one significant concern and a couple of minor ones.


1. Fragile fallback — 1.hours hardcoded in two places must match proofExpiration

Files: Signer.ext.kt:35, Proof.ext.kt:10

Issue: The signingInfo function falls back to at + 1.hours when expiresAt is null, and the expired check does the same. This only produces correct signature verification if the original proof was signed with a proofExpiration of exactly 1 hour.

All current proof method implementations default proofExpiration to 1.hours, so this works today. However, PinBasedProofEndpoints takes proofExpiration as a required parameter with no default — any consumer of this library can set it to something other than 1 hour. If they do, and a mobile client strips expiresAt during the round-trip, the signingInfo fallback will compute a different payload than what was originally signed, and signature verification will silently fail.

Why it matters: This is an auth-critical code path. The backwards compatibility guarantee is actually conditional on a specific configuration, which isn't documented anywhere. Future developers (or current library consumers) won't know this.

Suggested fix: Either:

  • Extract the fallback duration into a shared constant with a clear name like DEFAULT_PROOF_EXPIRATION_FALLBACK and document that it must match the signing-time expiration for null-expiresAt proofs to verify, or
  • Remove the fallback from signingInfo entirely and instead have Signer.verify / verifyBlocking try verification with the fallback only if the first attempt fails (try original payload, then try with at + 1.hours).

Confidence: High


2. Stale doc comment on Proof.expiresAt

File: proofModels.kt:113

The doc comment still says @property expiresAt The timestamp when this proof is no longer valid. without mentioning it's nullable or what null means. The inline comment // Nullable for now for backwards compatibility with mobile apps is only visible in source, not in generated docs.

Suggested fix: Update the KDoc:

* @property expiresAt The timestamp when this proof is no longer valid.
*           Null for backwards compatibility with older clients; when null, defaults to [at] + 1 hour.

Confidence: High


3. No test coverage for the null expiresAt path

Files: No test changes in the diff.

The backwards compatibility scenario (proof deserialized without expiresAt → signature still verifies → expiry check still works) has no test. Given this is security-critical code with a subtle correctness requirement (the fallback must match the signing duration), a test would catch regressions.

Confidence: Medium

kf7mxe and others added 2 commits April 22, 2026 09:27
# Conflicts:
#	sessions/src/main/kotlin/com/lightningkite/lightningserver/sessions/proofs/extensions/Proof.ext.kt
#	sessions/src/main/kotlin/com/lightningkite/lightningserver/sessions/proofs/extensions/Signer.ext.kt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants