AlistGo/alist · error

public key refused

Error message

public key refused

What it means

Returned at the end of PublicKeyAuth after none of the SSH public keys stored for the user matches the key presented by the client. The driver fetches all keys via op.GetSSHPublicKeyByUserId and compares the marshaled key bytes; a mismatch (or unparsable stored key) causes the loop to skip the candidate, and the final statement returns 'public key refused'. This is an authentication failure, distinct from the permission check that precedes it.

Source

Thrown at server/sftp.go:130

		return nil, errors.New("user is not allowed to access via SFTP")
	}
	keys, _, err := op.GetSSHPublicKeyByUserId(userObj.ID, 1, -1)
	if err != nil {
		return nil, err
	}
	marshal := string(key.Marshal())
	for _, sk := range keys {
		if marshal != sk.KeyStr {
			pubKey, _, _, _, e := ssh.ParseAuthorizedKey([]byte(sk.KeyStr))
			if e != nil || marshal != string(pubKey.Marshal()) {
				continue
			}
		}
		sk.LastUsedTime = time.Now()
		_ = op.UpdateSSHPublicKey(&sk)
		return nil, nil
	}
	return nil, errors.New("public key refused")
}

func (d *SftpDriver) AuthLogCallback(conn ssh.ConnMetadata, method string, err error) {
	ip := conn.RemoteAddr().String()
	if err == nil {
		utils.Log.Infof("[SFTP] %s(%s) logged in via %s", conn.User(), ip, method)
	} else if method != "none" {
		utils.Log.Infof("[SFTP] %s(%s) tries logging in via %s but with error: %s", conn.User(), ip, method, err)
	}
}

func (d *SftpDriver) GetBanner(_ ssh.ConnMetadata) string {
	return setting.GetStr(conf.Announcement)
}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Add the client's public key (~/.ssh/id_*.pub output) under the user's SSH public keys in the AList admin panel and reconnect.
  2. Confirm the key belongs to the same username being used to connect (keys are scoped per user ID).
  3. Re-copy the stored key exactly (single line, key-type base64-comment) so ssh.ParseAuthorizedKey can parse it and the marshaled form matches.
  4. If the client agent offers many keys, ensure the correct one is offered (ssh -i) so a later refusal is not caused by wrong-key ordering.

Example fix

# before: client key not registered, server logs 'public key refused'
ssh alist@example.com

# after: register the exact public key, then connect
# admin UI -> Users -> SSH Public Keys -> paste contents of:
cat ~/.ssh/id_ed25519.pub
ssh -i ~/.ssh/id_ed25519 alist@example.com
Defensive patterns

Strategy: validation

Validate before calling

# Before connecting, confirm the key you will offer is registered:
ssh-keygen -lf ~/.ssh/id_ed25519.pub   # fingerprint of client key
# compare with the fingerprint shown for the stored key in the AList admin panel

Prevention

When it happens

Trigger: Client offers an SSH key that is not registered for the account; the stored KeyStr is in a different format/comment so string comparison fails AND ssh.ParseAuthorizedKey fails or the re-marshaled bytes differ; all user keys were deleted from the admin panel.

Common situations: New machine / new SSH keypair not added in the AList SSH public keys settings; key was re-saved with a trailing comment or whitespace so neither raw-string nor parsed comparison matches; user uploaded a private key instead of the public key; key registered under a different user account.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/e6aca2f600121c02. Report an issue: GitHub.