---
title: Password authentication
layout: page
parent: Tutorial
nav_order: 2
---
# {{ page.title }}
In this chapter, we will authenticate to the SSH server using a password.
{: .note }
Public key authentication, [which is described in the next chapter][3-pubkey-auth], is considered more secure than password authentication and should be preferred whenever possible, especially if you cannot securely verify the public key of the server that you are connecting to.
[3-pubkey-auth]: {% link tutorial/3-pubkey-auth.md %}
## Handle client events in a task
In the previous chapter, we spawned a task to poll the [`ClientFuture`][client-fut] and we waited for [`ClientEvent`-s][client-event] from the [`ClientReceiver`][client-rx] on the main task. However, from now on, we will need the main task to invoke operations on the [`Client`][client], so we start by moving the event handling from the main task to another spawned task:
[client-fut]: https://docs.rs/makiko/latest/makiko/struct.ClientFuture.html
[client-event]: https://docs.rs/makiko/latest/makiko/enum.ClientEvent.html
[client-rx]: https://docs.rs/makiko/latest/makiko/struct.ClientReceiver.html
[client]: https://docs.rs/makiko/latest/makiko/struct.Client.html
```rust
// Do not handle the client events on the main task
/*
loop {
// Wait for the next event.
let event = client_rx.recv().await
.expect("Error while receiving client event");
...
}
*/
// Instead, spawn another Tokio task to handle the client events.
tokio::task::spawn(async move {
loop {
// Wait for the next event.
let event = client_rx.recv().await
.expect("Error while receiving client event");
... // Handle the events as before
}
});
```
## Authenticate
Back on the main task, we can now call the [`Client::auth_password()`][client-auth-password] method to attempt password authentication using username "alice" and password "alicealice":
[client-auth-password]: https://docs.rs/makiko/latest/makiko/struct.Client.html#method.auth_password
```rust
// Try to authenticate using a password.
let auth_res = client.auth_password("alice".into(), "alicealice".into()).await
.expect("Error when trying to authenticate");
```
The method returns an [`AuthPasswordResult`][auth-password-result], which has these variants:
- `Success` means that we are now authenticated.
- `Failure` means that the server has not accepted the authentication and provided an [`AuthFailure`][auth-failure] with details.
- `ChangePassword` means that the password was correct, but we need to change the password to a new one. The SSH specification provides a mechanism for changing the password, but I have not found any SSH server or client that implements this feature, so Makiko does not support it either. This means that we don't need to handle the `ChangePassword` variant in practice, so we treat it as an error.
[auth-password-result]: https://docs.rs/makiko/latest/makiko/enum.AuthPasswordResult.html
[auth-failure]: https://docs.rs/makiko/latest/makiko/struct.AuthFailure.html
In this tutorial, we can simply print a message on success and panic on failure:
```rust
// Deal with all possible outcomes of password authentication.
match auth_res {
makiko::AuthPasswordResult::Success => {
println!("We have successfully authenticated using a password");
},
makiko::AuthPasswordResult::ChangePassword(prompt) => {
panic!("The server asks us to change password: {:?}", prompt);
},
makiko::AuthPasswordResult::Failure(failure) => {
panic!("The server rejected authentication: {:?}", failure);
}
}
```
---
Full code for this tutorial can be found in [`examples/tutorial_2.rs`][tutorial-2]. The program will print a message if the authentication was successful, or an error if it failed. If you don't use the [example server for this tutorial][example-server], you may need to change the code to use a different username and password.
[tutorial-2]: https://github.com/honzasp/makiko/blob/master/examples/tutorial_2.rs
[example-server]: {% link tutorial/1-connect.md %}#example-server
{% include tutorial_next.html link="tutorial/3-pubkey-auth.md" title="Public key authentication" %}