Sample code for 30+ languages & platforms
DataFlex

SSH Auth Failure Reason (AuthenticatePwPk)

See more SSH Examples

Demonstrates how to determine why authentication failed when a server requires both a password and a private key. If AuthenticatePwPk fails, GetLastJsonData returns diagnostic JSON whose authResult and authFailReason members reveal which factor was at fault.

Background: With multi-factor SSH, a plain failure is ambiguous — the key could be wrong, the password could be wrong, or both. The diagnostic JSON resolves that: it reports Key is incorrect when the key fails, or a partialAuthResult showing the key succeeded before Password is incorrect. Note the ordering consequence: if the key is rejected, authentication never reaches the password check, so you cannot yet know whether the password is also wrong. Passwords and passphrases are never included in this JSON, so it is safe to log.

Chilkat DataFlex Downloads

DataFlex
Use ChilkatAx-win32.pkg

Procedure Test
    Boolean iSuccess
    Variant vKey
    Handle hoKey
    String sPrivKeyText
    Handle hoSsh
    Integer iPort
    String sPassword
    Variant vJson
    Handle hoJson
    String sTemp1
    Boolean bTemp1

    Move False To iSuccess

    //  This example requires the Chilkat API to have been previously unlocked.
    //  See Global Unlock Sample for sample code.

    //  Demonstrates how to determine why authentication failed when a server requires BOTH a
    //  password and a private key.  Was the private key wrong, or the password?

    //  Load the private key used for authentication.
    Get Create (RefClass(cComChilkatSshKey)) To hoKey
    If (Not(IsComObjectCreated(hoKey))) Begin
        Send CreateComObject of hoKey
    End

    //  The key password is not hard-coded in a real application; obtain it from a secure source.
    Set ComPassword Of hoKey To "myKeyPassword"

    Get ComLoadText Of hoKey "qa_data/my_private_key_file" To sPrivKeyText
    Get ComLastMethodSuccess Of hoKey To bTemp1
    If (bTemp1 = False) Begin
        Get ComLastErrorText Of hoKey To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComFromOpenSshPrivateKey Of hoKey sPrivKeyText To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoKey To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get Create (RefClass(cComChilkatSsh)) To hoSsh
    If (Not(IsComObjectCreated(hoSsh))) Begin
        Send CreateComObject of hoSsh
    End
    Move 22 To iPort
    Get ComConnect Of hoSsh "ssh.example.com" iPort To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  Normally you would not hard-code the password in source.  You should instead obtain it
    //  from an interactive prompt, environment variable, or a secrets vault.
    Move "mySshPassword" To sPassword

    //  Authenticate using both a password and a private key.
    Get pvComObject of hoKey to vKey
    Get ComAuthenticatePwPk Of hoSsh "mySshLogin" sPassword vKey To iSuccess
    If (iSuccess) Begin
        Showln "Authentication is successful!"
        Procedure_Return
    End

    //  Authentication failed.  The diagnostic JSON explains which factor was at fault.
    Get Create (RefClass(cComChilkatJsonObject)) To hoJson
    If (Not(IsComObjectCreated(hoJson))) Begin
        Send CreateComObject of hoJson
    End
    Get pvComObject of hoJson to vJson
    Send ComGetLastJsonData To hoSsh vJson
    Set ComEmitCompact Of hoJson To False

    //  If the key is correct but the password is wrong:
    //  {
    //    "public_key_type": "rsa",
    //    "partialAuthResult": "publickey success. continue to authenticate with password...",
    //    "authResult": "failed",
    //    "authFailReason": "Password is incorrect"
    //  }
    //  
    //  If the key is incorrect.  Whether the password is also wrong is unknown, because
    //  authentication never got far enough to check it:
    //  {
    //    "public_key_type": "rsa",
    //    "authResult": "failed",
    //    "authFailReason": "Key is incorrect"
    //  }

    Get ComStringOf Of hoJson "authResult" To sTemp1
    Showln "authResult: " sTemp1
    Get ComStringOf Of hoJson "authFailReason" To sTemp1
    Showln "authFailReason: " sTemp1


End_Procedure