Skip to content

[BUG] aiograpi backend submits raw TOTP seed instead of generating 6-digit verification code #45

@SkyPlay-Code

Description

@SkyPlay-Code

Describe the bug

When using the aiograpi backend with a configured Two-Factor Authentication (2FA) seed, insto fails to log in and throws an aiograpi: UnknownError: Please check the security code and try again (Response 400 Bad Request) error.

This happens because the aiograpi backend passes the raw, static base32 TOTP secret key directly as the verification_code parameter to client.login() instead of generating the temporary 6-digit numerical code first.

Where the bug occurs

In insto/backends/aiograpi.py inside the _ensure_logged_in method:

try:
    await self._client.login(
        self._username,
        self._password,
        verification_code=self._totp_seed or "", # <--- Submits raw seed directly
    )

Steps to Reproduce

  1. Configure insto to use the aiograpi backend with your Instagram credentials and a valid aiograpi.totp_seed.
  2. Launch insto and attempt any target command (e.g., /target <username>).
  3. Observe the login failure in insto.log matching:
    aiograpi.exceptions.UnknownError: Please check the security code and try again.
    insto.exceptions.Transient: aiograpi: UnknownError: Please check the security code and try again.
    

Expected Behavior

The backend should use the totp_seed to generate the correct, current 6-digit dynamic verification code on-the-fly and submit that numerical code to the login() function.

Actual Behavior

The backend submits the raw alphanumeric secret string (e.g., GA2V...) to Instagram's legacy two_factor_login endpoint, which is instantly rejected as an invalid verification code.

Proposed Fix

Importing the logic to dynamically generate the 6-digit code using aiograpi's built-in totp_generate_code helper resolves the issue. To account for potential synchronous or asynchronous implementations of the generator, the following safe wrapper can be used in insto/backends/aiograpi.py:

        try:
            code = ""
            if self._totp_seed:
                import inspect
                res = self._client.totp_generate_code(self._totp_seed)
                if inspect.iscoroutine(res):
                    code = await res
                else:
                    code = res

            await self._client.login(
                self._username,
                self._password,
                verification_code=code,
            )

Testing this locally successfully generates the dynamic code, completes the login handshake, and persists the aiograpi.session.json file.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions