Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Authy to 1Password

Moving Authy to 1Password

1Password 5.3 for OSX, 5.2 for iOS, and 4.1.0.538 for Windows support OTP. I've been using Authy for a while now, but the fact is, I haven't really been using 2FA for some time. As mentioned by 1Password in a recent blog post, having the OTP generator and password on the same device is very much not 2FA. It's just an expiring OTP, which can help, but let's not kid ourselves too much.

With that out of the way. One of the things that was interesting to me was moving my OTP out of Authy and into 1Password. I like the control I get with 1Password, but I didn't want to have to reset all my OTP right away, that would suck. So, I got to dissecting the Authy Chrome App to see what I could do.

Run the Authy Chrome app and make sure it's unlocked.

Now, enable Developer mode in Chrome. We'll need this to inspect the background application that stores all the OTP information. It'll also tell you the Application ID for Authy (gaedmjdfmmahhbjefcbgaolhhanlaolb on my system) which is useful if you want to dive into the actual guts (which I did, a lot.)

Once Developer mode is enabled, click "main.html" next to "Inspect views:". We are going to inject the code below into main.html in order to get a pretty page we can use. On the console window that shows, copy/paste the javascript below and hit enter.

Viola! You can now use this page to move your OTP credentials to 1Password.

window.open('data:text/html;charset=utf-8,' + encodeURIComponent('<!DOCTYPE html>'+ '<html lang="en">'+ '<head><title>Embedded Window</title></head>'+ '<body>' +
  jQuery(require("models/apps/app_manager").get().getDecryptedApps()).map(function (ndx, elem) {
    if (!elem.decryptedSeed) { return }
    var name = elem.name || elem.originalName
    return "<h1><img src='" +
      require('models/assets/asset_manager').get().assetAccounts[elem.accountType].menuItemUrl + 
      "'>" + name + "</h1><h2>" + elem.decryptedSeed + "</h2>" +
      "<img src='https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/" + encodeURI(name) + "%3Fsecret%3D" + elem.decryptedSeed.toLowerCase() + "'/>"
}).toArray().join("<br>")
  + '</body>'+ '</html>' ) );

Minified (for copy/pasta)

window.open("data:text/html;charset=utf-8,"+encodeURIComponent('<!DOCTYPE html><html lang="en"><head><title>Embedded Window</title></head><body>'+jQuery(require("models/apps/app_manager").get().getDecryptedApps()).map(function(e,t){if(t.decryptedSeed){var r=t.name||t.originalName;return"<h1><img src='"+require("models/assets/asset_manager").get().assetAccounts[t.accountType].menuItemUrl+"'>"+r+"</h1><h2>"+t.decryptedSeed+"</h2><img src='https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/"+encodeURI(r)+"%3Fsecret%3D"+t.decryptedSeed.toLowerCase()+"'/>"}}).toArray().join("<br>")+"</body></html>"));
@eightam

This comment has been minimized.

Copy link

eightam commented Sep 15, 2016

Hi, thanks so much for this script - but it doesn't seem to work anymore.
It's just opening a window with the following address:
data:text/html;charset=utf-8,<!DOCTYPE%20html><html%20lang%3D"en"><head><title>Embedded%20Window<%2Ftitle><%2Fhead><body><%2Fbody><%2Fhtml>

@piscis

This comment has been minimized.

Copy link

piscis commented Mar 12, 2017

same here but I came up with the following to manualy generate the OTP Links in the developer console. For there its just copy past into 1Password.

appManager.getModel().forEach(function(i){
  if(i.markedForDeletion === false){
    console.log('otpauth://totp/'+i.name+'?secret='+i.decryptedSeed+'&issuer='+i.accountType);
  }
}); 
@akurtz

This comment has been minimized.

Copy link

akurtz commented May 25, 2017

Nice and simple, @piscis, thanks! I just made a small adjustment to encode the name so you can always right-click the line and Copy Link Address to get the whole URI. (Otherwise it will break at problematic characters like spaces.)

appManager.getModel().forEach(function(i){
  if(i.markedForDeletion === false){
    console.log('otpauth://totp/'+encodeURIComponent(i.name)+'?secret='+i.decryptedSeed+'&issuer='+i.accountType);
  }
});
@delicopsch56

This comment has been minimized.

Copy link

delicopsch56 commented Oct 18, 2017

The modified code provided by akurtz works really well. The only issue I have is that it doesn't retrieve the AUTHY generated tokens themselves, used by the likes of Coinbase, Gemini, and Tether. I think that these are proprietary, and in the case of problematic sites such as Coinbase it doesn't seem possible to retrieve your seed after setting it if you didn't save it when turning it on. I'll try to look for a solution but this really isn't an area where I have a great deal of technical expertise, so if anyone else has a solution, please share!

@givemelove

This comment has been minimized.

Copy link

givemelove commented Jan 8, 2018

Thank you @akurtz, I can confirm that the snippet still works really well.

Just a reminder for those that just install the Authy chrome extension for that purpose, make sure to unlock your codes by entering your passcode at least once. This is required for the decryptedSeed variable to be available. If you don't, you will see and undefined secret value.

@Nomy

This comment has been minimized.

Copy link

Nomy commented Jan 21, 2018

Just confirming that the code from @akurtz still works.
I just used https://stefansundin.github.io/2fa-qr/ to generate QR code by pasting the URI in the otpauth field.

@RVWoiDiEasuZr6z3RvotiXdri4ye7EMhQtpeTVc

This comment has been minimized.

Copy link

RVWoiDiEasuZr6z3RvotiXdri4ye7EMhQtpeTVc commented Jul 24, 2018

I've had some success with @akurtz code. but the 2fa im trying to migrate is an authy app one, so it shows up when you do appManager.getAuthyApps() but i cant get the decrypted seed

@JazzTech

This comment has been minimized.

Copy link

JazzTech commented Feb 14, 2019

I'm trying to use the code mentioned above, but I think that Chrome has changed their Developer interface. When I go to Menu >> More tools >> Extensions, I see a bunch of blocks listing my installed Chrome extensions. I figured out that I need to click on the Inspect views background page to get to the code associated to the Authy extension. However, I'm lost after that.

Could someone help with the last few details to install the @akurtz code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.