Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 17 additions & 18 deletions DfnsDemo/DfnsDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objectVersion = 60;
objects = {

/* Begin PBXBuildFile section */
48F0B3B02ED061F300500085 /* DfnsSdk in Frameworks */ = {isa = PBXBuildFile; productRef = 48F0B3AF2ED061F300500085 /* DfnsSdk */; };
7A1A68702BBEA54B00167ED0 /* DfnsDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1A686F2BBEA54B00167ED0 /* DfnsDemoApp.swift */; };
7A1A68722BBEA54B00167ED0 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1A68712BBEA54B00167ED0 /* ContentView.swift */; };
7A1A68742BBEA54C00167ED0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A1A68732BBEA54C00167ED0 /* Assets.xcassets */; };
7A1A68772BBEA54C00167ED0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A1A68762BBEA54C00167ED0 /* Preview Assets.xcassets */; };
7A1A68A92BC5943700167ED0 /* MyServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1A68A82BC5943700167ED0 /* MyServer.swift */; };
7A439BB12BCD22710022D861 /* MyBusinessLogic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A439BB02BCD22710022D861 /* MyBusinessLogic.swift */; };
7A439BB72BCD67270022D861 /* DfnsSdk in Frameworks */ = {isa = PBXBuildFile; productRef = 7A439BB62BCD67270022D861 /* DfnsSdk */; };
7A5207E72BCD8B22003EC637 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A5207E62BCD8B22003EC637 /* Config.swift */; };
/* End PBXBuildFile section */

