Skip to content

Commit 324fba3

Browse files
authored
Merge pull request #99 from eu-digital-identity-wallet/release/0.10.0
Sdjwt 11
2 parents 7c5525f + 75aae95 commit 324fba3

File tree

6 files changed

+61
-114
lines changed

6 files changed

+61
-114
lines changed

Sources/TypeMetadata/TypeMetadataMerger.swift

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ package protocol TypeMetadataMergerType {
2525
*
2626
* The merging process prioritizes the properties of the first element in the array,
2727
* using subsequent elements to fill in missing values or merge collections.
28+
*
29+
* If a child type defines claim metadata with the same path as
30+
* in the extended type, the child type's claim metadata will fully override the parent's.
2831
*/
2932
func mergeMetadata(from metadataArray: [ResolvedTypeMetadata]) -> ResolvedTypeMetadata?
3033
}
@@ -53,19 +56,7 @@ struct TypeMetadataMerger: TypeMetadataMergerType {
5356
primary: result.claims,
5457
secondary: parent.claims,
5558
keySelector: \.path,
56-
merge: { current, parent in
57-
SdJwtVcTypeMetadata.ClaimMetadata(
58-
path: current.path,
59-
display: mergeByKey(
60-
primary: current.display ?? [],
61-
secondary: parent.display ?? [],
62-
keySelector: \.lang,
63-
merge: { current, _ in current }
64-
),
65-
selectivelyDisclosable: current.selectivelyDisclosable,
66-
svgId: current.svgId
67-
)
68-
}
59+
merge: { current, _ in current }
6960
)
7061

7162
return ResolvedTypeMetadata(
@@ -123,5 +114,3 @@ struct TypeMetadataMerger: TypeMetadataMergerType {
123114
return merged
124115
}
125116
}
126-
127-

Sources/Utilities/SdJwtVcIssuerPublicKeySource.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,5 @@ import X509
1919
public enum SdJwtVcIssuerPublicKeySource {
2020
case metadata(iss: URL, kid: String?, fetcher: SdJwtVcIssuerMetaDataFetching)
2121
case x509CertChain(iss: URL, chain: [Certificate], trust: X509SDJWTVCCertificateTrust)
22-
case didUrl(iss: String, kid: String?, loukup: LookupPublicKeysFromDIDDocument)
2322
}
2423

Sources/Verifier/SDJWTVCVerifier.swift

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,8 @@ import JSONWebSignature
2121
import JSONWebToken
2222

2323
private let HTTPS_URI_SCHEME = "https"
24-
private let DID_URI_SCHEME = "did"
2524
private let SD_JWT_DC_TYPE = "dc+sd-jwt"
2625

