-
Notifications
You must be signed in to change notification settings - Fork 15
MFA Authentication Flow
When a TP-Link account has two-factor authentication (2FA/MFA) enabled, the login process requires an additional verification step.
Login Request
│
├── error_code: 0 → Success (no MFA)
│
└── error_code: -20677 → MFA Required
│
├── supportedMFATypes: ["email"]
│ │
│ └── Request email code
│ │
│ └── User enters code
│ │
│ └── checkMFACodeAndLogin → Token
│
└── supportedMFATypes: ["push"]
│
└── Request push notification
│
└── User approves on phone
│
└── checkMFACodeAndLogin → Token
When login returns error code -20677, the response includes:
{
"error_code": -20677,
"result": {
"mfaProcessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"supportedMFATypes": ["email"],
"accountId": "1234567"
}
}Save the mfaProcessId - it's needed for the verification step.
Endpoint: POST {appServerUrl}/api/v2/account/getEmailVC4TerminalMFA
Body:
{
"mfaProcessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"appType": "Kasa_Android_Mix"
}This sends a verification code to the user's registered email address.
Endpoint: POST {appServerUrl}/api/v2/account/getPushVC4TerminalMFA
Body:
{
"mfaProcessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"appType": "Kasa_Android_Mix"
}This sends a push notification to the user's Kasa app on their phone.
Endpoint: POST {appServerUrl}/api/v2/account/checkMFACodeAndLogin
Body (from decompiled CheckMFACodeParams):
{
"appType": "Kasa_Android_Mix",
"code": "123456",
"mfaProcessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"mfaType": "email"
}Successful Response:
Same as a successful login - returns token, refreshToken, accountId, etc.
{
"error_code": 0,
"result": {
"token": "xxxxxxxx-xxxxxxxxxxxxxxxxxxxx",
"refreshToken": "xxxxxxxx-xxxxxxxxxxxxxxxxxxxx",
"accountId": "1234567",
...
}
}For the Python library, MFA support needs a callback mechanism since the verification code must come from the user interactively.
Proposed API:
# Option 1: Callback function
def mfa_callback(mfa_type, email):
code = input(f"Enter the MFA code sent to {email}: ")
return code
device_manager = TPLinkDeviceManager(
username="user@example.com",
password="password",
mfa_callback=mfa_callback
)
# Option 2: Exception-based
try:
device_manager = TPLinkDeviceManager(username="...", password="...")
except TPLinkMFARequiredError as e:
code = input(f"Enter MFA code: ")
device_manager = e.complete_login(code)-
API Interface:
sources/com/tplink/cloud/api/AccountV2Api.java-checkMFACodeAndLogin(),getEmailVC4TerminalMFA() -
Params:
sources/com/tplink/cloud/bean/account/params/CheckMFACodeParams.java -
Login Result:
sources/com/tplink/cloud/bean/account/result/LoginV2Result.java- ContainsmfaProcessId,supportedMFATypes