alexzorin / authy

Go library and program to access your Authy TOTP secrets.
MIT License
800 stars 58 forks source link

Get Issuer from authy and replace if necessary #6

Open craftbyte opened 4 years ago

craftbyte commented 4 years ago

Hi, A lot of my TOTP secrets are just my email as the username which causes confusion when importing. Would it be possible to get the issuer from Authy and prepend it to the username and add to the issuer parameter?

alexzorin commented 4 years ago

Would it be possible to get the issuer from Authy and prepend it to the username and add to the issuer parameter?

Sure - if it is actually present in the data.

I don't have access to an Authy account anymore, so I will need some help. If you can run the exporter with this environment variable set, it will show the raw responses from the Authy servers:

AUTHY_DEBUG=1

If you see the TOTP issuer is embedded somewhere in the responses, we can use it.

craftbyte commented 4 years ago

This is the newer format for the tokens endpoint:


    {
      "account_type": "authenticator",
      "digits": 6,
      "encrypted_seed": "seed",
      "issuer": "Cloudflare",
      "logo": "cloudflare",
      "name": "email1234@email.com",
      "original_name": "Cloudflare:email1234@email.com",
      "password_timestamp": 1589225507,
      "salt": "salt",
      "unique_id": "1586798286"
    }

It seems like all are now set to authenticator type. Here is some code I tried playing around with:

func (t AuthenticatorToken) IssuerName() string {
    if t.Issuer != "" {
        return t.Issuer
    }
    if t.OriginalName != "" {
        return strings.SplitN(t.OriginalName, ":", 2)[0]
    }
    if t.Logo != "" {
        return t.Logo
    }
    if strings.Contains(t.Name, ":") {
        return strings.SplitN(t.Name, ":", 2)[0]
    }
    if !strings.Contains(t.AccountType, "authenticator") {
        return t.AccountType
    }
    return ""
}

That also requires updating the AuthenticationToken struct with the new fields as well as updating the t.Description() method to exclude the issuer since otherwise we will duplicate it.

For the URL generation we will also have to fix encoding spaces, since Go by default replaces them with +'s.

        params.Set("issuer", tok.IssuerName())
        u := url.URL{
            Scheme:   "otpauth",
            Host:     "totp",
            Path:     tok.Description(),
            RawQuery: strings.ReplaceAll(params.Encode(), "+", "%20"),
        }
alexzorin commented 4 years ago

Wow, thanks, seems like you have done all the legwork already.

I think for the sake of conformity with https://github.com/google/google-authenticator/wiki/Key-Uri-Format#issuer , it might be worth also changing Description() to return issuer:name, if both issuer and name are defined.

For the URL generation we will also have to fix encoding spaces, since Go by default replaces them with +'s.

Nice catch, Go's choice to encode spaces here as + here is not something I'd noticed before.

Do you want to submit a PR (only if you want to)? Otherwise I'll try integrate these changes when I find the time.

craftbyte commented 4 years ago

I have some more stuff to work out then I can file a PR. I noticed a lot of the names are still including the : if they are older and the logo was not set so I would need to write some logic for that first.