27-
/**
28-
* A protocol to look up public keys from DIDs/DID URLs.
29-
*/
30-
public protocol LookupPublicKeysFromDIDDocument {
31-
/**
32-
* Asynchronously looks up public keys from a DID document based on a DID or DID URL.
33-
*
34-
* - Parameters:
35-
* - did: The DID identifier.
36-
* - didUrl: The DID URL (optional).
37-
* - Returns: An array of JWKs (public keys) or `nil` if the lookup fails.
38-
*/
39-
func lookup(did: String, didUrl: String?) async throws -> [JWK]?
40-
}
41-
42-
4326
/**
4427
* A protocol defining methods for verifying SD-JWTs
4528
*/
@@ -103,12 +86,10 @@ protocol SdJwtVcVerifierType {
10386
* It can be one of the following:
10487
* - metadata: Fetch issuer metadata to get keys.
10588
* - x509: Use X.509 certificates for verification.
106-
* - did: Use DID URLs to look up keys.
10789
*/
10890
public enum VerificationMethod {
10991
case metadata(fetcher: SdJwtVcIssuerMetaDataFetching)
11092
case x509(trust: X509SDJWTVCCertificateTrust)
111-
case did(lookup: LookupPublicKeysFromDIDDocument)
11293
}
11394

11495
/**
@@ -306,7 +287,7 @@ public class SDJWTVCVerifier: SdJwtVcVerifierType {
306287
private extension SDJWTVCVerifier {
307288

308289
/**
309-
* Selects the issuer's public key from the JWS object based on metadata, X.509 certificates, or DID URLs.
290+
* Selects the issuer's public key from the JWS object based on metadata, X.509 certificates.
310291
*
311292
* - Parameters:
312293
* - jws: The JSON Web Signature object.
@@ -353,17 +334,6 @@ private extension SDJWTVCVerifier {
353334
return .failure(
354335
SDJWTVerifierError.invalidJwt
355336
)
356-
357-
case .didUrl(let iss, let kid, let lookup):
358-
guard let key = try await lookup.lookup(
359-
did: iss,
360-
didUrl: kid
361-
)?.first(where: { $0.keyID == kid }) else {
362-
return .failure(
363-
SDJWTVerifierError.invalidJwt
364-
)
365-
}
366-
return .success(key)
367337
}
368338
}
369339

@@ -403,13 +373,6 @@ private extension SDJWTVCVerifier {
403373
chain: certChain,
404374
trust: trust
405375
)
406-
407-
case .did(lookup: let lookup):
408-
return .didUrl(
409-
iss: iss,
410-
kid: jws.protectedHeader.keyID,
411-
loukup: lookup
412-
)
413376
}
414377
}
415378

Tests/Mocks/LookupPublicKeysFromDIDDocumentMock.swift

Lines changed: 0 additions & 28 deletions
This file was deleted.

Tests/TypeMetadata/TypeMetadataMergerTests.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,62 @@ final class TypeMetadataMergerTests: XCTestCase {
189189
XCTAssertEqual(mergedClaim?.svgId, "child_svg") // child wins
190190
XCTAssertEqual(mergedClaim?.display?.first?.label, "Child Label") // child's display wins
191191
}
192+
193+
func test_mergeMetadata_withConflictingClaimPath_childFullyOverridesParentDisplay() {
194+
195+
let childClaim = SdJwtVcTypeMetadata.ClaimMetadata(
196+
path: ClaimPath([.claim(name: "same_path")]),
197+
display: [
198+
SdJwtVcTypeMetadata.ClaimDisplay(lang: "en", label: "Child Label EN")
199+
],
200+
selectivelyDisclosable: .always,
201+
svgId: "child_svg"
202+
)
203+
204+
let parentClaim = SdJwtVcTypeMetadata.ClaimMetadata(
205+
path: ClaimPath([.claim(name: "same_path")]),
206+
display: [
207+
SdJwtVcTypeMetadata.ClaimDisplay(lang: "en", label: "Parent Label EN"),
208+
SdJwtVcTypeMetadata.ClaimDisplay(lang: "fr", label: "Parent Label FR")
209+
],
210+
selectivelyDisclosable: .never,
211+
svgId: "parent_svg"
212+
)
213+
214+
let child = ResolvedTypeMetadata(
215+
vct: "child_vct",
216+
name: nil,
217+
description: nil,
218+
displays: [],
219+
claims: [childClaim]
220+
)
221+
222+
let parent = ResolvedTypeMetadata(
223+
vct: "parent_vct",
224+
name: nil,
225+
description: nil,
226+
displays: [],
227+
claims: [parentClaim]
228+
)
229+
230+
let merged = TypeMetadataMerger().mergeMetadata(from: [child, parent])
231+
232+
// Child claim fully overrides parent
233+
XCTAssertEqual(merged?.claims.count, 1)
234+
let mergedClaim = merged?.claims.first
235+
236+
// Only child's displays should be present (no French from parent)
237+
XCTAssertEqual(mergedClaim?.display?.count, 1)
238+
XCTAssertEqual(mergedClaim?.display?.first?.lang, "en")
239+
XCTAssertEqual(mergedClaim?.display?.first?.label, "Child Label EN")
240+
241+
// Parent's French display should NOT be present
242+
XCTAssertFalse(mergedClaim?.display?.contains(where: { $0.lang == "fr" }) ?? true)
243+
244+
// All child properties win
245+
XCTAssertEqual(mergedClaim?.selectivelyDisclosable, .always)
246+
XCTAssertEqual(mergedClaim?.svgId, "child_svg")
247+
}
192248

193249
func test_mergeMetadata_parentDisplaysAppended() {
194250
let childDisplay = SdJwtVcTypeMetadata.DisplayMetadata(

Tests/Verification/VcVerifierTest.swift

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,6 @@ final class VcVerifierTest: XCTestCase {
3636
extension: "json"
3737
))))
3838

39-
private let didVerifier = SDJWTVCVerifier( verificationMethod: .did(
40-
lookup: LookupPublicKeysFromDIDDocumentMock()
41-
))
42-
43-
44-
45-
46-
4739
override func setUp() async throws {
4840
}
4941

@@ -137,30 +129,6 @@ final class VcVerifierTest: XCTestCase {
137129
XCTAssertNoThrow(try result.get())
138130
}
139131

140-
func testVerifyIssuance_WithValidSDJWT_WithDID_ShouldSucceed() async throws {
141-
142-
// Given
143-
let sdJwtString = SDJWTConstants.did_sd_jwt.clean()
144-
145-
// When
146-
let result = try await didVerifier.verifyIssuance(unverifiedSdJwt: sdJwtString)
147-
148-
// Then
149-
XCTAssertNoThrow(try result.get())
150-
}
151-
152-
func testVerifyIssuance_WithValidSDJWT_WithDID_AndConfiguration_ShouldSucceed() async throws {
153-
154-
// Given
155-
let sdJwtString = SDJWTConstants.did_sd_jwt.clean()
156-
157-
// When
158-
let result = try await didVerifier.verifyIssuance(unverifiedSdJwt: sdJwtString)
159-
160-
// Then
161-
XCTAssertNoThrow(try result.get())
162-
}
163-
164132
func testVerifyIssuance_WithValidSDJWTFlattendedJSON_Withx509Header_ShouldSucceed() async throws {
165133

166134
// Given

0 commit comments

Comments
 (0)