Expand All @@ -34,7 +34,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7A439BB72BCD67270022D861 /* DfnsSdk in Frameworks */,
48F0B3B02ED061F300500085 /* DfnsSdk in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -97,7 +97,7 @@
);
name = DfnsDemo;
packageProductDependencies = (
7A439BB62BCD67270022D861 /* DfnsSdk */,
48F0B3AF2ED061F300500085 /* DfnsSdk */,
);
productName = DfnsDemo;
productReference = 7A1A686C2BBEA54B00167ED0 /* DfnsDemo.app */;
Expand Down Expand Up @@ -128,7 +128,7 @@
);
mainGroup = 7A1A68632BBEA54B00167ED0;
packageReferences = (
7A439BB52BCD67270022D861 /* XCRemoteSwiftPackageReference "dfns-sdk-swift" */,
48F0B3AE2ED061F300500085 /* XCLocalSwiftPackageReference "../../dfns-sdk-swift" */,
);
productRefGroup = 7A1A686D2BBEA54B00167ED0 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -227,6 +227,8 @@
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 6.0;
};
name = Debug;
};
Expand Down Expand Up @@ -282,6 +284,8 @@
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 6.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
Expand Down Expand Up @@ -313,7 +317,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
SWIFT_STRICT_CONCURRENCY = minimal;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
Expand Down Expand Up @@ -345,7 +349,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
SWIFT_STRICT_CONCURRENCY = minimal;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
Expand Down Expand Up @@ -373,21 +377,16 @@
};
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
7A439BB52BCD67270022D861 /* XCRemoteSwiftPackageReference "dfns-sdk-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/dfns/dfns-sdk-swift";
requirement = {
branch = m;
kind = branch;
};
/* Begin XCLocalSwiftPackageReference section */
48F0B3AE2ED061F300500085 /* XCLocalSwiftPackageReference "../../dfns-sdk-swift" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = "../../dfns-sdk-swift";
};
/* End XCRemoteSwiftPackageReference section */
/* End XCLocalSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
7A439BB62BCD67270022D861 /* DfnsSdk */ = {
48F0B3AF2ED061F300500085 /* DfnsSdk */ = {
isa = XCSwiftPackageProductDependency;
package = 7A439BB52BCD67270022D861 /* XCRemoteSwiftPackageReference "dfns-sdk-swift" */;
productName = DfnsSdk;
};
/* End XCSwiftPackageProductDependency section */
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions DfnsDemo/DfnsDemo/Config.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// The url below should match the value in .entitlements file
enum Config {
public static let serverUrl: String = "https://airedale-finer-baboon.ngrok-free.app"
public static let passkeyRelyingPartyId: String = "airedale-finer-baboon.ngrok-free.app"
Expand Down
34 changes: 22 additions & 12 deletions DfnsDemo/DfnsDemo/ContentView.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import SwiftUI

struct ContentView: View {
@ObservedObject var userConfig: UserConfig
@ObservedObject var myBusinessLogic: MyBusinessLogic
@Binding var userConfig: UserConfig
let myBusinessLogic: MyBusinessLogic

var body: some View {
NavigationView {
Expand Down Expand Up @@ -31,7 +31,7 @@ struct ContentView: View {

Text("Your customers, either new or existing, must register with Dfns first and have credential(s) in our system in order to own and be able to interact with their blockchain wallets.\n\nThe delegated registration flow allows you to initiate and and complete the registration process on your customers behalf, without them being aware that the wallets infrastructure is powered by Dfns, i.e. they will not receive an registration email from Dfns directly unlike the normal registration process for your employees. Their WebAuthn credentials are still completely under their control.")

NavigationLink("Go to Delegated Registration", destination: DelegatedRegistrationView(userConfig: userConfig, myBusinessLogic: myBusinessLogic)).buttonStyle(.borderedProminent).padding(.vertical, 15)
NavigationLink("Go to Delegated Registration", destination: DelegatedRegistrationView(userConfig: $userConfig, myBusinessLogic: myBusinessLogic)).buttonStyle(.borderedProminent).padding(.vertical, 15)

/// STEP 2

Expand All @@ -42,7 +42,7 @@ struct ContentView: View {

Text("The delegated signing flow does not need the end user sign with the WebAuthn credential. The login can be performed on the server side transparent to the end users and obtain a readonly auth token. For example, your server can choose to automatically login the end users upon the completion of delegated registration. In this tutorial, this step is shown as explicit in order to more clearly demonstrate how the interaction works.")

NavigationLink("Go to Delegated Login", destination: DelegatedLoginView(userConfig: userConfig, myBusinessLogic: myBusinessLogic)).buttonStyle(.borderedProminent).padding(.vertical, 15)
NavigationLink("Go to Delegated Login", destination: DelegatedLoginView(userConfig: $userConfig, myBusinessLogic: myBusinessLogic)).buttonStyle(.borderedProminent).padding(.vertical, 15)

/// STEP 3

Expand All @@ -69,8 +69,8 @@ struct ContentView: View {
}

struct DelegatedRegistrationView: View {
@ObservedObject var userConfig: UserConfig
@ObservedObject var myBusinessLogic: MyBusinessLogic
@Binding var userConfig: UserConfig
let myBusinessLogic: MyBusinessLogic
@State var registerResponse: String = ""

var body: some View {
Expand All @@ -90,13 +90,20 @@ struct DelegatedRegistrationView: View {
.frame(maxWidth: .infinity, alignment: .leading)

TextField("Choose a username", text: $userConfig.email).textFieldStyle(.roundedBorder).padding(.vertical)
.textFieldStyle(.roundedBorder)
.padding(.vertical)
.keyboardType(.emailAddress)
.textInputAutocapitalization(.never)

Button("Register EndUser") {
Task {
let result = await myBusinessLogic.registerUser(userConfig: userConfig)
registerResponse = result
}
}.buttonStyle(.borderedProminent).frame(maxWidth: .infinity).padding(.bottom)
}
.buttonStyle(.borderedProminent)
.frame(maxWidth: .infinity)
.padding(.bottom)

JSONText(registerResponse)
}.padding()
Expand All @@ -106,8 +113,8 @@ struct DelegatedRegistrationView: View {
}

struct DelegatedLoginView: View {
@ObservedObject var userConfig: UserConfig
@ObservedObject var myBusinessLogic: MyBusinessLogic
@Binding var userConfig: UserConfig
let myBusinessLogic: MyBusinessLogic
@State var loginResponse: String = ""

var body: some View {
Expand All @@ -123,7 +130,10 @@ struct DelegatedLoginView: View {

Text("This auth token is readonly and needs to be cached and passed along with all requests interacting with the Dfns API. To clearly demonstrate all the necessary components for each step, this example will cache the auth token in the application context and send it back with every sequently request to the server. You should however choose a more secure caching method.").padding(.vertical)

TextField("Enter the username", text: $userConfig.email).textFieldStyle(.roundedBorder)
TextField("Enter the username", text: $userConfig.email)
.textFieldStyle(.roundedBorder)
.keyboardType(.emailAddress)
.textInputAutocapitalization(.never)

Button("Login EndUser") {
Task {
Expand All @@ -142,8 +152,8 @@ struct DelegatedLoginView: View {
}

struct EndUserWalletsView: View {
@ObservedObject var userConfig: UserConfig
@ObservedObject var myBusinessLogic: MyBusinessLogic
let userConfig: UserConfig
let myBusinessLogic: MyBusinessLogic
@State var walletResponse: String = ""
@State var messageToSign: String = ""
@State var signingResponse: String = ""
Expand Down
18 changes: 11 additions & 7 deletions DfnsDemo/DfnsDemo/DfnsDemoApp.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import DfnsSdk
import SwiftUI
import Observation

class UserConfig: ObservableObject {
@Observable
final class UserConfig {
var authToken: String?
var email: String

init() {
email = ""
email = ""
}
@Published var authToken: String?
@Published var email: String

}

@main
struct DfnsDemoApp: App {
@StateObject private var userConfig = UserConfig()
@StateObject private var myBusinessLogic = MyBusinessLogic(
@State private var userConfig = UserConfig()
@State private var myBusinessLogic = MyBusinessLogic(
url: Config.serverUrl,
passkeyRelyingPartyId: Config.passkeyRelyingPartyId
)

var body: some Scene {
WindowGroup {
ContentView(userConfig: userConfig, myBusinessLogic: myBusinessLogic)
ContentView(userConfig: $userConfig, myBusinessLogic: myBusinessLogic)
}
}
}
9 changes: 6 additions & 3 deletions DfnsDemo/DfnsDemo/MyBusinessLogic.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import DfnsSdk
import Foundation
import Observation

/**
Controller that is doing the interface between the UI, the Demo Server and the Passkey Signer
*/
final class MyBusinessLogic: ObservableObject {
@Observable
@MainActor
final class MyBusinessLogic: @unchecked Sendable {
private var passkeyRelyingPartyId: String
private var myServer: MyServer
private var passkeysSigner: PasskeysSigner
private let myServer: MyServer
private let passkeysSigner: PasskeysSigner

init(url: String, passkeyRelyingPartyId: String) {
self.passkeyRelyingPartyId = passkeyRelyingPartyId
Expand Down
5 changes: 3 additions & 2 deletions DfnsDemo/DfnsDemo/MyServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import Foundation
/**
Implement the API of the server
*/
final class MyServer {
private var url: String = ""
@MainActor
final class MyServer: @unchecked Sendable {
private let url: String

init(url: String) {
self.url = url
Expand Down
13 changes: 13 additions & 0 deletions DfnsDemo/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// swift-tools-version:6.2

// This is a HACKY workaround the fact that SPM does not allow for Package level exclusion
// of files/folders. SPM actually HAD support for it but it was removed in 2017, in PR
// https://github.com/apple/swift-package-manager/commit/cb69accf41da55386f9703308958aa49ca2a4c5f
//
// So instead we have to add an empty dummy Package.swift to each folder we wanna hide, as per:
// See: https://github.com/apple/swift-package-manager/issues/4460#issuecomment-1475025748
// And: https://stackoverflow.com/questions/69382302/swift-package-how-to-exclude-files-in-root-git-directory-from-the-actual-swift/70990534#70990534
// And: https://github.com/tuist/tuist/pull/2058
import PackageDescription

let package = Package(name: "HIDDEN")
8 changes: 7 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
// swift-tools-version: 5.10
// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "DfnsSdk",
platforms: [
.macOS(.v10_15),
.iOS(.v15),
.watchOS(.v6),
.tvOS(.v13)
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
Expand Down
Loading