failed to authenticate SSH session
Opened this issue · 19 comments
I am trying to push to a github repo using the ssh remote but I am getting an error
failed to authenticate SSH session: ; class=Ssh (23)
the code
fn push(repo_location: &str, origin: &str) {
let repo = Repository::open(repo_location).unwrap();
let mut origin = repo.find_remote(&origin).unwrap();
let branch = repo.find_branch(&"main", BranchType::Local).unwrap();
let branch_ref = branch.into_reference();
let branch_ref_name = branch_ref.name().unwrap();
repo.set_head(branch_ref_name).unwrap();
let mut remote_callbacks = git2::RemoteCallbacks::new();
remote_callbacks.credentials(|_url, _username_from_url, _allowed_types| {
match git2::Cred::ssh_key(
_username_from_url.unwrap(),
// Some(std::path::Path::new("<home>/.ssh/github/id_rsa.pub")),
None,
std::path::Path::new("<home>/.ssh/github/id_rsa"),
None,
) {
Ok(cred) => {
println!("credential creation success");
Ok(cred)
}
Err(e) => {
println!("credential creation Failed: {:#?}", e);
Err(e)
}
}
});
let mut push_options = git2::PushOptions::new();
let mut_push_options = push_options.remote_callbacks(remote_callbacks);
match origin.push(&[branch_ref_name], Some(mut_push_options)) {
Ok(_) => {
println!("push-pushed to remote")
}
Err(e) => {
println!("push-failed to push to remote: {}", e)
}
};
}
and I am getting this output
and I am able to read the key file
can anyone help?
if I also add the public key it's an infinite loop not stopping and re-trying
@vlad-anger I saw you in a libgit2 PR. Can you help? or tag someone who can?
Can you help?
@harilet Yes
- Your code works. I've tested (with ssh auth, all good)
- Problem you have is related to ssh agent. You need to ensure you have proper one running before invoke program. I would recommend you to check
general info + agent discussion
Run agent windows/mac
so even though git push origin main works for me and I am passing the key in the following code and not using the ssh_key_from_agent still need to use ssh agent?
git2::Cred::ssh_key(
_username_from_url.unwrap(),
// Some(std::path::Path::new("<home>/.ssh/github/id_rsa.pub")),
None,
std::path::Path::new("<home>/.ssh/github/id_rsa"),
None,
)
I can push with killed ssh-agent. Cred callback with priv. key seems to be sufficient (which intuitively makes sense). But i'm not that knowledgeable & sure, It's libgit2 under hood.
So because it works for me with priv. key & without ssh agent, could you recheck your key is fine & you have added it to git remote you are pushing? (So it's not auth issue)
my id_rsa is a publickey?
You can name files how you want, but most likely It's private, public should be id_rsa.pub
You can verify it's private by file start: -----BEGIN OPENSSH PRIVATE KEY-----
Btw do you have chance to test on linux machine | in vm, just to cut area of issue?
my id_rsa starts with -----BEGIN OPENSSH PRIVATE KEY-----
I am using windows11
I am using windows11
I'm not sure if issue is related to libgit2 + windows, or still tricky thing with your keys
But i can't help much unless you can test it in linux VM for ex., so we can know for sure
I think I'm having similar issue. So at first I setup creds like this:
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(|url, username_from_url, allowed_types| {
println!("Connecting to: {url}");
if allowed_types.is_ssh_key() {
return Cred::ssh_key_from_agent(username_from_url.unwrap_or("git"));
}
Err(git2::Error::from_str("No valid credentials available"))
});It worked fine on macOS but failed on Windows.
It just goes into infinite loop and calls callbacks.credentials over and over again and never finishes.
Then I tried to manually get the key like this:
let key = Cred::ssh_key(
"git",
Some(&public_path()),
&private_path(),
Some("PASSWORD"),
)?;On macOS it works if password is correct. If the password is wrong it goes in the same infinite loop.
On Windows it never works.
It is obviously failing and trying to get the key again but my main question is where can I get error messages from these fails? Why does it tries to get the key over and over again instead of just failing with error message?
when I don't use the public key I get failed to authenticate SSH session: ; class=Ssh (23)
when I do use it it goes into a infinite loop and I usually just kill it
in some link @vlad-anger gave, there ssh agent was being used, so I tried this
remote_callbacks.credentials(|_url, _username_from_url, _allowed_types| {
git2::Cred::ssh_key_from_agent(_username_from_url.unwrap())
});
and it works fine
git2::Cred::ssh_key_from_agent(_username_from_url.unwrap()) works on Windows for you?
On my system it returns Ok but still goes into infinite loop of calling remote_callbacks.credentials
Yes, worked in windows for me
code:
fn push(repo_location: &str, origin: &str) {
let repo = Repository::open(repo_location).unwrap();
let mut origin = repo.find_remote(&origin).unwrap();
let branch = repo.find_branch(&"main", BranchType::Local).unwrap();
let branch_ref = branch.into_reference();
let branch_ref_name = branch_ref.name().unwrap();
repo.set_head(branch_ref_name).unwrap();
let mut remote_callbacks = git2::RemoteCallbacks::new();
remote_callbacks.credentials(|_url, _username_from_url, _allowed_types| {
git2::Cred::ssh_key_from_agent(_username_from_url.unwrap())
});
let mut push_options = git2::PushOptions::new();
let mut_push_options = push_options.remote_callbacks(remote_callbacks);
match origin.push(&[branch_ref_name], Some(mut_push_options)) {
Ok(_) => {
println!("pushed to remote")
}
Err(e) => {
println!("failed to push to remote: {}", e)
}
};
}
Output:
Where can I get the error messages when it goes in the infinite loop to understand what goes wrong in my case?
Error message
code:
remote_callbacks.credentials(|_url, _username_from_url, _allowed_types| {
git2::Cred::ssh_key(
_username_from_url.unwrap(),
None,
std::path::Path::new(&format!("{}/.ssh/github/id_rsa",home)),
None,
)
});
Loop
code:
remote_callbacks.credentials(|_url, _username_from_url, _allowed_types| {
println!("Connecting to: {_url}");
git2::Cred::ssh_key(
_username_from_url.unwrap(),
Some(std::path::Path::new(&format!("{}/.ssh/github/id_rsa.pub",home))),
std::path::Path::new(&format!("{}/.ssh/github/id_rsa",home)),
None,
)
});
output:
I get error message too if I remove public key and infinite loop with it.
But still why does it get into infinite loop? Where is the error message from that?
I don't see an error for the infinite loop, can I see it if I open and repack git2::Cred::ssh_key?
I ran into the same issue. The loop does not seem to be infinite though, it terminates with an error after some time.
Debugging this (without the public key path set, i.e. not the case with the loop) I found out that the problem is that on Windows by default in libssh2 it goes through the "wincng" backend where it attempts to read the key file as rsa or dsa (in _libssh2_wincng_load_private, essentially looking for the BEGIN RSA PRIVATE KEY or BEGIN DSA PRIVATE KEY headers in the file through _libssh2_pem_parse) which both failed for me because my key is an ecdsa key (BEGIN OPENSSH PRIVATE KEY header).
I worked around this by enabling the openssl-on-win32 feature for libssh2-sys in my Cargo.toml:
libssh2-sys = { version = "*", features = ["openssl-on-win32"] }
I also linked openssl statically by setting the OPENSSL_STATIC env var and installing openssl through vcpkg for the x64-windows-static triplet and pointing OPENSSL_DIR to the vcpkg installed/x64-windows-static directory. Although this should also work with dynamic linking, you just need to make sure the dll can be found at runtime.
Hi!! I don't know if this is helpful or not, but I had the same problem with ssh_key_from_agent failing to authenticate or being stuck in a loop on Windows 11. My problem was that, even though I had OpenSSH client installed as the ssh-agent , the service itself was not enabled at all.
I fixed it with these steps:
-
Enable the SSH agent service in PowerShell:
Set-Service -Name ssh-agent -StartupType Automatic -
Start the service:
Start-Service ssh-agent -
Add my SSH key:
ssh-add <full_path_to_your_key> -
Verify it's working:
ssh-add -l
Here's my Rust code:
fn main() {
let into = PathBuf::from_str("C:\\Users\\yago\\Desktop\\PrivateRepo").unwrap();
let ssh_clone_url = "git@github.com:Stiff-Rock/JavaFx.git";
let mut callbacks = git2::RemoteCallbacks::new();
callbacks.credentials(|_url, username, _allowed_types| {
let username = username.unwrap_or("git");
println!("Auth callback with user {}", username);
git2::Cred::ssh_key_from_agent(username)
});
let mut fetch_options = git2::FetchOptions::new();
fetch_options.download_tags(git2::AutotagOption::All);
fetch_options.remote_callbacks(callbacks);
let mut repo_builder = git2::build::RepoBuilder::new();
repo_builder.fetch_options(fetch_options);
let res = repo_builder.clone(ssh_clone_url, &into);
match res {
Ok(_) => println!("Successfully cloned repository"),
Err(error) => eprintln!("Error cloning repository: {}", error),
}
}For my use case it's not an ideal solution, since I'll need to find a way to enable the OpenSSH service automatically if i want my app to work out of the box (as far as i know, i could be wrong) but at least now I got it working.
Edit: Unfortunately, I haven't been able to make it work is using Cred::ssh_key, only with Cred::ssh_key_from_agent
Edit: I found a solution for Cred::ssh_key(username, None, &ssh_private_key, None), I had to convert the ssh key to PEM format in PowerShell with ssh-keygen -p -m PEM -f <path_to_ssh_key> and it started working for me.





