Skip to content

Commit 4e29b7d

Browse files
authored
Merge pull request #1892 from walt-id/feature/wal-1078-rejection-scenario
[WAL-1078] feat(mobile): add OpenID4VP rejection scenario
2 parents 6bfc634 + 80de1ca commit 4e29b7d

66 files changed

Lines changed: 4087 additions & 541 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

waltid-applications/mobile-e2e-fixtures/ios/TestHelpers/DemoBackend.swift

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ public final class DemoBackend {
134134
)
135135
}
136136

137+
public func createResponseBoundVerifierSession(scenario: DemoCredentialScenario) async throws -> DemoVerifierSession {
138+
try await createVerifierSession(
139+
scenario: scenario,
140+
transactionData: [],
141+
bindClientIDToResponseURI: true
142+
)
143+
}
144+
137145
public func createTransactionDataVerifierSession(
138146
scenario: DemoCredentialScenario = DemoBackend.transactionDataPresentationScenario
139147
) async throws -> DemoVerifierSession {
@@ -172,18 +180,29 @@ public final class DemoBackend {
172180

173181
private func createVerifierSession(
174182
scenario: DemoCredentialScenario,
175-
transactionData: [[String: Any]]
183+
transactionData: [[String: Any]],
184+
bindClientIDToResponseURI: Bool = false
176185
) async throws -> DemoVerifierSession {
177186
let endpoint = Self.verifierBaseURL
178187
.appendingPathComponent("verification-session")
179188
.appendingPathComponent("create")
189+
let requestedSessionID = bindClientIDToResponseURI ? UUID().uuidString.lowercased() : nil
190+
var coreFlow: [String: Any] = [
191+
"dcql_query": [
192+
"credentials": [scenario.verifierCredentialQuery],
193+
],
194+
]
195+
if let requestedSessionID {
196+
let responseURI = Self.verifierBaseURL
197+
.appendingPathComponent("verification-session")
198+
.appendingPathComponent(requestedSessionID)
199+
.appendingPathComponent("response")
200+
coreFlow["sessionId"] = requestedSessionID
201+
coreFlow["clientId"] = "redirect_uri:\(responseURI.absoluteString)"
202+
}
180203
var payload: [String: Any] = [
181204
"flow_type": "cross_device",
182-
"core_flow": [
183-
"dcql_query": [
184-
"credentials": [scenario.verifierCredentialQuery],
185-
],
186-
],
205+
"core_flow": coreFlow,
187206
]
188207
if !transactionData.isEmpty {
189208
payload["openid"] = ["transactionData": transactionData]
@@ -203,6 +222,13 @@ public final class DemoBackend {
203222
userInfo: [NSLocalizedDescriptionKey: "Missing sessionId in public demo verifier2 response: \(response)"]
204223
)
205224
}
225+
guard requestedSessionID == nil || requestedSessionID == sessionID else {
226+
throw NSError(
227+
domain: "WalletE2E",
228+
code: 308,
229+
userInfo: [NSLocalizedDescriptionKey: "Public demo verifier2 did not preserve the requested session ID"]
230+
)
231+
}
206232
let requestURL = response["bootstrapAuthorizationRequestUrl"] as? String
207233
?? response["authorizationRequestUrl"] as? String
208234
?? response["fullAuthorizationRequestUrl"] as? String
@@ -261,6 +287,51 @@ public final class DemoBackend {
261287
)
262288
}
263289

290+
public func waitForVerifierFailure(
291+
sessionID: String,
292+
expectedError: String,
293+
timeoutSeconds: TimeInterval
294+
) async throws -> [String: Any] {
295+
let deadline = Date().addingTimeInterval(timeoutSeconds)
296+
297+
while Date() < deadline {
298+
let url = Self.verifierBaseURL
299+
.appendingPathComponent("verification-session")
300+
.appendingPathComponent(sessionID)
301+
.appendingPathComponent("info")
302+
let response = try await client.jsonRequest(url: url, retryTransientFailures: true)
303+
let status = (response["status"] as? String)
304+
?? ((response["session"] as? [String: Any])?["status"] as? String)
305+
306+
switch status?.uppercased() {
307+
case "FAILED":
308+
guard let failure = response["failure"] as? [String: Any],
309+
failure["error"] as? String == expectedError else {
310+
throw NSError(
311+
domain: "WalletE2E",
312+
code: 305,
313+
userInfo: [NSLocalizedDescriptionKey: "public demo verifier2 omitted \(expectedError) failure details for session \(sessionID): \(response)"]
314+
)
315+
}
316+
return response
317+
case "SUCCESSFUL", "ERROR", "EXPIRED":
318+
throw NSError(
319+
domain: "WalletE2E",
320+
code: 306,
321+
userInfo: [NSLocalizedDescriptionKey: "public demo verifier2 reported \(status ?? "UNKNOWN") instead of \(expectedError) for session \(sessionID): \(response)"]
322+
)
323+
default:
324+
try await Task.sleep(nanoseconds: 2_000_000_000)
325+
}
326+
}
327+
328+
throw NSError(
329+
domain: "WalletE2E",
330+
code: 307,
331+
userInfo: [NSLocalizedDescriptionKey: "public demo verifier2 did not report \(expectedError) within \(timeoutSeconds)s for session \(sessionID)"]
332+
)
333+
}
334+
264335
private static func sdJwtQuery(id: String, vct: String) -> [String: Any] {
265336
[
266337
"id": id,

waltid-applications/waltid-wallet-demo-compose/sharedLogic/src/commonMain/kotlin/id/walt/walletdemo/compose/logic/DemoWallet.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ interface DemoWallet {
66
suspend fun resolveOffer(offerUrl: String): WalletDemoOfferPreview
77
suspend fun receive(offerUrl: String, txCode: String? = null): List<String>
88
suspend fun present(requestUrl: String, did: String? = null): WalletDemoOperationResult
9-
suspend fun previewPresentation(requestUrl: String): WalletDemoPresentationPreview
9+
suspend fun previewPresentation(requestUrl: String): WalletDemoPresentationPreviewResult
1010
suspend fun submitPresentation(
1111
requestUrl: String,
1212
selectedCredentialOptions: List<WalletDemoPresentationCredentialSelection>,
1313
selectedDisclosureOptions: List<WalletDemoPresentationDisclosureSelection>,
1414
did: String? = null,
1515
): WalletDemoOperationResult
16+
suspend fun rejectPresentation(requestUrl: String): WalletDemoOperationResult
1617
}

waltid-applications/waltid-wallet-demo-compose/sharedLogic/src/commonMain/kotlin/id/walt/walletdemo/compose/logic/LazyDemoWallet.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal class LazyDemoWallet(
2929
override suspend fun present(requestUrl: String, did: String?): WalletDemoOperationResult =
3030
wallet().present(requestUrl, did)
3131

32-
override suspend fun previewPresentation(requestUrl: String): WalletDemoPresentationPreview =
32+
override suspend fun previewPresentation(requestUrl: String): WalletDemoPresentationPreviewResult =
3333
wallet().previewPresentation(requestUrl)
3434

3535
override suspend fun submitPresentation(
@@ -39,4 +39,7 @@ internal class LazyDemoWallet(
3939
did: String?,
4040
): WalletDemoOperationResult =
4141
wallet().submitPresentation(requestUrl, selectedCredentialOptions, selectedDisclosureOptions, did)
42+
43+
override suspend fun rejectPresentation(requestUrl: String): WalletDemoOperationResult =
44+
wallet().rejectPresentation(requestUrl)
4245
}

0 commit comments

Comments
 (0)