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
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let package = Package(
targets: ["TSAuthenticationSDK", "TSAuthenticationSDK-Dependencies"])
],
dependencies: [
.package(url: "https://github.com/TransmitSecurity/core-ios-sdk.git", from: "1.0.29")
.package(url: "https://github.com/TransmitSecurity/core-ios-sdk.git", from: "1.0.31")
],
targets: [
.binaryTarget(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,55 @@ SWIFT_CLASS("_TtC19TSAuthenticationSDK16TSAuthentication")



SWIFT_CLASS("_TtC19TSAuthenticationSDK30TSWebAuthnAllowCredentialsData")
@interface TSWebAuthnAllowCredentialsData : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end


SWIFT_CLASS("_TtC19TSAuthenticationSDK52TSWebAuthnAuthenticationCredentialRequestOptionsData")
@interface TSWebAuthnAuthenticationCredentialRequestOptionsData : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end


SWIFT_CLASS("_TtC19TSAuthenticationSDK36TSWebAuthnAuthenticatorSelectionData")
@interface TSWebAuthnAuthenticatorSelectionData : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end


SWIFT_CLASS("_TtC19TSAuthenticationSDK38TSWebAuthnCredentialRequestOptionsData")
@interface TSWebAuthnCredentialRequestOptionsData : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end


SWIFT_CLASS("_TtC19TSAuthenticationSDK30TSWebAuthnPubKeyCredParamsData")
@interface TSWebAuthnPubKeyCredParamsData : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end


SWIFT_CLASS("_TtC19TSAuthenticationSDK16TSWebAuthnRPData")
@interface TSWebAuthnRPData : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end


SWIFT_CLASS("_TtC19TSAuthenticationSDK18TSWebAuthnUserData")
@interface TSWebAuthnUserData : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end




#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ public typealias TSTOTPRegistrationCompletion = (Result<TSTOTPRegistrationResult
public typealias TSTOTPGenerateCodeCompletion = (Result<TSTOTPGenerateCodeResult, TSAuthenticationError>) -> ()
public typealias TSApprovalCompletion = (Result<TSAuthenticationResult, TSAuthenticationError>) -> ()
public typealias TSNativeBiometricsApprovalCompletion = (Result<TSNativeBiometricsAuthenticationResult, TSAuthenticationError>) -> ()
public typealias TSSignChallengeCompletion = (Result<TSSignChallengeResult, TSAuthenticationError>) -> Void
public typealias TSPinCodeRegistrationCompletion = (Result<TSPinCodeRegistrationResult, TSAuthenticationError>) -> ()
public typealias TSPinCodeAuthenticationCompletion = (Result<TSPinCodeAuthenticationResult, TSAuthenticationError>) -> ()
public typealias TSPinCodeUnregistrationCompletion = (Result<TSPinCodeUnregistrationResult, TSAuthenticationError>) -> ()

/// Alternate paths used by the SDK to route API calls to your proxy server.
public struct WebAuthnApis: Codable {
Expand Down Expand Up @@ -146,6 +150,17 @@ final public class TSAuthentication: NSObject, TSBaseAuthenticationSdkProtocol,
controller.register(username: username, displayName: displayName, completion: completion)
}

/**
Initiates the client-side WebAuthn credential registration process using parameters provided by the backend.
- Parameter webAuthnRegistrationData: The JSON response object received from your backend containing the necessary data to initiate the WebAuthn registration on the client device.
- Parameter completion: An optional closure that is called asynchronously upon the completion (either success or failure) of the WebAuthn registration attempt.
*/
public func registerWebAuthn(_ webAuthnRegistrationData: TSWebAuthnRegistrationData, completion: TSRegistrationCompletion?) {
guard let controller else { completion?(.failure(.notInitialized)); return }
// 1. webauthn-registration: start registration
controller.register(webAuthnRegistrationData, completion: completion)
}

/**
Invokes a WebAuthn credential authentication, including prompting the user for biometrics.
If authentication is completed successfully, this function will return a callback containing a WebAuthnEncodedResult.
Expand All @@ -158,7 +173,18 @@ final public class TSAuthentication: NSObject, TSBaseAuthenticationSdkProtocol,
}

/**
Invokes a WebAuthn credential sign transaction, including prompting the user for biometrics.
Invokes a WebAuthn credential authentication, including prompting the user for biometrics.
- Parameter webAuthnAuthenticationData: The JSON response object received from your backend containing the necessary data to initiate the WebAuthn authentication on the client device.
- Parameter completion: A closure that is called asynchronously upon the completion (success or failure) of the WebAuthn authentication attempt.
*/
public func authenticateWebAuthn(_ webAuthnAuthenticationData: TSWebAuthnAuthenticationData, options: TSAuthentication.WebAuthnAuthenticationOptions = [], completion: TSAuthenticationCompletion? = nil) {
guard let controller else { completion?(.failure(.notInitialized)); return }

controller.authenticate(webAuthnAuthenticationData, options: options, completion: completion)
}

/**
Invokes a WebAuthn credential signing transaction, including prompting the user for biometrics.
If transaction signing is completed successfully, this function will return a callback containing a WebAuthnEncodedResult.
The WebAuthnEncodedResult should be used to make a completion request using your backend API which will commuincate with Transmit's Service
*/
Expand All @@ -168,6 +194,17 @@ final public class TSAuthentication: NSObject, TSBaseAuthenticationSdkProtocol,
controller.authenticate(username: username, options: options, completion: completion)
}

/**
Initiates a WebAuthn credential signing transaction, typically prompting the user for biometrics or a security key.
- Parameter webAuthnAuthenticationData: The JSON response object received from your backend containing the necessary data to initiate the WebAuthn authentication on the client device.
- Parameter completion: A closure called asynchronously upon completion (success or failure) of the WebAuthn signing attempt.
*/
public func signWebauthnTransaction(_ webAuthnAuthenticationData: TSWebAuthnAuthenticationData, options: TSAuthentication.WebAuthnAuthenticationOptions = [], completion: TSAuthenticationCompletion? = nil) {
guard let controller else { completion?(.failure(.notInitialized)); return }

controller.authenticate(webAuthnAuthenticationData, options: options)
}

/**
Invokes a WebAuthn credential authentication, including prompting the user for biometrics, in order to verify a user's authorization for a specific action.
If authentication is completed successfully, this function will return a callback containing a WebAuthnEncodedResult.
Expand All @@ -184,6 +221,20 @@ final public class TSAuthentication: NSObject, TSBaseAuthenticationSdkProtocol,
controller.approval(username: username, approvalData: approvalData, options: options, completion: completion)
}

/**
Invokes a WebAuthn credential authentication, including prompting the user for biometrics, in order to verify a user's authorization for a specific action.
If authentication is completed successfully, this function will return a callback containing a WebAuthnEncodedResult.
The WebAuthnEncodedResult should be used to make a completion request using your backend API which will commuincate with Transmit's Service

- Parameter webAuthnAuthenticationData: The JSON response object received from your backend containing the necessary data to initiate the WebAuthn approval on the client device.
- Parameter completion: A closure that is called asynchronously upon the completion (success or failure) of the WebAuthn approval attempt.
*/
public func approvalWebAuthn(_ webAuthnAuthenticationData: TSWebAuthnAuthenticationData, options: TSAuthentication.WebAuthnAuthenticationOptions = [], completion: TSApprovalCompletion? = nil) {
guard let controller else { completion?(.failure(.notInitialized)); return }

controller.approval(webAuthnAuthenticationData, options: options, completion: completion)
}

/**
Registers native biometrics (Touch ID or Face ID) on the device for user authentication.
*/
Expand Down Expand Up @@ -272,6 +323,131 @@ final public class TSAuthentication: NSObject, TSBaseAuthenticationSdkProtocol,

controller.generateTOTPCodeWithChallenge(UUID: UUID, challenge: challenge, completion: completion)
}

