Proposal Details

Background

In the current x/crypto/ssh package, authentication methods are static: the client attempts none first and then iterates through the methods specified in ClientConfig.Auth.

While this works for most cases, it has limitations for advanced use cases:

  • Dynamic authentication decisions are not possible. For example, selecting an authentication method based on metadata returned by the server, or reacting to partial successes.
  • Authentication interruption: there's no clean way to abort the authentication process based on runtime context or policy.
  • Limited access to negotiation data: ConnMetadata and NegotiatedAlgorithms are only accessible after authentication completes, not during the process.

Proposal

Add a new optional callback field to ClientConfig:

    // AuthCallback is an optional hook invoked before each authentication
    // attempt. The callback can inspect the connection metadata, negotiated
    // algorithms, and the authentication methods that are supported by the
    // server, have already succeeded (in case of partial success), or previously
    // failed.
    //
    // Return values:
    //
    // - non-nil error: the authentication process stops immediately.
    // - non-nil AuthMethod and nil error: the returned AuthMethod will be
    //   attempted next, instead of the methods defined in [ClientConfig.Auth].
    // - nil [AuthMethod] and nil error: the methods defined in
    //   [ClientConfig.Auth] will be attempted.
    AuthCallback func(conn ConnMetadata, algorithms NegotiatedAlgorithms,
        supportedAuthMethods, succeededAuthMethods, failedAuthMethods []string) (AuthMethod, error)

The callback is invoked after the initial none authentication, once the server’s supported methods are known and it is invoked before each subsequent authentication attempt.

Return values:

  • A non-nil AuthMethod: will be attempted immediately.
  • A non-nil error: aborts the authentication process.
  • Both nil: proceed with the normal authentication flow.

If AuthCallback is not set, the behavior is unchanged and fully backward-compatible

@golang/proposal-review

Comment From: gopherbot

Change https://go.dev/cl/717140 mentions this issue: ssh: add AuthCallback to ClientConfig