Menu

Importing TOTP from Bitwarden JSON should allow generating TOTP codes

2022-07-01
2022-07-03
  • Carey Bishop

    Carey Bishop - 2022-07-01

    Hi there

    I've been trying to import some Bitwarden JSON containing TOTP information into KeePass, and I noticed that it appears to just create a custom field called TOTP, instead of importing the TOTP information into the separate fields that KeePass expects. As such, it's not possible to generate TOTP codes from the imported entries.

    I've had a look at the code and I've come up with a simple patch to the ImportLogin method in BitwardenJson112.cs. The new code checks to see if the TOTP data being imported is an otpauth:// URL, and if it is, it uses the ImportOtpAuth method instead to ensure that it gets imported correctly.
    If the TOTP field does not look like an otpauth:// URL, the old code path is followed to allow importing information in any other format (although all the Bitwarden JSON examples I've seen seem to expect an otpauth:// URL in this field).

    Hopefully you can include this patch (or a similar fix) in a future release.

    Thanks

    private static void ImportLogin(JsonObject jo, PwEntry pe, PwDatabase pd) {
    
        ImportString(jo, "username", pe, PwDefs.UserNameField, pd);
        ImportString(jo, "password", pe, PwDefs.PasswordField, pd);
    
        // START OF PATCH
        string totpURL = jo.GetValue<string>("totp");
        if (totpURL != null && totpURL.StartsWith("otpauth:"))
        {
            // Import URL into multiple fields so that TOTP codes can be generated
            EntryUtil.ImportOtpAuth(pe, totpURL, pd);
        }
        else
        {
            // Existing behaviour
            ImportString(jo, "totp", pe, "TOTP", pd);
            ProtectedString ps = pe.Strings.Get("TOTP");
            if(ps != null) pe.Strings.Set("TOTP", ps.WithProtection(true));
        }
        // END OF PATCH
    
        JsonObject[] vUris = jo.GetValueArray<JsonObject>("uris");
        if(vUris != null)
        {
            int iUri = 1;
            foreach(JsonObject joUri in vUris)
            {
                if(joUri == null) { Debug.Assert(false); continue; }
    
                string str = joUri.GetValue<string>("uri");
                if(!string.IsNullOrEmpty(str))
                {
                    ImportUtil.AppendToField(pe, ((iUri == 1) ?
                        PwDefs.UrlField : ("URL " + iUri.ToString())),
                        str, pd);
                    ++iUri;
                }
            }
        }
    }
    
     
  • ReadyPlayerOne

    ReadyPlayerOne - 2022-07-02

    I would say first you should contact Bitwarden about what your asking as well.
    https://bitwarden.com/help/authenticator-keys/

     
    • Carey Bishop

      Carey Bishop - 2022-07-03

      No, I don't think that's helpful.

      I already have the information in the Bitwarden JSON file format, the trouble is that KeePass doesn't import this into the right fields (TimeOtp-*). The patch I provided above can be applied to KeePass to resolve the issue.

      You can find information about the Bitwarden JSON file format including a link to a sample file at https://bitwarden.com/help/condition-bitwarden-import/#condition-a-json

      The totp field in that file already contains the information that I'm interested in.

       
  • Dominik Reichl

    Dominik Reichl - 2022-07-03

    Thanks for the hint! I've now added such an automatic conversion (similar to what you suggested).

    Here's the latest development snapshot for testing:
    https://keepass.info/filepool/KeePass_220703.zip

    Best regards,
    Dominik

     
    • Carey Bishop

      Carey Bishop - 2022-07-03

      Thanks @dreichl, that snapshot build works the way I was expecting.

       

Log in to post a comment.