跳转至

Android v391.0.0.42.82 登录流程

igapi-rs 的 Android 平台支持 多版本并存:v428(默认,5 步 Bloks 流程)与 v391(7 步 CAA 流程)。 本文档说明 v391 的 7 步 CAA 登录流程、版本选择方式,以及必须知悉的 attestation 现实边界

完整端点覆盖状态见 Android v391.0.0.42.82 能力索引

⚠️ 现实边界:登录成功依赖硬件 attestation

v391 登录第 6 步 send_login_request 需在 X-IG-Attest-Params 头携带 Android Keystore 硬件密钥证明(key_hash / signed_nonce)。真机是硬件绑定的 AndroidKeyStore / StrongBox 签名。

本 SDK 默认使用纯软件 EC 签名器SoftwareAttestationProvider),它保证协议结构合法、 流程能推进到 send_login_request,但会被登录风控拒绝(服务端返回 SLR error)。因此:

  • ✅ 可用:完整 7 步协议、请求头/体与真机抓包对齐、可跑到 send_login。
  • ❌ 不保证:端到端登录成功——需通过 with_attestation_provider 注入 真机/Frida 硬件签名的 provider。

完整生命周期

v391 支持 init → 登录 → 2FA 验证 全流程:

  • 登录:下方 7 步 CAA 流程。
  • 2FA 验证:登录返回需二次验证时,login()TwoFactorRequired 并暂存 two_step_verification_context;随后调用 complete_two_factor(code) 完成 two_step_verification.entrypointverify_code.async。判定依据真机抓包: 成功响应含 logged_in_user 且由 IG-Set-Authorization 下发 Bearer 令牌落地会话; 验证码错误时 HTTP 200 但无 logged_in_user(服务端提示 “check the security code and try again”), 此时保留上下文可用新验证码重试。
  • init 收尾:登录成功后自动 best-effort 拉取一批预热端点(aed/current、loom/fetch_config、 get_account_family、ndx_ig_steps、fetch_onetap、process_contact_point_signals 等),失败不阻断登录。

two_step_verification_context 的提取依据 two_step_verification.entrypoint 响应中 文档记录的 Bloks map.Make 结构(键数组含字段名、值数组按位对齐)解析,非猜测; 但触发 2FA 的 send_login 响应本身未单独留档,且因 attestation 阻断,端到端仍需注入 真机硬件签名后才能验证。

7 步时序

来源:一手抓包 docs/api/android/v391.0.0.42.82/(Redmi Note 9 / M2007J22C)。

# 端点 作用
1 POST /launcher/mobileconfig/ 无会话配置同步(signed_body=SIGNATURE.<明文JSON>,非签名)
2 POST /attestation/create_android_keystore/ 提交 key_hash → 取 challenge_nonce
3 POST /bloks/async_action/...login.process_client_data_and_redirect/ 客户端数据处理与重定向
4 POST /bloks/async_action/...phone.number.prefill.async.controller/ 手机号/用户名预填
5 POST /bloks/async_action/...caa.login.oauth.token.fetch.async/ OAuth Token 获取
6 POST /bloks/async_action/...caa.login.async.send_login_request/ 提交加密密码 + X-IG-Attest-Params
7 POST /zr/dual_tokens/ Zero-Rating 双 Token(仅登录成功后有意义)

设备标识映射(v391)

头 / 字段 形态 说明
X-IG-Android-ID / body device_id(android) android-<16hex> 由系统 ANDROID_ID 派生
X-IG-Device-ID / app_scoped_device_id / custom_device_id 带连字符 UUID guid 形态
X-IG-Family-Device-ID / family_device_id 带连字符 UUID mobileconfig 中为大写

授权新账号 / 注册链路边界

v391 原始文档还覆盖授权新账号与注册后 onboarding 链路。Rust core 已提供版本 API、 流程对象和稳定摘要响应:

  • client.reg()fxcal/get_sso_accountsspc_create_profilecaa.reg.usernamecaa.reg.ac_optincaa.reg.create.account,并提供 RegistrationFlow 串联上下文。
  • client.attestation()create_android_keystorecreate_android_playintegrity challenge 请求;真实硬件签名或 Google integrity_token 仍由调用方/provider 提供。
  • client.onboarding():动态 onboarding、contact point prefill、头像 rupload、 change_profile_picturefxcal_linkfxcal_link_log,并提供 OnboardingFlow
  • client.home():feed timeline、Direct inbox、users info、notifications badge 等高价值接口 提供 HomeResponse 摘要模型。

响应模型只提升稳定摘要字段,完整原始响应仍保留在 raw 中:注册使用 RegistrationResponse,onboarding 使用 OnboardingResponse,home/profile/feed 使用 HomeResponse。注册响应中的 reg_contextauth_tokenevent_request_idwaterfall_id 等服务端/Bloks 不透明上下文仍由 flow 保存并传递;SDK 不伪造缺失上下文。 错误语义采用现有 InstagramError 映射,注册 flow 额外记录 RegistrationFlowFailure 用于表达用户名不可用、challenge、rate limit、attestation 缺失等失败上下文。

Python 暴露部分稳定 typed wrapper,包括 SSO 查询、用户名校验、dynamic steps、contact prefill、 feed timeline、Direct inbox 和 users info。CLI 只暴露 provider 本地预检与 home smoke,不提供完整 注册/onboarding 命令。原因是完整注册仍依赖真实硬件 attestation / Play Integrity provider、上传状态 和服务端不透明上下文;过早包装成命令会制造看似可用、实际无法稳定完成注册的接口。

使用方式

Rust

use igapi_core::android::v391::Client;
use igapi_core::ClientConfig;

let client = Client::new(ClientConfig::default())?;

// 默认软件 attestation:能跑完 7 步,但 send_login 预期返回 SLR error。
match client.login("username", "password").await {
    Ok(()) => println!("登录成功"),
    Err(e) => println!("登录未成功(默认软件 attestation 预期被拒):{e}"),
}

版本目录规范:v391 独有流程必须位于 src/core/src/android/versions/v391/,Rust 入口使用 igapi_core::android::v391::Client

注入硬件 attestation

实现 AndroidAttestationProvider 接口,包裹真机/Frida 硬件签名,然后注入。 旧实现只需要 key_hash() + sign(challenge_nonce);推荐新实现覆盖 try_key_hash()try_sign(challenge_nonce)play_integrity_token(challenge_nonce), 用于返回 unavailablechallenge_expiredsigning_failedtoken_missingdevice_unsupported 等明确错误语义。

use std::sync::Arc;

let client = Client::new(ClientConfig::default())?
    .with_attestation_provider(Arc::new(MyHardwareAttestation::new()));

SDK 只负责请求 Instagram challenge、调用外部 provider、组装 keystore header 或接收 Play Integrity token;不会伪造 Android Keystore 硬件证明,也不会伪造 Google Play Integrity token。默认 SoftwareAttestationProvider 对 Play Integrity 会返回 token_missing

可用 CLI 做本地 provider 预检:

ig-cli --android-version 391 v391-provider-check

Python

import igapi

# 版本命名空间(推荐):固定使用 v391 / v428 版本边界
client = igapi.android.v391.Client()        # 7 步 CAA
client = igapi.android.v428.Client()        # 5 步 Bloks(= 默认)

try:
    await client.login("username", "password")
except Exception:
    # 触发 2FA 时:提交验证码完成登录
    await client.complete_two_factor("123456")

注意:Python 模块名不能以数字开头,所以规范使用 igapi.android.v391,不使用 igapi.android.391

CLI

# 默认 v428;用 --android-version 391 切到 7 步 CAA 流程
ig-cli --android-version 391 login --username <u> --password <p>
# 触发 2FA 时提供验证码(不加则交互式从标准输入读取)
ig-cli --android-version 391 login -u <u> -p <p> --two-factor-code 123456
# 使用已登录 Android AccountInfo 做 home smoke
ig-cli --android-version 391 v391-home-smoke -a "<account>" --target feed