authy

package module
v0.0.0-...-c3c8072 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 18, 2023 License: MIT Imports: 27 Imported by: 0

README

authy

GoDoc

This is a Go library that allows you to access your Authy TOTP tokens.

It was created to facilitate exports of your TOTP database, because Authy do not provide any way to access or port your TOTP tokens to another client.

It also somewhat documents Authy's protocol/encryption, since public materials on that are somewhat scarce.

Please be careful. You can get your Authy account suspended very easily by using this package. It does not hide itself or mimic the official clients.

Applications

authy-export

This program will enrol itself as an additional device on your Authy account and export all of your TOTP tokens in Key URI Format.

It is also able to save the TOTP database in a JSON file encrypted with your Authy backup password, which can be used for backup purposes, and to read it back in order to decrypt it.

Installation

Pre-built binaries are available from the releases page. (Windows binaries have been removed because of continual false positive virus complaints, sorry).

Alternatively, it can be compiled from source, which requires Go 1.12 or newer:

go install github.com/alexzorin/authy/...@latest

authy To use it:

  1. Run authy-export
  2. The program will prompt you for your phone number country code (e.g. 1 for United States) and your phone number. This is the number that you used to register your Authy account originally.
  3. If the program identifies an existing Authy account, it will send a device registration request using the push method. This will send a push notification to your existing Authy apps (be it on Android, iOS, Desktop or Chrome), and you will need to respond that from your other app(s).
  4. If the device registration is successful, the program will save its authentication credential (a random value) to $HOME/authy-go.json for further uses. Make sure to delete this file and de-register the device after you're finished.
  5. If the program is able to fetch your TOTP encrypted database, it will prompt you for your Authy backup password. This is required to decrypt the TOTP secrets for the next step.
  6. The program will dump all of your TOTP tokens in URI format, which you can use to import to other applications.
  7. Alternatively, you can save the TOTP encrypted database to a file with the --save option, and reload it later with the --load option in order to decrypt it and dump the tokens.

If you notice any missing TOTP tokens, please try toggling "Authenticator Backups" in your Authy settings, to force your backup to be resynchronized.

How do you then import it into another app?

Up to you, depends on the app. If the app uses QR scanning, you can try stick all the dumped URIs into a file (tokens) and then scan each QR code from your terminal, e.g.:

#!/usr/bin/env bash
cat tokens | while IFS= read -r line; do
  clear
  echo -n "$line" | qrencode -t UTF8
  read -p $"Press any key to continue" key < /dev/tty
done

"My Twitch (or other site) token is different to the one I see in the Authy app?"

This is expected, depending on what the site is.

In Authy, there are two types of secrets:

  • Tokens: You sign up to a website, the website generates a TOTP secret, and you scan it via a QR code (in any app, not necessarily Authy). You can export that secret to other TOTP apps and the code will match.
  • Apps: The website has exported their TOTP flow to Authy's proprietary service, which requires you to use the Authy app. For sites like Twitch, Authy assigns a unique TOTP secret for every device you use the Authy app on. Each device will produce different 7-digit codes, but they will all work. If you deregister any device from your Authy account, that device's TOTP secrets will be revoked and its 7-digit codes will no longer work.

Twitch (and a handful of other sites) are the latter: Authy Apps.

Now, authy-export registers itself as a device on your Authy account. Per the explanation above, that means it is assigned a unique TOTP secret for sites like Twitch, which means it will generate different 7-digit codes to your primary Authy device. These codes will work as long as you don't deregister the authy-export device from your Authy account.

This is unfortunate, but the fact is: you cannot fully delete your Authy account if you want to keep using TOTP-based authentication with Twitch. If you do, all of the TOTP secrets will be revoked, and you will locked out of Twitch. It happened to me, and Twitch support chose to not help me out ^_^.

Batch support

When environment variable named AUTHY_EXPORT_PASSWORD exists, authy-export does not ask for a password and uses the variable instead. Use with care!

LICENSE

See LICENSE

All product names, logos, and brands are property of their respective owners. All company, product and service names used in this website are for identification purposes only. Use of these names, logos, and brands does not imply endorsement

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthenticatorApp

type AuthenticatorApp struct {
	ID string `json:"_id"`

	// Display name of the token
	Name string `json:"name"`

	SerialID int `json:"serial_id"`

	Version int `json:"version"`

	AssetsGroup string `json:"assets_group"`

	AuthyID uint64 `json:"authy_id"`

	// The Device Secret Seed (hex-encoded). It is the TOTP
	// secret that protects the authenticated endpoints.
	SecretSeed string `json:"secret_seed"`

	// How many digits in the TOTP
	Digits int `json:"digits"`
}

