diff --git a/cyberduck/bookmarks.md b/cyberduck/bookmarks.md
index 0f29b5e7..a96a7768 100644
--- a/cyberduck/bookmarks.md
+++ b/cyberduck/bookmarks.md
@@ -114,6 +114,7 @@ Select *Bookmark → Edit Bookmark (macOS `⌘E` Windows `Strg+E`)*. A panel whe
| Connect
Mode | For [FTP](../protocols/ftp.md) connections only. Refer to [FTP Connect Mode](../protocols/ftp.md#ftp-connect-mode). |
| Encoding | For [FTP](../protocols/ftp.md) connections only. Character encoding of filenames on the server. You can also change
the encoding used when the connection is open using *View → Text Encoding* if characters
are not displayed properly. Try `UTF-8` (the default), `ISO-8859-1`, and `Windows-1252`.
Refer to [Character Encoding](../protocols/ftp.md#character-encoding). |
| Timezone | For all protocols except [FTP](../protocols/ftp.md), timestamps are reported in [UTC](http://en.wikipedia.org/wiki/Coordinated_Universal_Time) from the server and there is no
need for configuration. All timestamps in the browser are automatically converted to the timezone
you have configured in the *System Preferences* and displayed in local time. For [FTP](../protocols/ftp.md)
however, the local timezone is assumed for timestamps in directory listings If the server
is configured with a different timezone that your Mac and returning the local time for
modification dates, there will be an offset by the timezone difference. To get the correct local
time for modification dates in the browser, you can choose the timezone of the server in the
bookmark settings. Select *Bookmark → Edit Bookmark*. |
+| Kerberos
Realm | For [SFTP](../protocols/sftp/index.md) connections only. Default realm for [Kerberos authentication](../tutorials/sftp_kerberos.md#kerberos-realm-per-bookmark).
Leave empty to use the default realm from the Kerberos configuration. |
### Passwords
diff --git a/protocols/profiles/index.md b/protocols/profiles/index.md
index 7e633199..5696d28f 100644
--- a/protocols/profiles/index.md
+++ b/protocols/profiles/index.md
@@ -70,6 +70,7 @@ The value of `Vendor` must be unique among all installed connection profiles.
- `Anonymous Configurable` Boolean if anonymous access is configurable.
- `Path Configurable` Boolean if default path is configurable.
- `Certificate Configurable` Boolean if client certificate is configurable.
+- `Kerberos Configurable` Boolean if the Kerberos realm is configurable in the bookmark. Defaults to `true` for [SFTP](../sftp/index.md) profiles.
- `Role Configurable`. Boolean if role is configurable. Typically an ARN referencing the AWS IAM role to assume using AWS STS API.
- `Region` Location constraint for [OpenStack Swift](../openstack/index.md) and [S3](../s3/index.md) profiles.
:::{admonition} S3
diff --git a/protocols/sftp/index.md b/protocols/sftp/index.md
index a70650e1..a947f0c5 100644
--- a/protocols/sftp/index.md
+++ b/protocols/sftp/index.md
@@ -9,6 +9,11 @@ providers
../../tutorials/sftp_publickeyauth_1password
../../tutorials/sftp_publickeyauth_bitwarden
../../tutorials/sftp_publickeyauth_yubikey
+../../tutorials/sftp_publickeyauth_pageant
+../../tutorials/sftp_publickeyauth_securitykey
+../../tutorials/sftp_publickeyauth_pkcs11
+../../tutorials/sftp_kerberos
+../../tutorials/sftp_azure_blob_storage
:::
:::{image} ../_images/ftp.png
@@ -32,7 +37,7 @@ If you have access to a server using a secure shell ([SSH2](http://en.wikipedia.
#### Public Key Fingerprints
-Public key fingerprints are checked against and written to `~/ssh/known_hosts` when accepted. This does not apply to the Mac App Store version which does store key fingerprints in the preferences.
+Public key fingerprints are checked against and written to `~/.ssh/known_hosts` when accepted. This does not apply to the Mac App Store version which does store key fingerprints in the preferences.
#### Configuration File
@@ -41,10 +46,15 @@ The following configuration options from `~/.ssh/config` are supported for SFTP
- *IdentityFile* for public key authentication.
- *IdentityAgent* for public key authentication. Specifies the UNIX-domain socket used to communicate with the authentication agent.
- *HostName* aliases.
+- *Port* to connect to.
- *User* preference for login credentials.
- *ProxyJump* to connect via SSH tunnel through bastion server.
-- *PreferredAuthentications* to limit authentication methods tried to login.
-- *IdentitiesOnly*. Only try explicitly set private keys to authenticate but not all identities found in SSH agent. Resolves _Too many authentication failures_ errors with servers limiting the number of attempted authentication requests.
+- *ProxyCommand* to connect through the standard input and output of a command.
+- *PreferredAuthentications* to set the order of authentication methods tried to login. Methods not listed are still tried afterwards.
+- *IdentitiesOnly*. Only try the private key set with *IdentityFile* in `~/.ssh/config` to authenticate but not all identities found in SSH agent. The key selected in the bookmark does not apply. With no *IdentityFile* set, no identity from the SSH agent is offered. Resolves _Too many authentication failures_ errors with servers limiting the number of attempted authentication requests.
+- *Include* to read other configuration files and *Match* blocks with the criteria `host` and `user`.
+- *SecurityKeyProvider* for the middleware library signing with a [FIDO2 security key](../../tutorials/sftp_publickeyauth_securitykey.md) for `sk-ecdsa-sha2-nistp256@openssh.com` and `sk-ssh-ed25519@openssh.com` keys.
+- *PKCS11Provider* for the module reading keys from a [smartcard](../../tutorials/sftp_publickeyauth_pkcs11.md).
- A [bookmark](../../cyberduck/bookmarks.md) will update its public key authentication setting from the *IdentityFile* configuration in `~/.ssh/config`. Also when opening a new [connection](../../cyberduck/connection.md#toolbar-button) using *File → Open Connection…, IdentityFile* and *User* parameters in the OpenSSH user config file are auto completed.
Example `~/.ssh/config` configuration:
@@ -97,23 +107,54 @@ Follow the [step-by-step instructions](../../tutorials/sftp_publickeyauth.md) to
#### PuTTY Key Format Interoperability
-PuTTY private keys (`.ppk`) are supported for `rsa` key types. `ed25519` is not supported.
+PuTTY private keys (`.ppk`) are supported for `rsa`, `dsa`, `ecdsa` and `ed25519` key types.
#### OpenSSH Key Format Interoperability
-OpenSSH private keys of type `rsa`, `dsa`, `ecdsa` and `ed25519` (in OpenSSL `PEM` format) are supported. The new OpenSSH format (`openssh-key-v1`) is only supported for `ecdsa` and `ed25519`.
+OpenSSH private keys of type `rsa`, `dsa`, `ecdsa` and `ed25519` (in OpenSSL `PEM` format) are supported. The new OpenSSH format (`openssh-key-v1`) is supported for `rsa`, `ecdsa` and `ed25519` but not for `dsa`.
##### OpenSSH User Certificate Authentication
+Applies to SSH servers, which are configured with [`TrustedUserCAKeys`](https://man.openbsd.org/sshd_config#TrustedUserCAKeys), refer to your software vendor for configuration. To configure authentication with a User CA signed private key, configure the private key as described in [Configure Public Key Authentication](#public-key-authentication) step 3. The signed public key file _must_ reside next to the private key file, suffixed `-cert.pub` or `.pub`. The [`CertificateFile`](https://man.openbsd.org/ssh_config#CertificateFile) configuration directive in `~/.ssh/config` is not supported. Pay attention to the server configuration and [`PubkeyAcceptedAlgorithms`](https://man.openbsd.org/sshd_config#PubkeyAcceptedAlgorithms) specifically which determines the allowed private key algorithms to authenticate with.
+
+#### Security Key (FIDO2) Authentication
+
:::{important}
-* Cyberduck [8.9.0](https://cyberduck.io/changelog/) or later required
-* Mountain Duck [4.16.0](https://mountainduck.io/changelog/) or later required
+* Cyberduck [9.6.0](https://cyberduck.io/changelog/) or later required
:::
-Applies to SSH servers, which are configured with [`TrustedUserCAKeys`](https://man.openbsd.org/sshd_config#TrustedUserCAKeys), refer to your software vendor for configuration. To configure authentication with a User CA signed private key, configure the private key as described in [Configure Public Key Authentication](#public-key-authentication) step 3. The signed public key file _must_ reside next to the private key file, suffixed `-cert.pub` or `.pub`. The [`CertificateFile`](https://man.openbsd.org/ssh_config#CertificateFile) configuration directive in `~/.ssh/config` is not supported. Pay attention to the server configuration and [`PubkeyAcceptedAlgorithms`](https://man.openbsd.org/sshd_config#PubkeyAcceptedAlgorithms) specifically which determines the allowed private key algorithms to authenticate with.
+Keys of type `sk-ecdsa-sha2-nistp256@openssh.com` and `sk-ssh-ed25519@openssh.com` created with `ssh-keygen -t ecdsa-sk` respectively `ssh-keygen -t ed25519-sk` are supported. The private key of such a key never leaves the authenticator, which is either the Secure Enclave of a Mac unlocked with _Touch ID_ or a hardware token such as a _YubiKey_ touched to confirm. The key file selected in the [Bookmark](../../cyberduck/bookmarks.md) holds the credential handle only.
+
+Signing a login is delegated to the middleware library of the authenticator, set with the [`SecurityKeyProvider`](#configuration-file) directive in `~/.ssh/config`, the `SSH_SK_PROVIDER` environment variable or the [hidden configuration option](../../tutorials/hidden_properties.md) `ssh.authentication.securitykey.provider`. A value of the configuration directive beginning with `$` is read from the environment variable of that name. It defaults to `/usr/lib/ssh-keychain.dylib` for keys in the Secure Enclave on macOS. There is no default on other platforms, where OpenSSH talks to a token with built-in USB HID support instead of a library that could be loaded. Add the key to an [SSH agent](#public-key-authentication-using-ssh-agent) there, which prompts to confirm the login and works with any token supported by OpenSSH, or set the directive or option to a middleware library for the token.
+
+:::{important}
+The server must run _OpenSSH 8.2_ or later. Earlier versions do not know the `sk-*` key types and ignore the entry in `authorized_keys`.
+:::
+
+:::{admonition} Tutorial
+:class: tip
+
+Follow the [step-by-step instructions](../../tutorials/sftp_publickeyauth_securitykey.md) to create a key in the Secure Enclave or on a hardware token and connect with it.
+:::
+
+#### Smartcard (PKCS#11) Authentication
+
+:::{important}
+* Cyberduck [9.6.0](https://cyberduck.io/changelog/) or later required
+:::
+
+Private keys kept on a smartcard are read with the _PKCS#11_ module of the card, the equivalent of `ssh -I`. Every key on the card with a matching certificate is offered to the server in turn and the PIN is prompted for when required by the card. A key on a card without a certificate is not found.
+
+Set the module with the [`PKCS11Provider`](#configuration-file) directive in `~/.ssh/config` or the [hidden configuration option](../../tutorials/hidden_properties.md) `ssh.authentication.pkcs11.library`. Set an absolute path to the module. On macOS, the file name `opensc-pkcs11.so` of the _OpenSC_ module bundled with the application is accepted as well. Set the [hidden configuration option](../../tutorials/hidden_properties.md) `ssh.authentication.pkcs11.enable` to `false` to disable authentication with a smartcard.
+
+:::{admonition} Tutorial
+:class: tip
+
+Follow the [step-by-step instructions](../../tutorials/sftp_publickeyauth_pkcs11.md) to authenticate with a key on a smartcard.
+:::
#### Public Key Authentication Using SSH Agent
-When connecting to a SSH server, Cyberduck will lookup matching private keys from the SSH agent when attempting to authenticate with the server if no password is available and no explicit private key to use is configured in the bookmark.
+When connecting to a SSH server, Cyberduck will try the identities from the SSH agent to authenticate with the server. When a password is saved for the bookmark, password authentication is attempted first. When a private or public key is selected in the bookmark, only the identity in the agent matching this key is offered. If no identity matches, all identities are offered. Disable the use of the SSH agent with the [hidden configuration option](../../tutorials/hidden_properties.md) `ssh.authentication.agent.enable=false`.
:::{admonition} Mac App Store
:class: attention
@@ -146,14 +187,10 @@ Host myhostname
IdentityAgent ~/.bitwarden-ssh-agent.sock
```
-
:::
:::{group-tab} Windows
-The following agents are supported:
- * [Pageant](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html). Refer to [How To Use Pageant to Streamline SSH Key Authentication with PuTTY](https://www.digitalocean.com/community/tutorials/how-to-use-pageant-to-streamline-ssh-key-authentication-with-putty).
- * OpenSSH for Windows using the pipe (`\\.\pipe\openssh-ssh-agent`) by default. Use `IdentityAgent` to set a custom socket path for any other compatible agent if needed.
- * [1Password SSH agent](https://developer.1password.com/docs/ssh/agent/compatibility/#cyberduck)
+SSH agents that provide a named pipe are supported, such as the OpenSSH agent, the [1Password SSH agent](https://developer.1password.com/docs/ssh/agent/compatibility/#cyberduck) and [Pageant](../../tutorials/sftp_publickeyauth_pageant.md). The OpenSSH agent pipe (`\\.\pipe\openssh-ssh-agent`) is used by default. Use `IdentityAgent` to set a different pipe if needed.
:::
::::
@@ -175,6 +212,24 @@ Host myhostname
Alternatively you can select the public key file in the [bookmark](../../cyberduck/bookmarks.md#edit-bookmark) configuration.
+### Kerberos (GSSAPI) Authentication
+
+:::{important}
+* Cyberduck [9.6.0](https://cyberduck.io/changelog/) or later required
+:::
+
+Authentication with the method `gssapi-with-mic` using a _Kerberos_ ticket obtained with `kinit` is supported. The method is attempted after public key authentication and before prompting for a password when no password is saved for the bookmark. Without a valid ticket the login continues with the next authentication method. Connect using the fully qualified hostname matching the service principal of the server.
+
+The Kerberos configuration is read from the default location such as `/etc/krb5.conf`. Use the [hidden configuration options](../../tutorials/hidden_properties.md) `java.security.krb5.conf` to set a different configuration file or `java.security.krb5.realm` and `java.security.krb5.kdc` to set the realm and KDC without a configuration file.
+
+Set the realm of the server in _Kerberos Realm_ of the [bookmark](../../cyberduck/bookmarks.md#bookmark-options) when no default realm is configured or the server belongs to a different realm.
+
+:::{admonition} Tutorial
+:class: tip
+
+Follow the [step-by-step instructions](../../tutorials/sftp_kerberos.md) to authenticate with a Kerberos ticket.
+:::
+
### One-Time Passcodes (2FA)
Using a challenge-response authentication with one-time password generators such as [*DUO*](https://duo.com/product/multi-factor-authentication-mfa), [*SecurID*](https://www.rsa.com/products/securid/) or [*Google Authenticator*](https://github.com/google/google-authenticator) is supported. After the initial login prompt for the username and password, a second login prompt is displayed to enter the one-time passcode.
@@ -254,7 +309,7 @@ Use *View → Customize Toolbar...* to add the *Terminal.app* toolbar icon to yo
You can change the SSH command using the [hidden configuration option](../../tutorials/hidden_properties.md)
```
-terminal.command.ssh=\"ssh\ -t\ {0}\ {1}@{2}\ -p\ {3}\ \\\"cd\ {4}\ \&\&\ exec\ \\\\\$SHELL\\\"\"
+terminal.command.ssh=\"ssh\ -t\ {0}\ {1}@{2}\ -p\ {3}\ \\\"cd\ {4}\ \&\&\ exec\ \\\\\$SHELL\ -l\\\"\"
```
where
@@ -265,7 +320,7 @@ where
- {3} is the port number of the remote host
- {4} is the current working directory in the browser
-Because of all the escaping of characters, it might be easier to edit the key using *Property List Editor* if you have the developer tools installed. You can then set the string for the key `terminal.command.ssh to ssh -t {0} {1}@{2} -p {3} "cd {4} && exec \$SHELL"`. Test the string in *Terminal.app* first if it is valid.
+Because of all the escaping of characters, it might be easier to edit the key using *Property List Editor* if you have the developer tools installed. You can then set the string for the key `terminal.command.ssh` to `ssh -t {0} {1}@{2} -p {3} "cd {4} && exec \$SHELL -l"`. Test the string in *Terminal.app* first if it is valid.
**Using [iTerm2](https://www.iterm2.com/)**
@@ -364,11 +419,11 @@ You can set Cyberduck or a third-party application as the default application (p
### Key Exchange
-`diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`, `diffie-hellman-group14-sha256`, `diffie-hellman-group15-sha512`, `diffie-hellman-group16-sha512`, `diffie-hellman-group17-sha512`, `diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `curve25519-sha256@libssh.org`
+`curve25519-sha256`, `curve25519-sha256@libssh.org`, `diffie-hellman-group-exchange-sha256`, `ecdh-sha2-nistp521`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp256`, `diffie-hellman-group-exchange-sha1`, `diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`, `diffie-hellman-group14-sha256`, `diffie-hellman-group15-sha512`, `diffie-hellman-group16-sha512`, `diffie-hellman-group17-sha512`, `diffie-hellman-group18-sha512`, `diffie-hellman-group14-sha256@ssh.com`, `diffie-hellman-group15-sha256`, `diffie-hellman-group15-sha256@ssh.com`, `diffie-hellman-group15-sha384@ssh.com`, `diffie-hellman-group16-sha256`, `diffie-hellman-group16-sha384@ssh.com`, `diffie-hellman-group16-sha512@ssh.com`, `diffie-hellman-group18-sha512@ssh.com`
### SSH Key Types
-`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `ssh-ed25519`, `rsa-sha2-256`, `rsa-sha2-512`
+`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `ssh-ed25519`, `rsa-sha2-256`, `rsa-sha2-512`, `sk-ecdsa-sha2-nistp256@openssh.com`, `sk-ssh-ed25519@openssh.com`
### SSH Certificate Key Types
@@ -380,7 +435,7 @@ Compression with `zlib` and `zlib@openssh.com` is supported.
### Private Key Files
-`pkcs5`, `pkcs8`, `openssh-key-v1`
+`pkcs5`, `pkcs8`, `openssh-key-v1`, PuTTY `.ppk`
## Incompatibilities
@@ -399,7 +454,7 @@ Running an SSH agent with many added identities can lead to the server error _To
Possible remedies using configuration in [OpenSSH configuration file](#openssh-configuration-interoperability):
- [`IdentitiesOnly`](https://man.openbsd.org/ssh_config.5#IdentitiesOnly) in client configuration file `~/.ssh/config`. Only try to authenticate with explicitly set private key instead of all identities retrieved from SSH agent.
-- Set [`PreferredAuthentications`](https://man.openbsd.org/ssh_config.5#PreferredAuthentications) in client configuration file `~/.ssh/config` to disable public key authentication for example.
+- Set [`PreferredAuthentications`](https://man.openbsd.org/ssh_config.5#PreferredAuthentications) in client configuration file `~/.ssh/config` to try another method such as `password` before public key authentication. Methods not listed are still tried afterwards.
### Illegal SFTP Packet Length: `Invalid packet: indicated length 1114795883 too large`
diff --git a/tutorials/index.md b/tutorials/index.md
index f5b267ec..7c30c757 100644
--- a/tutorials/index.md
+++ b/tutorials/index.md
@@ -17,10 +17,14 @@ owncloud_opencloud_oidc
iam
vault_localdisk
sftp_publickeyauth
+sftp_publickeyauth_securitykey
+sftp_publickeyauth_pkcs11
sftp_publickeyauth_1password
sftp_publickeyauth_bitwarden
sftp_publickeyauth_yubikey
sftp_azure_blob_storage
+sftp_publickeyauth_pageant
+sftp_kerberos
cli_github_action
:::
@@ -65,6 +69,12 @@ Both [Cyberduck](../cyberduck/index.md) and [Mountain Duck](../mountainduck/inde
## [Configure Public Key Authentication for SFTP](sftp_publickeyauth.md)
Configure Public Key Authentication for SFTP using OpenSSH tools.
+### [Use a FIDO2 Security Key](sftp_publickeyauth_securitykey.md)
+Authenticate with a `sk-*` key in the Secure Enclave unlocked with Touch ID or on a hardware token such as a YubiKey.
+
+### [Use a PKCS#11 Smartcard](sftp_publickeyauth_pkcs11.md)
+Authenticate with a private key kept on a smartcard read with a PKCS#11 module such as OpenSC.
+
### [Configure 1Password SSH Agent](sftp_publickeyauth_1password.md)
Authenticate with SSH private key saved in 1Password.
@@ -77,5 +87,11 @@ Authenticate with SSH private key saved on YubiKey.
## [Connect to Azure Blob Storage with SFTP](sftp_azure_blob_storage.md)
Authenticate with a local user using a password or private key, or with an SSH certificate issued by Microsoft Entra ID.
+### [Configure Pageant](sftp_publickeyauth_pageant.md)
+Authenticate with SSH private key loaded in Pageant.
+
+## [Configure Kerberos Authentication for SFTP](sftp_kerberos.md)
+Authenticate with a Kerberos ticket obtained with `kinit` using GSSAPI.
+
## [Use Cyberduck CLI GitHub Action](cli_github_action.md)
Use Cyberduck CLI Docker Container in GitHub Actions
\ No newline at end of file
diff --git a/tutorials/sftp_kerberos.md b/tutorials/sftp_kerberos.md
new file mode 100644
index 00000000..2e56d8ba
--- /dev/null
+++ b/tutorials/sftp_kerberos.md
@@ -0,0 +1,172 @@
+Configure Kerberos Authentication for SFTP
+====
+
+> Authentication with _Kerberos_ allows you to connect to a remote server without a password using the ticket you already obtained when logging in to your organization's realm with `kinit` or with your account on the Mac. The ticket is presented to the server using the SSH authentication method `gssapi-with-mic`, the equivalent of `ssh -o GSSAPIAuthentication=yes`.
+
+:::{important}
+* Cyberduck [9.7.0](https://cyberduck.io/changelog/) or later required
+* Mountain Duck [6.0.0](https://mountainduck.io/changelog/) or later required
+:::
+
+Authentication with Kerberos is attempted after public key authentication and before prompting for a password when no password is saved for the bookmark. Without a valid ticket the method is skipped and the login continues with the next authentication method offered by the server.
+
+## Requirements
+
+- The server running OpenSSH is configured with `GSSAPIAuthentication yes` in `sshd_config` and has a keytab with the service principal `host/server.example.com@EXAMPLE.COM` for its fully qualified hostname. Refer to your administrator.
+- Your principal such as `user@EXAMPLE.COM` is allowed to log in to the account on the server. By default the principal `user@EXAMPLE.COM` maps to the account `user`. Additional principals are listed in `~/.k5login` of the account on the server.
+- The Kerberos configuration with the default realm and the Key Distribution Center (KDC) of your organization is found in `/etc/krb5.conf` or can be looked up in DNS. Alternatively set the [realm in the bookmark](#kerberos-realm-per-bookmark).
+- On Windows, [MIT Kerberos for Windows](https://web.mit.edu/kerberos/dist/) is installed to obtain the ticket.
+
+## Setup
+
+:::::{tabs}
+::::{group-tab} macOS
+
+1. Obtain a ticket for your principal. Enter the password of your Kerberos account when prompted.
+ ```
+ kinit user@EXAMPLE.COM
+ ```
+
+ :::{tip}
+ Tickets obtained with _Ticket Viewer.app_ in `/System/Library/CoreServices/Applications` or when logging in to a Mac bound to a directory service with Kerberos are used as well.
+ :::
+
+2. Verify a ticket for the realm is listed and has not expired.
+ ```
+ klist
+ ```
+
+3. Verify the setup with OpenSSH before connecting with Cyberduck. Use the fully qualified hostname of the server.
+ ```
+ ssh -o GSSAPIAuthentication=yes -o PreferredAuthentications=gssapi-with-mic user@server.example.com
+ ```
+
+ A service ticket for `host/server.example.com@EXAMPLE.COM` is now listed with `klist`.
+
+4. Add a new [Bookmark](../cyberduck/bookmarks.md) in Cyberduck or Mountain Duck. Enter the fully qualified hostname `server.example.com` in _Server_ and your account in _Username_. You do **not** need to set a value for _Password_ or select a _SSH Private Key_.
+
+ :::{warning}
+ The hostname must match the service principal in the keytab of the server. Connecting using an IP address or a short hostname may fail when it cannot be resolved to the fully qualified name.
+ :::
+
+5. Optionally enter the realm such as `EXAMPLE.COM` in _Kerberos Realm_ in the _More Options_ tab of the bookmark when no default realm is configured or the server belongs to a [different realm](#kerberos-realm-per-bookmark).
+
+6. Connect to the server. No prompt is displayed when the ticket is accepted.
+
+::::
+::::{group-tab} Windows
+
+The ticket of _MIT Kerberos for Windows_ is kept in memory by its credentials cache server and cannot be read directly.The ticket granting ticket is copied to a temporary credentials cache file for the login using the `klist.exe` and `kcpytkt.exe` tools of MIT Kerberos for Windows. The temporary file is deleted afterwards.
+
+1. Install [MIT Kerberos for Windows](https://web.mit.edu/kerberos/dist/). The tools are looked up in `%ProgramFiles%\MIT\Kerberos\bin`.
+
+2. Obtain a ticket for your principal with _MIT Kerberos Ticket Manager_ or from the command line. Enter the password of your Kerberos account when prompted.
+ ```
+ "%ProgramFiles%\MIT\Kerberos\bin\kinit.exe" user@EXAMPLE.COM
+ ```
+
+3. Verify a ticket for the realm is listed and has not expired.
+ ```
+ "%ProgramFiles%\MIT\Kerberos\bin\klist.exe"
+ ```
+
+4. Add a new [Bookmark](../cyberduck/bookmarks.md). Enter the fully qualified hostname `server.example.com` in _Server_ and your account in _Username_. You do **not** need to set a value for _Password_ or select a _SSH Private Key_.
+
+ :::{warning}
+ The hostname must match the service principal in the keytab of the server. Connecting using an IP address or a short hostname may fail when it cannot be resolved to the fully qualified name.
+ :::
+
+5. Check _Use MIT Kerberos_ in the bookmark.
+
+6. Enter the realm such as `EXAMPLE.COM` in _Kerberos Realm_. This is required unless the [Kerberos configuration](#kerberos-configuration) is found. The configuration `krb5.ini` of MIT Kerberos for Windows in `%ProgramData%\MIT\Kerberos5` is not read.
+
+7. Connect to the server. No prompt is displayed when the ticket is accepted.
+
+::::
+:::::
+
+## Kerberos Realm per Bookmark
+
+Set the realm of the server such as `EXAMPLE.COM` in _Kerberos Realm_ of the [bookmark](../cyberduck/bookmarks.md#bookmark-options) when no default realm is configured on your computer or the server belongs to a different realm than the default realm. The field is found in the _More Options_ tab on macOS.
+
+For a connection with a realm set in the bookmark, a temporary Kerberos configuration with this default realm replaces any [configuration file](#kerberos-configuration). The KDC of the realm is looked up from DNS SRV records unless set with the hidden configuration option `java.security.krb5.kdc`. Other settings from your configuration file such as `[domain_realm]` mappings do not apply to this connection.
+
+The realm is saved in the bookmark as the property `ssh.authentication.gssapi.realm` and can also be set in a [`.duck` bookmark file](hidden_properties.md#in-duck-bookmark-files).
+
+## Kerberos Configuration
+
+The Kerberos configuration is read from `/etc/krb5.conf` or on macOS from `~/Library/Preferences/edu.mit.Kerberos` and `/Library/Preferences/edu.mit.Kerberos` first when found. A minimal configuration for the realm `EXAMPLE.COM` looks like
+```
+[libdefaults]
+ default_realm = EXAMPLE.COM
+
+[realms]
+ EXAMPLE.COM = {
+ kdc = kdc.example.com
+ }
+
+[domain_realm]
+ .example.com = EXAMPLE.COM
+```
+
+Omit the `[realms]` section and add `dns_lookup_kdc = true` to `[libdefaults]` to look up the KDC from `_kerberos._tcp` and `_kerberos._udp` DNS SRV records of the realm instead.
+
+The following [hidden configuration options](hidden_properties.md) apply to all connections. Options marked as per bookmark can be set for a single bookmark as well.
+
+| Option | Description |
+|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `java.security.krb5.conf` | Path to a Kerberos configuration file to use instead of the default location such as `/etc/krb5.conf`. |
+| `java.security.krb5.realm` | Default realm such as `EXAMPLE.COM` overriding the configuration file. Must be set together with `java.security.krb5.kdc`. |
+| `java.security.krb5.kdc` | Hostname of the KDC for the default realm overriding the configuration file. Must be set together with `java.security.krb5.realm`. Separate multiple KDCs with `:`. |
+| `ssh.authentication.gssapi.ticketcache` | Path to a credentials cache file to read the ticket from instead of the default cache. Obtain a ticket written to the file with `kinit -c /path/to/file user@EXAMPLE.COM`. |
+| `ssh.authentication.gssapi.realm` | Per bookmark. Default realm for the connection set with _Kerberos Realm_ in the bookmark. Refer to [Kerberos Realm per Bookmark](#kerberos-realm-per-bookmark). |
+| `ssh.authentication.gssapi.mit` | Per bookmark. Windows only. Set to `true` to copy the ticket from the credentials cache of MIT Kerberos for Windows. Set with _Use MIT Kerberos_ in the bookmark. |
+| `ssh.authentication.gssapi.mit.path` | Windows only. Folder with `klist.exe` and `kcpytkt.exe` of MIT Kerberos for Windows when not installed in `%ProgramFiles%\MIT\Kerberos\bin`. |
+
+Example to set the realm and KDC for Cyberduck on macOS.
+```
+defaults write ch.sudo.cyberduck java.security.krb5.realm EXAMPLE.COM
+defaults write ch.sudo.cyberduck java.security.krb5.kdc kdc.example.com
+```
+
+:::{note}
+A KDC set with `java.security.krb5.kdc` is always contacted on the default port `88`. Use a configuration file with `kdc = kdc.example.com:port` for a KDC listening on a different port.
+:::
+
+## Connection Profiles
+
+The _Kerberos Realm_ field is shown in the bookmark for SFTP connections. Hide it for a [connection profile](../protocols/profiles/index.md) based on SFTP by setting `Kerberos Configurable` to `false`.
+
+## Require Public Key and Kerberos Authentication
+
+Servers can require authentication with both a private key and a Kerberos ticket with `AuthenticationMethods publickey,gssapi-with-mic` in `sshd_config`. Select the private key in _SSH Private Key_ of the bookmark. After the key has been accepted, login completes with the Kerberos ticket.
+
+## Troubleshooting
+
+:::{warning}
+When you are prompted for a password instead, no ticket was found or the server did not accept it. Verify with `klist` that the ticket for the realm has not expired and obtain a new ticket with `kinit` otherwise. Verify the login with `ssh -v -o GSSAPIAuthentication=yes user@server.example.com` which prints the reason why the method failed.
+:::
+
+:::{warning}
+The message _Server not found in Kerberos database_ printed by `ssh -v` indicates no service principal matches the hostname used to connect. Connect using the fully qualified hostname matching the keytab of the server.
+:::
+
+:::{warning}
+Authentication fails when the clock of your computer differs by more than five minutes from the KDC or the server. Enable _Set time and date automatically_ in _System Settings → General → Date & Time_.
+:::
+
+:::{warning}
+On Windows, when you are prompted for a password, verify `klist.exe` of MIT Kerberos for Windows lists a ticket granting ticket `krbtgt/EXAMPLE.COM@EXAMPLE.COM` for your realm. When MIT Kerberos for Windows is installed in a different folder, set the hidden configuration option `ssh.authentication.gssapi.mit.path` to the folder containing `klist.exe` and `kcpytkt.exe`.
+:::
+
+:::{note}
+The `GSSAPIAuthentication` directive in `~/.ssh/config` is not required. The authentication method is always attempted when offered by the server. Change the order in which methods are tried with [`PreferredAuthentications`](../protocols/sftp/index.md#configuration-file) instead. Methods not listed are still tried afterwards.
+:::
+
+## References
+
+- [`GSSAPIAuthentication` in ssh_config](https://man.openbsd.org/ssh_config#GSSAPIAuthentication)
+- [`GSSAPIAuthentication` in sshd_config](https://man.openbsd.org/sshd_config#GSSAPIAuthentication)
+- [RFC 4462: GSS-API Authentication and Key Exchange for SSH](https://www.rfc-editor.org/rfc/rfc4462)
+- [MIT Kerberos: krb5.conf](https://web.mit.edu/kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html)
+- [Java Kerberos Requirements](https://docs.oracle.com/en/java/javase/21/security/kerberos-requirements1.html) for the lookup of the configuration file and the system properties `java.security.krb5.realm` and `java.security.krb5.kdc`.
diff --git a/tutorials/sftp_publickeyauth_pageant.md b/tutorials/sftp_publickeyauth_pageant.md
new file mode 100644
index 00000000..75468ecf
--- /dev/null
+++ b/tutorials/sftp_publickeyauth_pageant.md
@@ -0,0 +1,49 @@
+Configure Public Key Authentication for SFTP using Pageant
+====
+
+> Public-key authentication using _Pageant_ SSH Agent allows you to connect to a remote server without a password. Instead of passwords, you use a pair of keys (private and public) for authentication. The private key is kept secret, while the public key is shared with the server.
+
+:::{important}
+* Cyberduck [9.6](https://cyberduck.io/changelog/) or later required
+* PuTTY/Pageant [0.77](https://www.chiark.greenend.org.uk/~sgtatham/putty/changes.html) or later required
+
+The previous built-in Pageant integration has been removed in Cyberduck 9.6. Refer to [#18479](https://github.com/iterate-ch/cyberduck/issues/18479).
+:::
+
+Refer to [How To Use Pageant to Streamline SSH Key Authentication with PuTTY](https://www.digitalocean.com/community/tutorials/how-to-use-pageant-to-streamline-ssh-key-authentication-with-putty) for general usage of Pageant. Pageant supports writing the `IdentityAgent`-option into an OpenSSH configuration file on startup.
+
+1. Install [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html), which includes _Pageant_ and _PuTTYgen_.
+
+2. Start Pageant with the `--openssh-config` option, e.g. in the shortcut used to launch Pageant at login. Private key files to load can be appended to the command line.
+
+ ```
+ pageant.exe --openssh-config %USERPROFILE%\.ssh\pageant.conf
+ ```
+
+3. Add an `Include` directive at the top of `%USERPROFILE%\.ssh\config` before any `Host` entry to apply it to all hosts.
+
+ ```
+ Include ~/.ssh/pageant.conf
+ ```
+
+4. Open your private key in _PuTTYgen_ and copy the public key shown in _Public key for pasting into OpenSSH authorized_keys file_. Add it to the `authorized_keys` in your `~/.ssh` directory on the server running OpenSSH.
+
+5. Add a new [Bookmark](../cyberduck/bookmarks.md) in Cyberduck. Enter the alias from your OpenSSH configuration or the hostname in _Server_. You do **not** need to set a value for _Password_.
+
+ :::{tip}
+ The server may respond with _[Too many authentication failures](../protocols/sftp/index.md#too-many-authentication-failures)_ when trying to authenticate with all keys loaded in _Pageant_. In the [Bookmark](../cyberduck/bookmarks.md) panel, select the public key corresponding to your private key loaded in _Pageant_ for *SSH Private Key*. The public key must be available as a file, e.g. saved from _PuTTYgen_ to `%USERPROFILE%\.ssh\mykey.pub`.
+
+ Alternatively, add the public key to the OpenSSH configuration file `~/.ssh/config` with the `IdentityFile` directive
+
+ ```
+ # Public Key File used to filter identities from SSH agent
+ IdentityFile ~/.ssh/mykey.pub
+ ```
+ :::
+
+6. Connect to the server. The private key loaded in _Pageant_ is used to authenticate.
+
+## References
+
+* [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html)
+* [How To Use Pageant to Streamline SSH Key Authentication with PuTTY](https://www.digitalocean.com/community/tutorials/how-to-use-pageant-to-streamline-ssh-key-authentication-with-putty)
diff --git a/tutorials/sftp_publickeyauth_pkcs11.md b/tutorials/sftp_publickeyauth_pkcs11.md
new file mode 100644
index 00000000..2794288d
--- /dev/null
+++ b/tutorials/sftp_publickeyauth_pkcs11.md
@@ -0,0 +1,86 @@
+Configure Public Key Authentication for SFTP using a PKCS#11 Smartcard
+====
+
+> Public-key authentication with a smartcard allows you to connect to a remote server without a password. The private key is kept on the card and never leaves it. A _PKCS#11_ module, the native library shipped with the driver of your card, is used to read the public keys from the card and to sign the login with the corresponding private key protected by a PIN. This is the equivalent of `ssh -I /path/to/module.so`.
+
+:::{important}
+* Cyberduck [9.7.0](https://cyberduck.io/changelog/) or later required
+* Mountain Duck [6.0.0](https://mountainduck.io/changelog/) or later required
+:::
+
+:::{note}
+Only keys with a matching certificate on the card are found. Cards holding a key without a certificate, such as a key generated with `pkcs11-tool --keypairgen` only, cannot be used.
+:::
+
+## Setup
+
+:::::{tabs}
+::::{group-tab} macOS
+
+1. Install the _PKCS#11_ module for your card. [OpenSC](https://github.com/OpenSC/OpenSC) supports many cards including _PIV_, _CAC_ and _OpenPGP_ cards.
+ ```
+ brew install opensc
+ ```
+
+ :::{tip}
+ Cyberduck and Mountain Duck already bundle _OpenSC_. Refer to the bundled library by its file name `opensc-pkcs11.so` instead of an absolute path when configuring the module. For a smartcard paired with macOS using `sc_auth pair`, the system module `/usr/lib/ssh-keychain.dylib` can be used instead.
+ :::
+
+2. Verify the module can read the certificates from the card. Insert the card first.
+ ```
+ pkcs11-tool --module /opt/homebrew/lib/opensc-pkcs11.so --list-objects --type cert
+ ```
+
+3. Print the public keys on the card and save them to a file.
+ ```
+ ssh-keygen -D /opt/homebrew/lib/opensc-pkcs11.so > ~/.ssh/smartcard.pub
+ ```
+
+4. Add the public key to the `authorized_keys` in your `~/.ssh` directory on the server running OpenSSH.
+ ```
+ ssh-copy-id -fi ~/.ssh/smartcard.pub user@remotehost
+ ```
+
+5. Verify the setup with OpenSSH before connecting with Cyberduck. You are prompted for the PIN of the card.
+ ```
+ ssh -I /opt/homebrew/lib/opensc-pkcs11.so user@remotehost
+ ```
+
+6. Refer to the module in your OpenSSH configuration file `~/.ssh/config`.
+ ```
+ Host *
+ PKCS11Provider /opt/homebrew/lib/opensc-pkcs11.so
+ ```
+
+ This [configuration](https://docs.cyberduck.io/protocols/sftp/#openssh-configuration-interoperability) directive is supported by Cyberduck and Mountain Duck. You can restrict the setting to a single alias in the configuration file instead of matching it for all connections with `*`. Alternatively set the [hidden configuration option](hidden_properties.md) `ssh.authentication.pkcs11.library` to the path of the module or to `opensc-pkcs11.so` for the bundled version.
+
+7. Add a new [Bookmark](../cyberduck/bookmarks.md) in Cyberduck or Mountain Duck. Enter the alias from your OpenSSH configuration or the hostname in _Server_. You do **not** need to set a value for _Password_ or select a _SSH Private Key_ because the keys are read from the card.
+
+ :::{tip}
+ The server may respond with _[Too many authentication failures](../protocols/sftp/index.md#too-many-authentication-failures)_ when the card holds several keys. Select the public key saved in step 3 for _SSH Private Key_ to only offer the matching identity.
+ :::
+
+8. Connect to the server and enter the PIN of the card when prompted.
+
+::::
+:::::
+
+## Troubleshooting
+
+:::{warning}
+When no key from the card is offered, verify the card holds a certificate for the key with `pkcs11-tool --module --list-objects --type cert`. A key without a certificate on the card is not found.
+:::
+
+:::{warning}
+When the connection continues with a prompt for a password, the module could not be loaded. Verify the path set with `PKCS11Provider` and that the same path works with `ssh -I`.
+:::
+
+:::{note}
+Removing the card while connected fails the session. Reconnect with the card inserted.
+:::
+
+## References
+
+- [OpenSC supported hardware](https://github.com/OpenSC/OpenSC/wiki/Supported-hardware-%28smart-cards-and-USB-tokens%29)
+- [`PKCS11Provider` in ssh_config](https://man.openbsd.org/ssh_config#PKCS11Provider)
+- [Use a FIDO2 Security Key](sftp_publickeyauth_securitykey.md) for authentication with a key in the Secure Enclave or on a hardware token such as a YubiKey.
diff --git a/tutorials/sftp_publickeyauth_securitykey.md b/tutorials/sftp_publickeyauth_securitykey.md
new file mode 100644
index 00000000..8589dca7
--- /dev/null
+++ b/tutorials/sftp_publickeyauth_securitykey.md
@@ -0,0 +1,159 @@
+Configure Public Key Authentication for SFTP using a FIDO2 Security Key
+====
+
+> Public-key authentication with a _FIDO2_ security key allows you to connect to a remote server without a password. The private key never leaves the authenticator, which is either the Secure Enclave of your Mac unlocked with _Touch ID_ or a hardware token such as a _YubiKey_ you touch to confirm. OpenSSH calls these keys `sk-ecdsa-sha2-nistp256@openssh.com` and `sk-ssh-ed25519@openssh.com`.
+
+:::{important}
+* Cyberduck [9.7.0](https://cyberduck.io/changelog/) or later required
+* Mountain Duck [6.0.0](https://mountainduck.io/changelog/) or later required
+:::
+
+The key file in `~/.ssh` holds a reference to the credential on the authenticator but no private key. Signing a login is therefore delegated either to a _security key provider_ library talking to the authenticator or to an [SSH agent](#let-an-ssh-agent-handle-the-security-key) holding the key.
+
+:::{note}
+A security key provider library is configured by default on macOS only, serving keys in the Secure Enclave. On Windows and Linux OpenSSH talks to a token with built-in USB HID support instead of a library, which Cyberduck cannot load. Leave the key to an [SSH agent](#let-an-ssh-agent-handle-the-security-key) there, or set `SecurityKeyProvider` to a middleware library for your token.
+:::
+
+:::{important}
+The server must run _OpenSSH 8.2_ or later. Earlier versions do not know the `sk-*` key types and ignore the entry in `authorized_keys`. Verify the version of the server with `ssh -v user@remotehost` and look for the line `remote software version`.
+:::
+
+## Create a Key in the Secure Enclave unlocked with Touch ID
+
+:::::{tabs}
+::::{group-tab} macOS
+
+1. Create an identity in the Secure Enclave protected with _Touch ID_. The private key is generated on the device and cannot be extracted.
+ ```
+ sc_auth create-ctk-identity -l "MacBook Touch ID SSH" -k p-256-ne -t bio
+ ```
+
+ :::{tip}
+ `-k p-256-ne` creates a non-extractable key on the NIST P-256 curve, the only curve supported by the Secure Enclave. `-t bio` requires _Touch ID_ to use the key.
+ :::
+
+2. Write the key file for the credential. Run the command in `~/.ssh` as the files are written to the current working directory.
+ ```
+ cd ~/.ssh && ssh-keygen -w /usr/lib/ssh-keychain.dylib -K
+ ```
+
+ :::{note}
+ When prompted with `Enter PIN for authenticator:`, press _Enter_ to leave the PIN empty. A key in the Secure Enclave has no PIN and is protected by _Touch ID_ instead. The prompt is shown by OpenSSH for any authenticator.
+ :::
+
+ This writes `id_ecdsa_sk_rk` and `id_ecdsa_sk_rk.pub`. Repeat the command with `-K` whenever you need the files again on another Mac with access to the same identity.
+
+3. Add the public key to the `authorized_keys` in your `~/.ssh` directory on the server running OpenSSH.
+ ```
+ ssh-copy-id -fi ~/.ssh/id_ecdsa_sk_rk.pub user@remotehost
+ ```
+
+4. Verify the setup with OpenSSH before connecting with Cyberduck. Confirm the prompt with _Touch ID_.
+ ```
+ ssh -o SecurityKeyProvider=/usr/lib/ssh-keychain.dylib -i ~/.ssh/id_ecdsa_sk_rk user@remotehost
+ ```
+
+ :::{tip}
+ Set the provider in `~/.ssh/config` to omit the `-o` option and the `-i` option.
+ ```
+ Host remotehost
+ User user
+ IdentityFile ~/.ssh/id_ecdsa_sk_rk
+ SecurityKeyProvider /usr/lib/ssh-keychain.dylib
+ ```
+ Cyberduck and Mountain Duck use `/usr/lib/ssh-keychain.dylib` by default on macOS and do not require this directive.
+ :::
+
+5. In the [Bookmark](../cyberduck/bookmarks.md) or [Connection](../cyberduck/connection.md) window, in _SSH Private Key_ select `id_ecdsa_sk_rk` in your `~/.ssh` directory. You do **not** need to set a value for _Password_.
+
+6. Connect to the server and confirm the prompt with _Touch ID_ to allow the Secure Enclave to sign the login.
+
+::::
+:::::
+
+## Create a Key on a Hardware Token such as YubiKey
+
+:::::{tabs}
+::::{group-tab} macOS
+
+1. Insert the security key and create a credential on the token. Touch the token when it blinks.
+ ```
+ cd ~/.ssh && ssh-keygen -t ed25519-sk -O resident
+ ```
+
+ :::{tip}
+ Use `-t ecdsa-sk` instead for tokens without support for Ed25519 credentials, such as a _YubiKey_ with a firmware version earlier than 5.2.3. Add `-O verify-required` to require the PIN of the token in addition to touching it. The option `-O resident` stores the credential on the token allowing to write the key files again on another machine with `ssh-keygen -K`.
+ :::
+
+ :::{note}
+ `ssh-keygen` talks to the token with the USB HID support built into OpenSSH. No middleware library is required to create the key. Pass `-w ` only to use a middleware library of your own instead.
+ :::
+
+2. Add the public key to the `authorized_keys` in your `~/.ssh` directory on the server running OpenSSH.
+ ```
+ ssh-copy-id -fi ~/.ssh/id_ed25519_sk.pub user@remotehost
+ ```
+
+3. Refer to the middleware library for the token in your OpenSSH configuration file `~/.ssh/config`. The default `/usr/lib/ssh-keychain.dylib` set on macOS serves keys in the Secure Enclave only.
+ ```
+ Host *
+ SecurityKeyProvider /path/to/middleware.so
+ ```
+
+ This [configuration](https://docs.cyberduck.io/protocols/sftp/#openssh-configuration-interoperability) directive is supported by Cyberduck and Mountain Duck. A value beginning with `$` is read from the environment variable of that name. Alternatively set the [hidden configuration option](hidden_properties.md) `ssh.authentication.securitykey.provider` to the path of the library.
+
+ :::{important}
+ The USB HID support built into OpenSSH is not a library and cannot be loaded. Unless the token comes with a middleware library implementing the OpenSSH security key API, leave the security key to an [SSH agent](#let-an-ssh-agent-handle-the-security-key) instead, which works with any token supported by OpenSSH.
+ :::
+
+4. In the [Bookmark](../cyberduck/bookmarks.md) or [Connection](../cyberduck/connection.md) window, in _SSH Private Key_ select `id_ed25519_sk` in your `~/.ssh` directory.
+
+5. Connect to the server and touch the security key when it blinks. Enter the PIN of the token when prompted for a key created with `-O verify-required`.
+
+::::
+:::::
+
+## Let an SSH Agent handle the Security Key
+
+Instead of talking to the authenticator, Cyberduck and Mountain Duck can leave the security key to an SSH agent. The agent prompts for the touch or the PIN and returns the signature.
+
+:::::{tabs}
+::::{group-tab} macOS
+
+1. Add the security key to the SSH agent of OpenSSH. You are asked to confirm with _Touch ID_ or to touch the token.
+ ```
+ ssh-add ~/.ssh/id_ecdsa_sk_rk
+ ```
+
+2. Verify the agent holds the key. The key type is printed as `ECDSA-SK` or `ED25519-SK`.
+ ```
+ ssh-add -l
+ ```
+
+3. Add a new [Bookmark](../cyberduck/bookmarks.md). No _SSH Private Key_ needs to be selected because the key is offered by the agent.
+
+ :::{tip}
+ The server may respond with _[Too many authentication failures](../protocols/sftp/index.md#too-many-authentication-failures)_ when the agent holds many keys. Select the public key `id_ecdsa_sk_rk.pub` for _SSH Private Key_ to only offer the matching identity from the agent.
+ :::
+
+::::
+:::::
+
+Other SSH agents manage keys of their own instead of a credential on a security key, with the approval prompt of the application taking the place of the touch. Refer to the tutorials for the [1Password SSH Agent](sftp_publickeyauth_1password.md), the [Bitwarden SSH Agent](sftp_publickeyauth_bitwarden.md) and [yubikey-agent](sftp_publickeyauth_yubikey.md) for the setup of the agent socket with `IdentityAgent` in `~/.ssh/config`.
+
+## Troubleshooting
+
+:::{warning}
+When the connection fails with the message _No security key provider configured_, no middleware library is set for your platform. A library is configured by default on macOS only. Set `SecurityKeyProvider` in `~/.ssh/config` or add the key to an SSH agent instead. A failure naming the library instead means it could not be loaded, in which case verify the path.
+:::
+
+:::{warning}
+When the server refuses the key without prompting for a touch, the public key is not accepted. Verify the entry in `authorized_keys` and that the server runs _OpenSSH 8.2_ or later.
+:::
+
+## References
+
+- [Cyberduck 9.6.0](https://cyberduck.io/changelog/) or later is required for authentication with a security key without an SSH agent.
+- [OpenSSH 8.2 release notes announcing FIDO/U2F support](https://www.openssh.com/txt/release-8.2)
+- [PROTOCOL.u2f describing the `sk-*` key types](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.u2f)
+- [Yubico Developers: Securing SSH with FIDO2](https://developers.yubico.com/SSH/Securing_SSH_with_FIDO2.html)