Skip to main content
Version: 4.0

Authenticating

The function definition for login() is as follows:

public function login(
string $username,
#[SensitiveParameter] string|PrivateKey|array|Agent ...$args
): bool

login() returns true on success and false on failure. Unlike most methods in phpseclib 4.0, it does not throw on authentication failure. Bad passwords and wrong keys are an expected outcome, not an error. Connection-level errors during login still throw (see Connecting / Failure Modes).

Password

use phpseclib4\Net\SSH2;

$ssh = new SSH2('localhost');
if (!$ssh->login('username', 'password')) {
throw new \Exception('Login failed');
}

If you're absolutely certain that the password / username you've entered are correct it's possible the server isn't using SSH authentication and that what's prompting you for your credentials is the terminal itself. In this scenario you would want to authenticate in the manner demonstrated in the No Authentication example.

Public Key

use phpseclib4\Net\SSH2;
use phpseclib4\Crypt\PublicKeyLoader;

$key = PublicKeyLoader::load(file_get_contents('privatekey'));

$ssh = new SSH2('localhost');
if (!$ssh->login('username', $key)) {
throw new \Exception('Login failed');
}

Public Key Authentication is one of the most secure ways to connect to a server. Even if the server is being "spoofed" or otherwise compromised the worst thing that'll happen is that the public key will be exposed to the attacker. The private key remains private and the hostile actor will be unable to login as you. This is in contrast to password authentication wherein supplying your password to a "spoofed" server means that the attacker could use that same password to login as you to the legit server.

RSA, DSA, ECDSA and EdDSA (Ed25519) keys are supported, in a myriad of different formats. Click the links for a more detailed breakdown.

PublicKeyLoader::load() auto-detects the format (OpenSSH, PuTTY, PKCS#8, raw PEM, etc.) and the key type, so you don't need to call format-specific loaders.

Password Protected Public Key

use phpseclib4\Net\SSH2;
use phpseclib4\Crypt\PublicKeyLoader;

$key = PublicKeyLoader::load(file_get_contents('privatekey'), 'password');

$ssh = new SSH2('localhost');
if (!$ssh->login('username', $key)) {
throw new \Exception('Login failed');
}

Keyboard-Interactive

use phpseclib4\Net\SSH2;

$ssh = new SSH2('localhost', 22);
$result = $ssh->login('username', [
['Password' => 'pass1'],
['Verification code' => 'code1']
]);

if (!$result) {
throw new \Exception('Login failed');
}

When doing password authentication phpseclib tries keyboard-interactive if password auth fails. Only after both fail does $ssh->login() return false. The reason for this is that a lot of systems just prompt for the password via keyboard-interactive. So if your server only has one keyboard-interactive prompt using the password authentication method would be sufficient.

The method utilized in this example is mainly useful when you have multiple keyboard-interactive prompts and need to disambiguate between them. This example utilizes prompt-based disambiguation. One can also distinguish between the various keyboard-interactive prompts via order-based disambiguation. This method is demonstrated in the Multi-Factor example. What'll happen in that example is that password auth will be tried, will presumably fail and then when keyboard-interactive succeeds all subsequent authentications will utilize keyboard-interactive (unless you're trying to auth with a public key).

Multi Factor

use phpseclib4\Net\SSH2;

$ssh = new SSH2('localhost');
if (!$ssh->login('username', 'pass1', 'code1')) {
throw new \Exception('Login failed');
}
// this does the same thing as the above
//if (!$ssh->login($username, 'pass1') && !$ssh->login('username', 'code1')) {
// throw new \Exception('Login failed');
//}

Since login() is variadic, you can pass as many credentials as your server demands. phpseclib feeds them to whatever auth methods the server requests next, in order.

SSH Agent

use phpseclib4\Net\SSH2;
use phpseclib4\System\SSH\Agent;

$agent = new Agent;

$ssh = new SSH2('localhost');
if (!$ssh->login('username', $agent)) {
throw new \Exception('Login failed');
}

See ssh-agent for more information.

By default, the socket path is determined by looking at $_SERVER['SSH_AUTH_SOCK'] and (failing the former) $_ENV['SSH_AUTH_SOCK'].

If necessary, the socket path can be passed to the Agent constructor. eg. if, on the CLI, echo $SSH_AUTH_SOCK returns /run/user/1000/keyring/ssh you can do $agent = new Agent('/run/user/1000/keyring/ssh').

Agent Forwarding

Let's say you wanted to connect to another SSH server (hereinafter referred to as server B) from the server that you're already SSH'd into (hereinafter referred to as server A). Let's also say that you use the same private key to access both servers. Normally this would mean that you'd need to have your private key on server A to connect to server B from server A but with Agent Forwarding that ceases to be the case. Instead you can do something like this:

$agent->startSSHForwarding($ssh);
echo $ssh->exec('ssh user@domain.tld "ls -latr"');

No Authentication

use phpseclib4\Net\SSH2;

$ssh = new SSH2('localhost');
$ssh->login('username');
$ssh->read('User Name:');
$ssh->write("username\n");
$ssh->read('Password:');
$ssh->write("password\n");

$ssh->setTimeout(1);
$ssh->read();
$ssh->write("ls -la\n");
echo $ssh->read();

I would provide a better example but have never had direct access to an SSH server that did authentication in this manner nor do I know how to set one up.