AuthenticatorApp is embedded in AuthenticatorAppsResponse

func (AuthenticatorApp) Token

func (a AuthenticatorApp) Token() (string, error)

Token produces the base32-encoded TOTP token backing this app. It has a period of 10.

type AuthenticatorAppsResponse

type AuthenticatorAppsResponse struct {
	// Display to user
	Message string `json:"message"`

	// Active encrypted authenticator apps
	AuthenticatorApps []AuthenticatorApp `json:"apps"`

	// Recently deleted, but not removed encrypted authenticator apps
	Deleted []AuthenticatorApp `json:"deleted"`

	// Whether this request succeeded
	Success bool `json:"success"`
}

AuthenticatorAppsResponse is the response from: https://api.authy.com/json/users/{User_ID}/devices/{Device_ID}/apps/sync

type AuthenticatorToken

type AuthenticatorToken struct {
	// In the Authy app, this is the visual icon type of this token
	AccountType string `json:"account_type"`

	// How many digits this TOTP token is
	Digits int `json:"digits"`

	// The encrypted TOTP seed
	EncryptedSeed string `json:"encrypted_seed"`

	// User-nominated name for the token
	Name string `json:"name"`

	// Purpose not known
	OriginalName string `json:"original_name"`

	// Purpose not known
	PasswordTimestamp uint64 `json:"password_timestamp"`

	// The salt used to encrypt the EncryptedSeed
	Salt string `json:"salt"`

	// The ID of this token
	UniqueID string `json:"unique_id"`
}

AuthenticatorToken is embedded in AuthenticatorTokensResponse

func (AuthenticatorToken) Decrypt

func (t AuthenticatorToken) Decrypt(passphrase string) (string, error)

Decrypt returns the base32-encoded seed for this TOTP token, decrypted by passphrase.

func (AuthenticatorToken) Description

func (t AuthenticatorToken) Description() string

Description returns OriginalName if not empty, otherwise Name, otherwise `Token-{UniqueID}`.

type AuthenticatorTokensResponse

type AuthenticatorTokensResponse struct {
	// Display to user
	Message string `json:"message"`

	// Active encrypted authenticator token
	AuthenticatorTokens []AuthenticatorToken `json:"authenticator_tokens"`

	// Recently deleted, but not removed encrypted authenticator tokens
	Deleted []AuthenticatorToken `json:"deleted"`

	// Whether this request succeeded
	Success bool `json:"success"`
}

AuthenticatorTokensResponse is the response from: https://api.authy.com/json/users/{User_ID}/authenticator_tokens?api_key={API_Key}&otp1={OTP_1}&otp2={OTP_2}&otp3={OTP_3}&device_id={Device_ID

type Client

type Client struct {
	UserAgent string
	APIKey    string
	// contains filtered or unexported fields
}

Client provides API interaction with the Authy API. See NewClient()

func NewClient

func NewClient() (Client, error)

NewClient creates a new Authy API client.

func (Client) CheckDeviceRegistration

func (c Client) CheckDeviceRegistration(ctx context.Context, userID uint64, requestID string) (DeviceRegistrationStatus, error)

CheckDeviceRegistration fetches the status of the device registration request (requestID) for the nominated Authy User ID (userID). This should be polled with a timeout.

func (Client) CompleteDeviceRegistration

func (c Client) CompleteDeviceRegistration(ctx context.Context, userID uint64, pin string) (CompleteDeviceRegistrationResponse, error)

CompleteDeviceRegistration completes the device registration process for the nominated Authy User ID (userID) and PIN (from the DeviceRegistrationStatus)

func (Client) QueryAuthenticatorApps

func (c Client) QueryAuthenticatorApps(ctx context.Context, userID uint64, deviceID uint64, deviceSeed string) (AuthenticatorAppsResponse, error)

QueryAuthenticatorApps fetches the encrypted Authy App tokens for userID, authenticating using the deviceSeed (hex-encoded).

func (Client) QueryAuthenticatorTokens

func (c Client) QueryAuthenticatorTokens(ctx context.Context, userID uint64, deviceID uint64, deviceSeed string) (AuthenticatorTokensResponse, error)

QueryAuthenticatorTokens fetches the encrypted TOTP tokens for userID, authenticating using the deviceSeed (hex-encoded).

func (Client) QueryDevicePrivateKey

func (c Client) QueryDevicePrivateKey(ctx context.Context, deviceID uint64, deviceSeed string) (DevicePrivateKeyResponse, error)