/// Registers a new PIN code for the given user, calling the completion handler when done.
///
/// - Parameters:
/// - username: The user’s identifier.
/// - pinCode: The PIN string to register.
/// - completion: A callback invoked on the MainActor with either:
/// • `.success(TSPinCodeRegistrationResult)` on success, or
/// • `.failure(TSAuthenticationError)` on error.
public func registerPinCode(username: String, pinCode: String, completion: @escaping TSPinCodeRegistrationCompletion) {
Task { @MainActor in
do {
let result = try await registerPinCode(username: username, pinCode: pinCode)
completion(.success(result))
} catch let error as TSPinCodeError {
completion(.failure(.pinCodeError(error)))
} catch {
completion(.failure(.pinCodeError(.internal(error))))
}
}
}

/// Async variant that actually performs the PIN registration.
///
/// - Parameters:
/// - username: The user’s identifier.
/// - pinCode: The PIN string to register.
/// - Returns: `TSPinCodeRegistrationResult` on success.
/// - Throws: `TSAuthenticationError` from the controller.
public func registerPinCode(username: String, pinCode: String) async throws -> TSPinCodeRegistrationResult {
guard let controller else { throw TSAuthenticationError.notInitialized }

do {
return try await controller.registerPINCode(username: username, pinCode: pinCode)
} catch let error as TSPinCodeError {
TSLog.e("PIN code registration failed with error: \(error)")
throw TSAuthenticationError.pinCodeError(error)
} catch {
TSLog.e("PIN code registration failed with error: \(error)")
throw TSAuthenticationError.pinCodeError(.internal(error))
}
}

