Skip to content

Commit

Permalink
Merge pull request #33 from decentralised-dataexchange/main
Browse files Browse the repository at this point in the history
  • Loading branch information
josmilan authored Jan 27, 2025
2 parents 421add0 + de5330a commit f39a495
Show file tree
Hide file tree
Showing 5 changed files with 456 additions and 270 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
targets: ["eudiWalletOidcIos"]),
],
dependencies: [
.package(url: "https://github.com/keefertaylor/Base58Swift.git", branch: "master"),
.package(url: "https://github.com/keefertaylor/Base58Swift.git", from: "2.1.11"),
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.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"),
Expand Down
112 changes: 60 additions & 52 deletions Sources/eudiWalletOidcIos/Service/IssueService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,80 +33,87 @@ public class IssueService: NSObject, IssueServiceProtocol {
/// - credentialOffer: The string representation of the credential offer.
/// - Returns: A `CredentialOffer` object if the resolution is successful; otherwise, `nil`.
public func resolveCredentialOffer(credentialOffer credentialOfferString: String) async throws -> CredentialOffer? {
let credentialOfferUrl = URL(string: credentialOfferString)
guard let credentialOfferUri = credentialOfferUrl?.queryParameters?["credential_offer_uri"] else { return nil }
let jsonDecoder = JSONDecoder()

if credentialOfferUri != "" {
var request = URLRequest(url: URL(string: credentialOfferUri)!)
request.httpMethod = "GET"

let (data, _) = try await URLSession.shared.data(for: request)
let credentialOfferUrl = URL(string: credentialOfferString)
guard let credentialOfferUri = credentialOfferUrl?.queryParameters?["credential_offer_uri"] else { return nil }
let jsonDecoder = JSONDecoder()

do {
guard let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return nil
//throw EUDIError(from: ErrorResponse(message: "Invalid JSON format", code: nil))
}
if credentialOfferUri != "" {
var request = URLRequest(url: URL(string: credentialOfferUri)!)
request.httpMethod = "GET"

// Check for specific keys to determine the model type
if jsonObject["credentials"] != nil {
// If the key 'credentialIssuer' is present, decode as CredentialOfferResponse
let model = try jsonDecoder.decode(CredentialOfferResponse.self, from: data)

if model.credentialIssuer == nil {
let error = EUDIError(from: ErrorResponse(message: "Invalid DID", code: nil))
let (data, response) = try await URLSession.shared.data(for: request)

do {
let httpRes = response as? HTTPURLResponse
if let res = httpRes?.statusCode, res >= 400 {
let errorData = String(data: data, encoding: .utf8)
let error = EUDIError(from: ErrorResponse(message: errorData, code: nil))
return CredentialOffer(fromError: error)
} else {
guard let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return nil
//throw EUDIError(from: ErrorResponse(message: "Invalid JSON format", code: nil))
}
return CredentialOffer(from: model)

} else if jsonObject["credential_configuration_ids"] != nil {
// If the key 'issuer' is present, decode as CredentialOfferV2
let modelV2 = try jsonDecoder.decode(CredentialOfferV2.self, from: data)

if modelV2.credentialIssuer == nil {
let error = EUDIError(from: ErrorResponse(message: "Invalid DID", code: nil))
return CredentialOffer(fromError: error)
}
return CredentialOffer(from: modelV2)
} else {
// If neither key is present, return an error
let error = EUDIError(from: ErrorResponse(message: "Invalid data format", code: nil))
return CredentialOffer(fromError: error)
}
}
} else {
guard let credentialOffer = credentialOfferUrl?.queryParameters?["credential_offer"] else { return nil }
let jsonData = Data(credentialOffer.utf8)

if credentialOffer != "" {
do {
if let model = try? jsonDecoder.decode(CredentialOfferResponse.self, from: jsonData) {
// Check for specific keys to determine the model type
if jsonObject["credentials"] != nil {
// If the key 'credentialIssuer' is present, decode as CredentialOfferResponse
let model = try jsonDecoder.decode(CredentialOfferResponse.self, from: data)

if model.credentialIssuer == nil {
let error = EUDIError(from: ErrorResponse(message: "Invalid DID", code: nil))
return CredentialOffer(fromError: error)
}
return CredentialOffer(from: model)
}

else if let modelV2 = try? jsonDecoder.decode(CredentialOfferV2.self, from: jsonData) {

} else if jsonObject["credential_configuration_ids"] != nil {
// If the key 'issuer' is present, decode as CredentialOfferV2
let modelV2 = try jsonDecoder.decode(CredentialOfferV2.self, from: data)

if modelV2.credentialIssuer == nil {
let error = EUDIError(from: ErrorResponse(message: "Invalid DID", code: nil))
return CredentialOffer(fromError: error)
}
return CredentialOffer(from: modelV2)
}

else {
} else {
// If neither key is present, return an error
let error = EUDIError(from: ErrorResponse(message: "Invalid data format", code: nil))
return CredentialOffer(fromError: error)
}
}
}
} else {
return nil
guard let credentialOffer = credentialOfferUrl?.queryParameters?["credential_offer"] else { return nil }
let jsonData = Data(credentialOffer.utf8)

if credentialOffer != "" {
do {
if let model = try? jsonDecoder.decode(CredentialOfferResponse.self, from: jsonData) {
if model.credentialIssuer == nil {
let error = EUDIError(from: ErrorResponse(message: "Invalid DID", code: nil))
return CredentialOffer(fromError: error)
}
return CredentialOffer(from: model)
}

else if let modelV2 = try? jsonDecoder.decode(CredentialOfferV2.self, from: jsonData) {
if modelV2.credentialIssuer == nil {
let error = EUDIError(from: ErrorResponse(message: "Invalid DID", code: nil))
return CredentialOffer(fromError: error)
}
return CredentialOffer(from: modelV2)
}

else {
let error = EUDIError(from: ErrorResponse(message: "Invalid data format", code: nil))
return CredentialOffer(fromError: error)
}
}
} else {
return nil
}
}
}
}

private func buildAuthorizationRequestV1(credentialOffer: CredentialOffer?, docType: String, format: String) -> String {
var authorizationDetails = if format == "mso_mdoc" {
Expand Down Expand Up @@ -926,3 +933,4 @@ extension IssueService: URLSessionDelegate, URLSessionTaskDelegate {
completionHandler(nil)
}
}

29 changes: 12 additions & 17 deletions Sources/eudiWalletOidcIos/Service/SDJWTService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,15 @@ public class SDJWTService {
}
public func createSDJWTR(
credential: String?,
presentationRequest: PresentationRequest,
privateKey: P256.Signing.PrivateKey
) -> String? {
inputDescriptor: InputDescriptor?, format: String?
, keyHandler: SecureKeyProtocol) -> String? {
do {
guard let credential = credential else {
return nil
}

let processedCredentialWithRequiredDisclosures = try processDisclosuresWithPresentationDefinition(
credential: credential,
presentationDefinition: VerificationService.processPresentationDefinition(presentationRequest.presentationDefinition)
)
credential: credential, inputDescriptor: inputDescriptor, format: format, keyHandler: keyHandler)

// let iat = Date()
// let payload =
Expand Down Expand Up @@ -83,19 +80,21 @@ public class SDJWTService {
}
public func processDisclosuresWithPresentationDefinition(
credential: String?,
presentationDefinition: PresentationDefinitionModel
) -> String? {
inputDescriptor: InputDescriptor?, format: String?, keyHandler: SecureKeyProtocol) -> String? {
guard let credential = credential else { return nil }

// Split the credential into disclosures and the issued JWT
guard let disclosures = getDisclosuresFromSDJWT(credential),
var issuedJwt = getIssuerJwtFromSDJWT(credential) else {
return nil
}
// if disclosures.count == 0 {
// return nil
// }
var disclosureList: [String] = []
// Extract requested parameters from the presentation definition
var requestedParams: [String] = []
if let fields = presentationDefinition.inputDescriptors?.first?.constraints?.fields {
if let fields = inputDescriptor?.constraints?.fields {
for field in fields {
if let paramName = field.path?.first?.split(separator: ".").last {
requestedParams.append(String(paramName))
Expand All @@ -122,13 +121,11 @@ public class SDJWTService {
}
}
}
if let inputDescriptors = presentationDefinition.inputDescriptors {
for inputDescriptor in inputDescriptors {
if let inputDescriptor = inputDescriptor {
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] = []
Expand All @@ -138,10 +135,8 @@ public class SDJWTService {
credentialList.append(credential)

var credentialFormat: String = ""
if let format = presentationDefinition.format ?? inputDescriptor.format {
for (key, value) in format {
credentialFormat = key
}
if let format = format {
credentialFormat = format
}
if credentialFormat == "mso_mdoc" {
tempCredentialList = credentialList
Expand Down Expand Up @@ -193,7 +188,6 @@ public class SDJWTService {
print("error")
}
}
}
}
return issuedJwt.isEmpty ? nil : issuedJwt
}
Expand Down Expand Up @@ -328,3 +322,4 @@ public class SDJWTService {
return String(first)
}
}

Loading

0 comments on commit f39a495

Please sign in to comment.