Skip to content

Session seed not cached after CreateSession proof requests #407

Description

@kilianglas

Summary

walletkit-core/src/authenticator/mod.rs:513-523 drops the newly minted session_id_r_seed returned by a ProofType::CreateSession proof request. The storage-side caching block keys off the request's session_id, which is always None for CreateSession, so the seed is never persisted — even though the response carries a valid newly-minted session_id that would be the correct cache key.

(Lookup is fine — for a CreateSession request there's nothing to look up, by definition. The bug is purely on the storage side, after the core authenticator has minted the new session.)

Code

// walletkit-core/src/authenticator/mod.rs:513-523
if let Some(seed) = result.session_id_r_seed {
    if let Some(session_id) = proof_request.0.session_id {  // ← request's session_id
        self.store
            .store_session_seed(session_id.oprf_seed, seed, now)?;
    }
}

For CreateSession:

  • proof_request.0.session_id is None (the RP doesn't have a session yet) → the inner if let is skipped.
  • result.session_id_r_seed is Some(new_seed) and result.proof_response.session_id is Some(new_session_id), both available — but only proof_request.0.session_id is consulted, so the cache write is skipped.

For Session requests, proof_request.0.session_id is Some, so the current path works.

Impact

Correctness is preserved because the core authenticator's Session branch (world-id-protocol/crates/authenticator/src/prove.rs:319-326) handles a missing cached seed by re-deriving via OPRF from session_id.oprf_seed. The functional cost is one extra OPRF round-trip on the first Session request after a CreateSession, after which caching fills correctly on that Session path.

So: a performance regression on CreateSession → Session transitions, not a broken flow.

Proposed fix

Cache under result.proof_response.session_id.oprf_seed instead of proof_request.0.session_id.oprf_seed. The response's session_id is correct in both flows:

  • CreateSession: response carries the newly minted session_id.
  • Session: response echoes the request's session_id (same oprf_seed).

Sketch:

if let (Some(seed), Some(session_id)) = (
    result.session_id_r_seed,
    result.proof_response.session_id,
) {
    if let Err(err) = self.store.store_session_seed(session_id.oprf_seed, seed, now) {
        tracing::error\!("error caching session_id_r_seed: {}", err);
    }
}

Notes

  • Pre-existing — not introduced by chore: bump world-id-protocol to v0.11.0 #406 (chore: bump world-id-protocol to v0.11.0).
  • Currently masked by walletkit-core/tests/proof_generation_integration.rs, which primes the store via store.store_session_seed(...) directly before the Session proof, bypassing the caching block.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions