[java-idp-plugin-vci] 05/07: Nonce null examples removed. Timestamp precision property added, for batch issuance time stamps
Codeberg
noreply at shibboleth.net
Thu Sep 24 13:16:30 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-idp-plugin-vci.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-vci/commit/a4d3e009cedf57b0ecf3996687d33d497604e4f2
commit a4d3e009cedf57b0ecf3996687d33d497604e4f2
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Thu Sep 24 16:14:48 2026 +0300
Nonce null examples removed. Timestamp precision property added, for batch issuance time stamps
---
README.md | 45 +++++++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
index f3474d0..62ac2be 100644
--- a/README.md
+++ b/README.md
@@ -320,7 +320,19 @@ What ends up in the credential:
| `dc+sd-jwt` | `iat` is the instant of issuance, `exp` closes the window, and `nbf` opens it whenever that is not the instant of issuance |
| `vc+sd-jwt` | The same three, and `validFrom` and `validUntil` as the same two ends of the window |
-A credential whose window opens at issuance carries no `nbf`.
+A credential whose window opens at issuance carries no `nbf`. The instant of issuance is rounded
+down to the full hour, so that every credential of one batch carries the same `iat` and `exp` and
+the two do not link the credentials to each other. To round to something else you need to set
+`openidvci.credentialTimestampPrecision` in *conf/openid-vci.properties*:
+
+```properties
+openidvci.credentialTimestampPrecision = PT15M
+```
+
+Rounding moves the window earlier, never later, so the expiration still chooses the same
+[Status List](#status-list) it would have chosen unrounded. Keep the precision shorter than the
+shortest `lifetime` you issue. A longer one closes the window before the credential is issued and
+nothing is issued.
##### Whether a credential states this deployment in OpenID Federation
@@ -550,7 +562,7 @@ for the wallet that redeems the code:
<bean parent="OpenID.VCI.Token"
p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
p:tokenEndpointAuthMethods="#{{'none'}}" />
- <bean parent="OpenID.VCI.Credentials" p:dpopProofNonceGenerator="#{null}" />
+ <bean parent="OpenID.VCI.Credentials" />
</list>
</property>
</bean>
@@ -731,9 +743,8 @@ code flow:
p:requirePushedAuthorizationRequest="true" />
<bean parent="OpenID.VCI.Token"
p:tokenEndpointAuthMethods="#{{'none'}}"
- p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
- p:dpopProofNonceGenerator="#{null}" />
- <bean parent="OpenID.VCI.Credentials" p:dpopProofNonceGenerator="#{null}" />
+ p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy" />
+ <bean parent="OpenID.VCI.Credentials" />
<bean parent="OAUTH2.PAR" p:tokenEndpointAuthMethods="#{{'none'}}" />
</list>
</property>
@@ -1248,6 +1259,7 @@ not state comes from the profile configuration.
| Switch | Why you would touch it |
|---|---|
+| `openidvci.credentialTimestampPrecision` | The full hour is too coarse or too fine for the `iat` and `exp` your credentials carry. |
| `lifetime` of a credential | One credential outlives another. A `credentialLifetime` for everything is the alternative. |
| `not_before` of a credential | The window opens on a date you decide instead of at issuance. A cohort of one school year is the case for it. |
| `credentialLifetime` | The validity of everything this deployment issues, and of anything that states no `lifetime` of its own. |
@@ -1469,6 +1481,11 @@ See [DID.Document](#diddocument).
`/.well-known/oauth-authorization-server` tells a wallet where the token endpoint is. Note that
`token_endpoint` is the VCI one and not the OP's own.
+`dpop_signing_alg_values_supported` names the algorithms a DPoP proof may be signed with, which
+FAPI 2.0 requires to carry at least one of `PS256`, `ES256`, `EdDSA` and `Ed25519`. Keep it in step
+with `idp.oauth2.dpop.proofAlgorithms` of *conf/oidc.properties*, the list a DPoP error response
+offers the wallet.
+
<details>
<summary>Contents of static/oauth-authorization-server.json as it comes with the plugin</summary>
@@ -1496,6 +1513,14 @@ See [DID.Document](#diddocument).
"code_challenge_methods_supported":[
"S256"
],
+ "dpop_signing_alg_values_supported":[
+ "ES256",
+ "ES384",
+ "ES512",
+ "PS256",
+ "PS384",
+ "PS512"
+ ],
"scopes_supported":[
"openid"
],
@@ -1895,7 +1920,7 @@ Issues the credential. A `POST` of `application/json` to
<property name="profileConfigurations">
<list>
...
- <bean parent="OpenID.VCI.Credentials" p:dpopProofNonceGenerator="#{null}" />
+ <bean parent="OpenID.VCI.Credentials" />
</list>
</property>
</bean>
@@ -2157,7 +2182,7 @@ examples of this document. `OIDC.Keyset`, `OIDC.Configuration`, `OAUTH2.TokenAud
<bean parent="OpenID.VCI.Token"
p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
p:tokenEndpointAuthMethods="#{{'none'}}" />
- <bean parent="OpenID.VCI.Credentials" p:dpopProofNonceGenerator="#{null}" />
+ <bean parent="OpenID.VCI.Credentials" />
</list>
</property>
</bean>
@@ -2173,9 +2198,8 @@ examples of this document. `OIDC.Keyset`, `OIDC.Configuration`, `OAUTH2.TokenAud
p:requirePushedAuthorizationRequest="true" />
<bean parent="OpenID.VCI.Token"
p:tokenEndpointAuthMethods="#{{'none'}}"
- p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy"
- p:dpopProofNonceGenerator="#{null}" />
- <bean parent="OpenID.VCI.Credentials" p:dpopProofNonceGenerator="#{null}" />
+ p:accessTokenClaimsSetManipulationStrategy-ref="openidvci.TokenManipulationStrategy" />
+ <bean parent="OpenID.VCI.Credentials" />
<bean parent="OAUTH2.PAR" p:tokenEndpointAuthMethods="#{{'none'}}" />
</list>
</property>
@@ -2200,6 +2224,7 @@ plugin and is loaded automatically, you do not need to touch `idp.additionalProp
|---|---|---|---|
| `openidvci.issuer` | String | | Credential Issuer value used in credentials and in Status List Tokens. Empty and `did:jwk` both mean the did:jwk of the signing key, `did:web` the did:web of this deployment and `url` the issuer of the OP. Any other value is the identifier itself. A Credential Configuration is able to state an `issuer` of its own and override this per credential. See [Credential Issuer identifiers](#credential-issuer-identifiers). |
| `openidvci.authn.flows` | String | `OpenIDVCIClient` | Regular expression matching the login flows to enable for VCI endpoints. `OpenIDVCIClient` is the `OAuth2Client` flow of the OP with `attest_jwt_client_auth` as a client authentication method. |
+| `openidvci.credentialTimestampPrecision` | Duration | `PT1H` | Granularity the instant of issuance is rounded down to, so that credentials of one batch carry the same `iat` and `exp`. A `not_before` and a `lifetime` are measured from the rounded instant. Must be shorter than the shortest credential lifetime issued. |
| `openidvci.StorageService` | Bean ID | Bean named **shibboleth.StorageService** | Storage for Credential Offers. Requires server-side storage. |
| `openidvci.preAuthorizedCode.defaultLifetime` | Duration | `PT10M` | Lifetime of the pre-authorized code. |
| `openidvci.preAuthorizedCode.defaultLength` | Integer | `0` | Length of pre-authorized codes. `0` means untruncated and self-contained; `10` or more means a stored offer. |
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list