Skip to content

Commit

Permalink
Fix: Support for client ID scheme x509 san dns
Browse files Browse the repository at this point in the history
  • Loading branch information
josmilan authored Nov 19, 2024
1 parent 7b5f2a6 commit bb794ac
Show file tree
Hide file tree
Showing 8 changed files with 1,009 additions and 466 deletions.
4 changes: 1 addition & 3 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "eudiWalletOidcIos",
platforms: [
Expand All @@ -16,7 +14,7 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/keefertaylor/Base58Swift.git", branch: "master"),
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.8.1"),
.package(url: "https://github.com/decentralised-dataexchange/PresentationExchangeSdkiOS.git", .upToNextMajor(from: "2024.8.1")),
.package(url: "https://github.com/decentralised-dataexchange/PresentationExchangeSdkiOS.git", .upToNextMajor(from: "2024.11.1")),
.package(url: "https://github.com/airsidemobile/JOSESwift.git", from: "2.3.0"),
.package(url: "https://github.com/apple/swift-crypto.git", from:"3.5.2"),
.package(url: "https://github.com/niscy-eudiw/SwiftCBOR.git", from: "0.5.7")
Expand Down
8 changes: 6 additions & 2 deletions Sources/eudiWalletOidcIos/Model/PresentationRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
import Foundation
public struct PresentationRequest: Codable {
public var state, clientId, redirectUri, responseType, responseMode, scope, nonce, requestUri: String?
public var state, clientId, clientIDScheme, redirectUri, responseType, responseMode, scope, nonce, requestUri: String?
public var responseUri: String?
public var presentationDefinition: String?
public var clientMetaData: String?
Expand All @@ -15,6 +15,7 @@ public struct PresentationRequest: Codable {
enum CodingKeys: String, CodingKey {
case state = "state"
case clientId = "client_id"
case clientIDScheme = "client_id_scheme"
case redirectUri = "redirect_uri"
case responseUri = "response_uri"
case responseType = "response_type"
Expand All @@ -27,7 +28,7 @@ public struct PresentationRequest: Codable {
case presentationDefinitionUri = "presentation_definition_uri"
case clientMetaDataUri = "client_metadata_uri"
}
public init(state: String?, clientId: String?, redirectUri: String?, responseUri: String?, responseType: String?, responseMode: String?, scope: String?, nonce: String?, requestUri: String?, presentationDefinition: String?, clientMetaData: String?, presentationDefinitionUri: String?, clientMetaDataUri: String?) {
public init(state: String?, clientId: String?, redirectUri: String?, responseUri: String?, responseType: String?, responseMode: String?, scope: String?, nonce: String?, requestUri: String?, presentationDefinition: String?, clientMetaData: String?, presentationDefinitionUri: String?, clientMetaDataUri: String?, clientIDScheme: String?) {
self.state = state
self.clientId = clientId
self.redirectUri = redirectUri
Expand All @@ -41,12 +42,14 @@ public struct PresentationRequest: Codable {
self.clientMetaData = clientMetaData
self.presentationDefinitionUri = presentationDefinitionUri
self.clientMetaDataUri = clientMetaDataUri
self.clientIDScheme = clientIDScheme
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
state = try container.decodeIfPresent(String.self, forKey: .state)
clientId = try container.decodeIfPresent(String.self, forKey: .clientId)
clientIDScheme = try container.decodeIfPresent(String.self, forKey: .clientIDScheme)
redirectUri = try container.decodeIfPresent(String.self, forKey: .redirectUri)
responseUri = try container.decodeIfPresent(String.self, forKey: .responseUri)
responseType = try container.decodeIfPresent(String.self, forKey: .responseType)
Expand Down Expand Up @@ -94,4 +97,5 @@ public struct ClientMetaData: Codable {
location = try container.decodeIfPresent(String.self, forKey: .location)
logoUri = try container.decodeIfPresent(String.self, forKey: .logoUri)
}

}
65 changes: 36 additions & 29 deletions Sources/eudiWalletOidcIos/Service/IssueService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,37 +134,33 @@ public class IssueService: NSObject, IssueServiceProtocol {
return authorizationDetails
}

private func buildAuthorizationRequestV2(credentialOffer: CredentialOffer?, docType: String, format: String, issuerConfig: IssuerWellKnownConfiguration?) -> String {
let credentialConfigID = credentialOffer?.credentials?.first?.types?.first ?? nil
var authorizationDetails = if format == "mso_mdoc" {
"[" + (([
"format": format,
"doctype": docType,
"credential_configuration_id": credentialConfigID,
"locations": [credentialOffer?.credentialIssuer ?? ""]

] as [String : Any]).toString() ?? "") + "]"
} else if format.contains("sd-jwt"){

func buildAuthorizationRequestV2(credentialOffer: CredentialOffer?, docType: String, format: String, issuerConfig: IssuerWellKnownConfiguration?) -> String {
let credentialConfigID = credentialOffer?.credentials?.first?.types?.first ?? nil
var authorizationDetails = if format == "mso_mdoc" {
"[" + (([
"type": "openid_credential",
"doctype": docType,
"credential_configuration_id": credentialConfigID,
"locations": [credentialOffer?.credentialIssuer ?? ""]

] as [String : Any]).toString() ?? "") + "]"
} else if format.contains("sd-jwt"){
"[" + (([
"type": "openid_credential",
"format": format,
"vct": getTypesFromIssuerConfig(issuerConfig: issuerConfig, type: credentialConfigID)
] as [String : Any]).toString() ?? "") + "]"
}
else {
"[" + (([
"type": "openid_credential",
"credential_configuration_id": credentialConfigID,
"credential_definition": ["type": getTypesFromIssuerConfig(issuerConfig: issuerConfig, type: credentialConfigID)]
] as [String : Any]).toString() ?? "") + "]"
}

"[" + (([
"type": "openid_credential",
"format": format,
"credential_configuration_id": credentialConfigID,
//pass issur config
"vct": getTypesFromIssuerConfig(issuerConfig: issuerConfig, type: credentialConfigID)
] as [String : Any]).toString() ?? "") + "]"
return authorizationDetails
}
else {
"[" + (([
"type": "openid_credential",
"format": format,
"credential_definition": ["type": getTypesFromIssuerConfig(issuerConfig: issuerConfig, type: credentialConfigID)]
] as [String : Any]).toString() ?? "") + "]"
}

return authorizationDetails
}


private func buildAuthorizationRequest(credentialOffer: CredentialOffer?, docType: String, format: String, issuerConfig: IssuerWellKnownConfiguration?) -> String {
Expand Down Expand Up @@ -787,6 +783,17 @@ public class IssueService: NSObject, IssueServiceProtocol {
}
}

public func isCredentialMetaDataAvailable(issuerConfig: IssuerWellKnownConfiguration?, type: String?) -> Bool? {
guard let issuerConfig = issuerConfig else { return nil }

if let credentialSupported = issuerConfig.credentialsSupported?.dataSharing?[type ?? ""] {
return true
} else {
return false
}
}


public func getTypesFromCredentialOffer(credentialOffer: CredentialOffer?) -> [String]? {
guard let credentialOffer = credentialOffer else { return nil }

Expand Down
2 changes: 2 additions & 0 deletions Sources/eudiWalletOidcIos/Service/IssueServiceProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ protocol IssueServiceProtocol {
issuerConfig: IssuerWellKnownConfiguration?,
type: String?) -> String?

func isCredentialMetaDataAvailable(issuerConfig: IssuerWellKnownConfiguration?, type: String?) -> Bool?

func getTypesFromCredentialOffer(credentialOffer: CredentialOffer?) -> [String]?
func getTypesFromIssuerConfig(issuerConfig: IssuerWellKnownConfiguration?, type: String?) -> Any?

Expand Down
95 changes: 89 additions & 6 deletions Sources/eudiWalletOidcIos/Service/SDJWTService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
//
import Foundation
import CryptoKit
import PresentationExchangeSdkiOS

public class SDJWTService {

public static var shared = SDJWTService()
Expand Down Expand Up @@ -90,7 +92,7 @@ public class SDJWTService {
var issuedJwt = getIssuerJwtFromSDJWT(credential) else {
return nil
}

var disclosureList: [String] = []
// Extract requested parameters from the presentation definition
var requestedParams: [String] = []
if let fields = presentationDefinition.inputDescriptors?.first?.constraints?.fields {
Expand All @@ -105,13 +107,94 @@ public class SDJWTService {
for disclosure in disclosures {
if let decodedDisclosure = disclosure.decodeBase64(),
let list = try? JSONSerialization.jsonObject(with: Data(decodedDisclosure.utf8), options: []) as? [Any],
list.count >= 2,
let paramName = list[1] as? String,
requestedParams.contains(paramName) {
issuedJwt += "~\(disclosure)"
list.count >= 2 {
if let paramName = list[1] as? String,
requestedParams.contains(paramName){
disclosureList.append(disclosure)
}
if let secondParam = list[2] as? [String: Any] {
let keys = Array(secondParam.keys)
for key in keys {
if requestedParams.contains(key) {
disclosureList.append(disclosure)
}
}
}
}
}
if let inputDescriptors = presentationDefinition.inputDescriptors {
for inputDescriptor in inputDescriptors {
if inputDescriptor.constraints?.limitDisclosure == nil {
return issuedJwt.isEmpty ? nil : issuedJwt
} else {
var verificationHandler : eudiWalletOidcIos.VerificationService?
let keyHandler = CryptoKitHandler()
verificationHandler = eudiWalletOidcIos.VerificationService(keyhandler: keyHandler)
let updatedDescriptor = verificationHandler?.updatePath(in: inputDescriptor)
var processedCredentials: [String] = []
var tempCredentialList: [String?] = []
var credentialList: [String] = []
var sdList: [String] = []
credentialList.append(credential)

var credentialFormat: String = ""
if let format = presentationDefinition.format ?? inputDescriptor.format {
for (key, value) in format {
credentialFormat = key
}
}
if credentialFormat == "mso_mdoc" {
tempCredentialList = credentialList
processedCredentials = verificationHandler?.processCborCredentialToJsonString(credentialList: tempCredentialList) ?? []
} else {
tempCredentialList = verificationHandler?.splitCredentialsBySdJWT(allCredentials: credentialList, isSdJwt: inputDescriptor.constraints?.limitDisclosure != nil) ?? []

processedCredentials = verificationHandler?.processCredentialsToJsonString(credentialList: tempCredentialList) ?? []
}
let jsonEncoder = JSONEncoder()
jsonEncoder.keyEncodingStrategy = .convertToSnakeCase
guard let jsonData = try? jsonEncoder.encode(updatedDescriptor),
let dictionary = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] else {
fatalError("Failed to convert Person to dictionary")
}
// Convert the dictionary to a string
guard let inputDescriptorString = String(data: try! JSONSerialization.data(withJSONObject: dictionary, options: .withoutEscapingSlashes), encoding: .utf8) else {
fatalError("Failed to convert dictionary to string")
}
do {

let matchesString = try matchCredentials(inputDescriptorJson: inputDescriptorString, credentials: processedCredentials)
for item in matchesString {
for data in item.fields {
let value = data.path.value
if let valueDict = value as? [String: Any], let sdArray = valueDict["_sd"] as? [Any] {
for element in sdArray {
if let sdValue = element as? String {
sdList.append(sdValue)
}
}
}
}
}
for dis in disclosures {
let sdData = calculateSHA256Hash(inputString: dis) ?? ""
if sdList.contains(sdData) {
if !(disclosureList.contains(sdData)) {
disclosureList.append(dis)
}
}
}
print("")
for data in disclosureList {
issuedJwt += "~\(data)"
}
return issuedJwt.isEmpty ? nil : issuedJwt
} catch {
print("error")
}
}
}
}

return issuedJwt.isEmpty ? nil : issuedJwt
}

Expand Down
Loading

0 comments on commit bb794ac

Please sign in to comment.