/// Authenticates a user’s PIN against a server‐provided challenge, calling the completion handler when done.
///
/// - Parameters:
/// - username: The user’s identifier.
/// - pinCode: The entered PIN string.
/// - challenge: A server‐provided challenge string to sign/verify.
/// - completion: A callback invoked on the MainActor with either:
/// • `.success(TSPinCodeAuthenticationResult)` on success, or
/// • `.failure(TSAuthenticationError)` on error.
public func authenticatePinCode(username: String, pinCode: String, challenge: String, completion: @escaping TSPinCodeAuthenticationCompletion) {
Task { @MainActor in
do {
let result = try await authenticatePinCode(username: username, pinCode: pinCode, challenge: challenge)
completion(.success(result))
} catch let error as TSPinCodeError {
completion(.failure(.pinCodeError(error)))
} catch {
completion(.failure(.pinCodeError(.internal(error))))
}
}
}

/// Unregister user's Pin Code authenticator.
///
/// - Parameters:
/// - username: The user’s identifier.
/// - completion: A callback invoked on the MainActor with either:
/// • `.success(TSPinCodeUnregistrationResult)` on success, or
/// • `.failure(TSAuthenticationError)` on error.
public func unregisterPinCode(username: String, completion: @escaping TSPinCodeUnregistrationCompletion) {
Task { @MainActor in
do {
let result = try await unregisterPinCode(username: username)
completion(.success(result))
} catch let error as TSPinCodeError {
completion(.failure(.pinCodeError(error)))
} catch {
completion(.failure(.pinCodeError(.internal(error))))
}
}
}

/// Unregister user's Pin Code authenticator.
///
/// - Parameters:
/// - username: The user’s identifier.
/// - Returns: `TSPinCodeUnregistrationResult` on success.
/// - Throws: `TSAuthenticationError` from the controller.
public func unregisterPinCode(username: String) async throws -> TSPinCodeUnregistrationResult {
guard let controller else { throw TSAuthenticationError.notInitialized }

do {
return try await controller.unregisterPinCode(username: username)
} catch let error as TSPinCodeError {
TSLog.e("PIN code unregistration failed with error: \(error)")
throw TSAuthenticationError.pinCodeError(error)
} catch {
TSLog.e("PIN code unregistration failed with error: \(error)")
throw TSAuthenticationError.pinCodeError(.internal(error))
}
}

/// Async variant that actually performs the PIN authentication.
///
/// - Parameters:
/// - username: The user’s identifier.
/// - pinCode: The entered PIN string.
/// - challenge: The server‐provided challenge to prove possession of the PIN key.
/// - Returns: `TSPinCodeAuthenticationResult` on success.
/// - Throws: `TSAuthenticationError` from the controller.
public func authenticatePinCode(username: String, pinCode: String, challenge: String) async throws -> TSPinCodeAuthenticationResult {
guard let controller else { throw TSAuthenticationError.notInitialized }
do {
return try await controller.authenticatePinCode(username: username, pinCode: pinCode, challenge: challenge)
} catch let error as TSPinCodeError {
TSLog.e("PIN code authentication failed with error: \(error)")
throw TSAuthenticationError.pinCodeError(error)
} catch {
TSLog.e("PIN code authentication failed with error: \(error)")
throw TSAuthenticationError.pinCodeError(.internal(error))
}
}

/**
Retrieves device-specific information, such as public key and its associated ID, which are unique to the application installed on the device.
Expand All @@ -282,6 +458,15 @@ final public class TSAuthentication: NSObject, TSBaseAuthenticationSdkProtocol,
controller.getDeviceInfo(completion)
}

/**
Signs the `challenge` string with the device key.
- Parameter challenge: The string to sign.
- Parameter completion: The callback containing either error or result object contaiting signed challenge.
*/
public func signWithDeviceKey(challenge: String, completion: @escaping TSSignChallengeCompletion) {
controller?.signChallenge(challenge, completion: completion)
}

/**
Checks if the WebAuthn feature is supported on the current iOS version.
@return
Expand Down
Binary file not shown.
Loading