Skip to content

Implement basic unit/instance attestation#487

Open
md4096 wants to merge 2 commits intodevelopfrom
feature/wia-wua
Open

Implement basic unit/instance attestation#487
md4096 wants to merge 2 commits intodevelopfrom
feature/wia-wua

Conversation

@md4096
Copy link
Collaborator

@md4096 md4096 commented Jan 21, 2026

@md4096 md4096 force-pushed the feature/wia-wua branch 2 times, most recently from c4550f7 to 8130d1d Compare February 4, 2026 13:44
@nodh
Copy link
Member

nodh commented Feb 12, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c4d86a20b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@md4096 md4096 marked this pull request as ready for review February 19, 2026 09:39
@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@md4096 md4096 force-pushed the feature/wia-wua branch 2 times, most recently from 5657425 to e46e847 Compare February 19, 2026 09:59
@nodh
Copy link
Member

nodh commented Feb 19, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e46e847869

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@md4096 md4096 force-pushed the feature/wia-wua branch 2 times, most recently from 38b704f to 49bf8e8 Compare February 20, 2026 09:44
@nodh
Copy link
Member

nodh commented Feb 20, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f5965ae9f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +494 to +495
val clientAttJwt = loadInstanceAttestation?.let { it().getOrNull()?.serialize() }
val clientAttPop = loadInstanceAttestationPop?.let { it().getOrNull()?.serialize() }

Choose a reason for hiding this comment

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

P1 Badge Preserve deprecated client attestation auth path

This code now always reads instance attestation headers from loadInstanceAttestation*, but the constructor still accepts loadClientAttestationJwt/signClientAttestationPop (marked deprecated, not removed). Callers that have not migrated yet will compile and instantiate this class, but token requests will silently omit attestation headers and fail with invalid_client against servers requiring attestation-based client auth.

Useful? React with 👍 / 👎.

Copy link
Member

Choose a reason for hiding this comment

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

Would be fine to use the fallback:

val clientAttJwt = loadInstanceAttestation?.let { it().getOrNull()?.serialize() }
    ?: loadClientAttestationJwt?.invoke()

Comment on lines +384 to +388
if (addKeyAttestation && loadUnitAttestation == null && loadKeyAttestation == null) {
throw IllegalArgumentException("Key attestation required, none provided")
}
return CredentialRequestProofContainer(
jwt = setOf(loadUnitAttestation?.invoke(

Choose a reason for hiding this comment

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

P1 Badge Honor legacy key attestation loader when required

When addKeyAttestation is true, the guard explicitly treats loadKeyAttestation as a valid source, but the JWT proof creation path never uses it and only calls loadUnitAttestation. If a wallet still provides only loadKeyAttestation (which is not deprecated here), this branch will pass the precondition and then emit a fallback proof without key attestation, causing issuer-side proof rejection.

Useful? React with 👍 / 👎.

Copy link
Member

Choose a reason for hiding this comment

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

Also sounds fine to add a fallback to loadKeyAttestation when loadUnitAttestation is null.

nonce = clientNonce,
)
)
)?.getOrNull()?.serialize() ?: fallbackProof(clientNonce, credentialIssuer))

Choose a reason for hiding this comment

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

P2 Badge Do not swallow unit attestation generation errors

Using getOrNull() here hides failures from loadUnitAttestation and silently falls back to fallbackProof. In key-attestation-required flows this converts a concrete attestation acquisition error into a generic downstream invalid_proof/issuance failure, making recovery and debugging much harder and sending a request that is known to violate issuer requirements.

Useful? React with 👍 / 👎.

Copy link
Member

Choose a reason for hiding this comment

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

Seems about right, because addKeyAttestation might be true but the call returns an error ... right @md4096?

Comment on lines +85 to +87
when (tokenStatusValid && signatureValid) {
true -> return@ProofValidator true
false -> return@ProofValidator false
Copy link
Member

Choose a reason for hiding this comment

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

It looks like this could be simplified to tokenStatusValid && signatureValid

/** Handles credential request encryption and credential response decryption. */
private val encryptionService: WalletEncryptionService = WalletEncryptionService(),
/** Returns a new unit attestation to use during credential issuance. */
val loadUnitAttestation: (suspend (input: LoadUnitAttestationInput) -> KmmResult<JwsSigned<JsonWebToken>>)? = null,
Copy link
Member

Choose a reason for hiding this comment

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

Why isn't that private?

CHANGELOG.md Outdated
- ISO mdoc:
- Preserve `Document.errors` in parsed ISO document results instead of failing validation
- Change: Executing unsatisfiable DCQL queries no longer throws on matching, only on submission.
- Add method `loadUnitAttestation` to `WalletService`
Copy link
Member

Choose a reason for hiding this comment

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

Please group your entries under OpenID for Verifiable Credential Issuance:

}
}
}.isSuccess
val signatureValid = true //TODO: Add list with trusted keys
Copy link
Member

Choose a reason for hiding this comment

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

Even now we should at least verify the cryptographic signature of the JWS, and simply trust all keys.

/** Returns a new unit attestation to use during credential issuance. */
val loadUnitAttestation: (suspend (input: LoadUnitAttestationInput) -> KmmResult<JwsSigned<JsonWebToken>>)? = null,

private val keyMaterial: KeyMaterial = EphemeralKeyWithoutCert(),
Copy link
Member

Choose a reason for hiding this comment

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

Please move that up the parameter list, to its original position

issuer = clientId, // omit when token was pre-authn?
audience = credentialIssuer,
issuedAt = clock.now().truncateToSeconds(),
issuedAt = Clock.System.now().truncateToSeconds(),
Copy link
Member

Choose a reason for hiding this comment

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

should add a clock parameter to that function

}
return CredentialRequestProofContainer(
jwt = setOf(loadUnitAttestation?.invoke(
LoadUnitAttestationInput(
Copy link
Member

Choose a reason for hiding this comment

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

Seems like duplicated code from createCredentialRequestProofAttestation()

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

Comments