Skip to content

Commit f28e81b

Browse files
feat: OID4VCI 1.0 Final / parameters for (deferred) credential responses (#154)
1 parent 1c71a24 commit f28e81b

7 files changed

Lines changed: 559 additions & 24 deletions

CHANGES.ja.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
変更点
22
======
33

4+
- `CredentialDeferredIssueRequest` クラス
5+
* `isDenied()` メソッドを追加。
6+
* `setDenied(boolean)` メソッドを追加。
7+
* `getInterval()` メソッドを追加。
8+
* `setInterval(int)` メソッドを追加。
9+
10+
- `CredentialDeferredIssueResponse.Action` 列挙型
11+
* `ACCEPTED` を追加。
12+
* `ACCEPTED_JWT` を追加。
13+
14+
- `CredentialSingleIssueRequest` クラス
15+
* `isDenied()` メソッドを追加。
16+
* `setDenied(boolean)` メソッドを追加。
17+
* `getInterval()` メソッドを追加。
18+
* `setInterval(int)` メソッドを追加。
19+
20+
421
4.34 (2026 年 01 月 03 日)
522
--------------------------
623

CHANGES.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
CHANGES
22
=======
33

4+
- `CredentialDeferredIssueRequest` class
5+
* Added the `isDenied()` method.
6+
* Added the `setDenied(boolean)` method.
7+
* Added the `getInterval()` method.
8+
* Added the `setInterval(int)` method.
9+
10+
- `CredentialDeferredIssueResponse.Action` enum
11+
* Added `ACCEPTED`.
12+
* Added `ACCEPTED_JWT`.
13+
14+
- `CredentialSingleIssueRequest` class
15+
* Added the `isDenied()` method.
16+
* Added the `setDenied(boolean)` method.
17+
* Added the `getInterval()` method.
18+
* Added the `setInterval(int)` method.
19+
20+
421
4.34 (2026-01-03)
522
-----------------
623

src/main/java/com/authlete/common/dto/CredentialDeferredIssueRequest.java

Lines changed: 254 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2023 Authlete, Inc.
2+
* Copyright (C) 2023-2026 Authlete, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
55
* use this file except in compliance with the License. You may obtain a copy of
@@ -26,7 +26,7 @@
2626
* The Authlete API is supposed to be called by the implementation of the
2727
* <b>deferred credential endpoint</b>. The endpoint is defined in the "<a href=
2828
* "https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html"
29-
* >OpenID for Verifiable Credential Issuance</a>" (OID4VCI) specification.
29+
* >OpenID for Verifiable Credential Issuance 1.0</a>" (OID4VCI) specification.
3030
* </p>
3131
*
3232
* <p>
@@ -41,14 +41,59 @@
4141
* </ol>
4242
*
4343
* <p>
44-
* The role of the {@code /vci/deferred/issue} API is to issue a credential.
44+
* The {@code /vci/deferred/issue} API is used for one of the following purposes:
4545
* </p>
4646
*
47+
* <ol>
48+
* <li>To issue a credential
49+
* <li>To deny the deferred credential request
50+
* <li>To notify that the requested credential is not ready yet
51+
* </ol>
52+
*
53+
* <h3>Issuing a credential</h3>
54+
*
4755
* <p>
48-
* If the credential for the transaction ID is not ready, the implementation
49-
* of the deferred credential endpoint should prepare an error response with
50-
* {@code "error":"issuance_pending"} manually and return it to the request
51-
* sender, without calling the {@code /vci/deferred/issue} API.
56+
* To issue a credential, the {@code order} request parameter must be set up
57+
* properly, and both the {@code denied} and {@code order.issuanceDeferred}
58+
* request parameters must be set to {@code false}.
59+
* </p>
60+
*
61+
* <h3>Denying a deferred credential request</h3>
62+
*
63+
* <p>
64+
* To deny the deferred credential request, the {@code denied} request parameter
65+
* in the API call must be set to {@code true}. In this case, Authlete prepares
66+
* a response containing {@code "error":"credential_request_denied"} and returns
67+
* <code>"action":"{@link CredentialDeferredIssueResponse.Action#BAD_REQUEST BAD_REQUEST}"</code>.
68+
* </p>
69+
*
70+
* <p>
71+
* Note that the {@code credential_request_denied} error code does not exist in
72+
* OID4VCI 1.0 ID1. Therefore, you should not call the API with {@code denied}
73+
* set to {@code true} when the target specification version is "1.0-ID1".
74+
* </p>
75+
*
76+
* <h3>Notifying that the credential is not ready yet</h3>
77+
*
78+
* <p>
79+
* To notify that the requested credential is not ready yet, the
80+
* {@code order.issuanceDeferred} request parameter in the API call must be
81+
* set to {@code true}. In this case, Authlete will do one of the following:
82+
* </p>
83+
*
84+
* <ol>
85+
* <li>
86+
* Prepare an error response with the {@code issuance_pending} error code for
87+
* OID4VCI 1.0 ID1.
88+
* <li>
89+
* Prepare a successful response containing the {@code transaction_id} and
90+
* {@code interval} parameters for OID4VCI 1.0 Final or later.
91+
* </ol>
92+
*
93+
* <p>
94+
* Note that if the Authlete Server version is older than 3.0.25 and the target
95+
* specification version is "1.0-ID1", you need to manually construct an error
96+
* response as shown below, without using the {@code /vci/deferred/issue} API.
5297
* </p>
5398
*
5499
* <pre>
@@ -61,15 +106,38 @@
61106
* }
62107
* </pre>
63108
*
109+
* <h3>Interval handling</h3>
110+
*
111+
* <p>
112+
* If the {@code interval} request parameter in the API call is present and its
113+
* value is positive, it is used as the value of the {@code interval} response
114+
* parameter in the deferred credential response. If the {@code interval}
115+
* request parameter is missing, zero, or negative, Authlete uses the default
116+
* value.
117+
* </p>
118+
*
119+
* <p>
120+
* Note that the {@code interval} response parameter does not exist in OID4VCI
121+
* 1.0 ID1. Therefore, you don't have to care about the {@code interval} request
122+
* parameter if the target specification version is "1.0-ID1".
123+
* </p>
124+
*
125+
* <h3>Important note</h3>
126+
*
127+
* <p>
128+
* In all cases, the {@code order.requestIdentifier} request parameter must be
129+
* set properly.
130+
* </p>
131+
*
64132
* @since 3.70
65133
* @since Authlete 3.0
66134
*
67-
* @see <a href="https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html"
68-
* >OpenID for Verifiable Credential Issuance</a>
135+
* @see <a href="https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html">
136+
* OpenID for Verifiable Credential Issuance 1.0</a>
69137
*/
70138
public class CredentialDeferredIssueRequest implements Serializable
71139
{
72-
private static final long serialVersionUID = 1L;
140+
private static final long serialVersionUID = 2L;
73141

74142

75143
/**
@@ -78,6 +146,26 @@ public class CredentialDeferredIssueRequest implements Serializable
78146
private CredentialIssuanceOrder order;
79147

80148

149+
/**
150+
* The flag that indicates whether to deny the deferred credential request.
151+
*
152+
* @since 4.35
153+
* @since Authlete 3.0.25
154+
*/
155+
private boolean denied;
156+
157+
158+
/**
159+
* The minimum amount of time in seconds that the Wallet SHOULD wait after
160+
* receiving the response before sending a new request to the Deferred
161+
* Credential Endpoint.
162+
*
163+
* @since 4.35
164+
* @since Authlete 3.0.25
165+
*/
166+
private int interval;
167+
168+
81169
/**
82170
* Get the credential order that provides an instruction for issuing a
83171
* credential.
@@ -107,4 +195,160 @@ public CredentialDeferredIssueRequest setOrder(CredentialIssuanceOrder order)
107195

108196
return this;
109197
}
198+
199+
200+
/**
201+
* Get the flag that indicates whether to deny the deferred credential
202+
* request.
203+
*
204+
* <p>
205+
* If this parameter is set to {@code true}, the response content prepared
206+
* by Authlete will contain {@code "error":"credential_request_denied"}
207+
* like below.
208+
* </p>
209+
*
210+
* <pre>
211+
* {
212+
* "error": "credential_request_denied"
213+
* }
214+
* </pre>
215+
*
216+
* <p>
217+
* Note that the {@code credential_request_denied} error code does not
218+
* exist in OID4VCI 1.0 ID1.
219+
* </p>
220+
*
221+
* @return
222+
* {@code true} for generating a response content containing
223+
* {@code "error":"credential_request_denied"}.
224+
*
225+
* @since 4.35
226+
* @since Authlete 3.0.25
227+
*/
228+
public boolean isDenied()
229+
{
230+
return denied;
231+
}
232+
233+
234+
/**
235+
* Set the flag that indicates whether to deny the deferred credential
236+
* request.
237+
*
238+
* <p>
239+
* If this parameter is set to {@code true}, the response content prepared
240+
* by Authlete will contain {@code "error":"credential_request_denied"}
241+
* like below.
242+
* </p>
243+
*
244+
* <pre>
245+
* {
246+
* "error": "credential_request_denied"
247+
* }
248+
* </pre>
249+
*
250+
* <p>
251+
* Note that the {@code credential_request_denied} error code does not
252+
* exist in OID4VCI 1.0 ID1.
253+
* </p>
254+
*
255+
* @param denied
256+
* {@code true} for generating a response content containing
257+
* {@code "error":"credential_request_denied"}.
258+
*
259+
* @return
260+
* {@code this} object.
261+
*
262+
* @since 4.35
263+
* @since Authlete 3.0.25
264+
*/
265+
public CredentialDeferredIssueRequest setDenied(boolean denied)
266+
{
267+
this.denied = denied;
268+
269+
return this;
270+
}
271+
272+
273+
/**
274+
* Get the minimum amount of time in seconds that the Wallet SHOULD wait
275+
* after receiving the response before sending a new request to the
276+
* Deferred Credential Endpoint.
277+
*
278+
* <p>
279+
* The value of this parameter is used as the value of the {@code interval}
280+
* parameter in the deferred credential response. However, the
281+
* {@code interval} parameter is included in the deferred credential
282+
* response only when the following conditions are met:
283+
* </p>
284+
*
285+
* <ul>
286+
* <li>
287+
* The value of the {@code order.issuanceDeferred} request parameter is
288+
* {@code true}.
289+
* </li>
290+
*
291+
* <li>
292+
* The version of the OID4VCI specification is 1.0-Final or later (that is,
293+
* the {@code oid4vciVersion} property of {@link Service} is set and its
294+
* value is not {@code "1.0-ID1"}).
295+
* </li>
296+
* </ul>
297+
*
298+
* @return
299+
* The minimum amount of time in seconds that the Wallet SHOULD
300+
* wait after receiving the response before sending a new request
301+
* to the Deferred Credential Endpoint.
302+
*
303+
* @since 4.35
304+
* @since Authlete 3.0.25
305+
*/
306+
public int getInterval()
307+
{
308+
return interval;
309+
}
310+
311+
312+
/**
313+
* Set the minimum amount of time in seconds that the Wallet SHOULD wait
314+
* after receiving the response before sending a new request to the
315+
* Deferred Credential Endpoint.
316+
*
317+
* <p>
318+
* The value of this parameter is used as the value of the {@code interval}
319+
* parameter in the deferred credential response. However, the
320+
* {@code interval} parameter is included in the deferred credential
321+
* response only when the following conditions are met:
322+
* </p>
323+
*
324+
* <ul>
325+
* <li>
326+
* The value of the {@code order.issuanceDeferred} request parameter is
327+
* {@code true}.
328+
* </li>
329+
*
330+
* <li>
331+
* The version of the OID4VCI specification is 1.0-Final or later (that is,
332+
* the {@code oid4vciVersion} property of {@link Service} is set and its
333+
* value is not {@code "1.0-ID1"}).
334+
* </li>
335+
* </ul>
336+
*
337+
* @param interval
338+
* The minimum amount of time in seconds that the Wallet SHOULD
339+
* wait after receiving the response before sending a new request
340+
* to the Deferred Credential Endpoint.
341+
*
342+
* @return
343+
* {@code this} object.
344+
*
345+
* @since 4.35
346+
* @since Authlete 3.0.25
347+
*/
348+
public CredentialDeferredIssueRequest setInterval(int interval)
349+
{
350+
this.interval = interval;
351+
352+
return this;
353+
}
110354
}

0 commit comments

Comments
 (0)