QueryDevicePrivateKey fetches the PKCS#1 private key for the nominated device ID, using the known device secret TOTP seed from CompleteDeviceRegistrationResponse.

func (Client) QueryUser

func (c Client) QueryUser(ctx context.Context, countryCallingCode int, phone string) (UserStatus, error)

QueryUser fetches the status of an Authy user account.

func (Client) RequestDeviceRegistration

func (c Client) RequestDeviceRegistration(ctx context.Context, userID uint64, via ViaMethod) (StartDeviceRegistrationResponse, error)

RequestDeviceRegistration begins a new device registration for an Authy User account, via the nominated mechanism.

type CompleteDeviceRegistrationResponse

type CompleteDeviceRegistrationResponse struct {
	Device struct {
		// The Device ID
		ID uint64 `json:"id"`

		// The Device Secret Seed (hex-encoded, 32-bytes). It is the TOTP
		// secret that protects the authenticated endpoints.
		SecretSeed string `json:"secret_seed"`

		// Purpose not known.
		APIKey string `json:"api_key"`

		// Purpose not known, but probably whether this device is being
		// re-installed.
		Reinstall bool `json:"reinstall"`
	} `json:"device"`

	// The Authy User ID
	AuthyID uint64 `json:"authy_id"`
}

CompleteDeviceRegistrationResponse is the response from: https://api.authy.com/json/users/16480/devices/registration/complete

type DevicePrivateKeyResponse

type DevicePrivateKeyResponse struct {
	Message    string `json:"message"`
	PrivateKey string `json:"private_key"`
	Success    bool   `json:"success"`
}

DevicePrivateKeyResponse is the response from https://api.authy.com/json/devices/{Device_ID}/rsa_key?api_key={API_Key}&&otp1={OTP_1}&otp2={OTP_2}&otp3={OTP_3}&device_id={DEVICE_ID}

func (DevicePrivateKeyResponse) AsPrivateKey

func (r DevicePrivateKeyResponse) AsPrivateKey() (*rsa.PrivateKey, error)

AsPrivateKey parses the PEM private key in PrivateKey

type DeviceRegistrationStatus

type DeviceRegistrationStatus struct {
	// pending, accepted, rejected, ??
	Status string `json:"status"`

	// PIN is required to complete the device registration
	PIN string `json:"pin"`

	// Whether this status request was successful, distinct to whether the
	// registration process is complete.
	Success bool `json:"success"`
}

DeviceRegistrationStatus is the response from: https://api.authy.com/json/users/{User_ID}/devices/registration/{Request_ID}/status?api_key={API_Key}&locale=en-GB&signature=b54ff1b646b207ff2da50ecb9a0bc2c770a1357b04278c8dd402f835db2824f4

type StartDeviceRegistrationResponse

type StartDeviceRegistrationResponse struct {
	// Message to display to the user upon receiving this response
	Message string `json:"message"`

	// The Request ID is used to poll the status of the device registration process
	RequestID string `json:"request_id"`

	// Purpose unclear
	ApprovalPIN int `json:"approval_pin"`

	// The ViaMethod
	Provider string `json:"provider"`

	// Whether the device registration request was accepted.
	// This is distinct to the device registration being successful/complete.
	Success bool `json:"success"`
}

StartDeviceRegistrationResponse is the response from: https://api.authy.com/json/users/{User_ID}/devices/registration/start

type UserStatus

type UserStatus struct {
	// Presumably, force device validation over HTTP rather than
	// allowing a phone call or SMS. ("Over the top").
	ForceOTT bool `json:"force_ott"`

	// How many devices are registered to this Authy user
	DevicesCount int `json:"devices_count"`

	// Authy User ID
	AuthyID uint64 `json:"authy_id"`

	// Presumably some kind of opaque status string
	Message string

	// Whether this request was successful
	Success bool
}

UserStatus is the response from: https://api.authy.com/json/users/{Country}-{Phone}/status

func (UserStatus) IsActiveUser

func (us UserStatus) IsActiveUser() bool

IsActiveUser reports whether this is an an active, registered Authy user.

type ViaMethod

type ViaMethod string

ViaMethod represents the methods available for new device registration

const (
	// ViaMethodPush to recieve an Authy app-based push notification
	ViaMethodPush ViaMethod = "push"
	// ViaMethodCall to receive a phone call
	ViaMethodCall ViaMethod = "call"
	// ViaMethodSMS to receive an SMS message
	ViaMethodSMS ViaMethod = "sms"
)

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL