Keyboard-Interactive Authentication
Generic challenge-response authentication through async callbacks.
Public Method
Traversio exposes generic keyboard-interactive authentication through:
.keyboardInteractive(
submethods: [String],
responseProvider: @Sendable (SSHKeyboardInteractiveChallenge) async throws -> [String]
)submethods is the optional hint list sent in the initial keyboard-interactive request.
For the common case, pass [].
End-to-End Example
import Traversio
@available(macOS 26.0, iOS 26.0, *)
func connectWithKeyboardInteractive(password: String) async throws {
let configuration = SSHClientConfiguration(
host: "example.com",
username: "deploy",
authentication: .keyboardInteractive(
submethods: [],
responseProvider: { challenge in
if challenge.prompts.count == 1,
challenge.prompts[0].prompt.localizedCaseInsensitiveContains("password") {
return [password]
}
throw CancellationError()
}
),
hostKeyPolicy: .knownHostsFile("/Users/me/.ssh/known_hosts")
)
try await SSHClient.withConnection(configuration: configuration) { connection in
let result = try await connection.execute("whoami")
print(String(decoding: result.standardOutput, as: UTF8.self))
}
}Challenge Model
SSHKeyboardInteractiveChallenge includes:
usernameserviceNamenameinstructionlanguageTagprompts
Each SSHKeyboardInteractivePrompt contains:
promptshouldEcho
Traversio supports multiple challenge rounds, including zero-prompt informational messages, and preserves prompt order when sending responses back to the server.
Important Rules
- your callback must return exactly one response per prompt
- if the response count does not match, Traversio throws
SSHAuthenticationMethodError.invalidKeyboardInteractiveResponseCount(expected:received:) - if the server sends a zero-prompt informational message, your callback should return
[] - UI integration, secure secret storage, and higher-level password heuristics remain application responsibilities
Limits
Supported behavior:
- generic challenge-response auth
- multi-round exchanges
- zero-prompt informational messages
Remaining gaps:
- live OpenSSH validation specifically for this public path
- helper adapters for system UI or secure secret stores
- broader host-key verification and the rest of the auth hardening matrix around this public path