Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Apple 2FA login by checking for actual phoneNumber id #125

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions endpoint/register/pypush_gsa_icloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import base64
import locale
import logging
import re
from datetime import datetime
import srp._pysrp as srp
from cryptography.hazmat.primitives import padding
Expand Down Expand Up @@ -221,11 +222,6 @@ def sms_second_factor(dsid, idms_token):
identity_token = base64.b64encode(
(dsid + ":" + idms_token).encode()).decode()

# TODO: Actually do this request to get user prompt data
# a = requests.get("https://gsa.apple.com/auth", verify=False)
# This request isn't strictly necessary though,
# and most accounts should have their id 1 SMS, if not contribute ;)

headers = {
"User-Agent": "Xcode",
"Accept-Language": "en-us",
Expand All @@ -237,19 +233,24 @@ def sms_second_factor(dsid, idms_token):

headers.update(generate_anisette_headers())

# TODO: Actually get the correct id, probably in the above GET
body = {"phoneNumber": {"id": 1}, "mode": "sms"}
# Extract the "boot_args" from the auth page to get the id of the trusted phone number
pattern = r'<script type="application/json" class="boot_args">\s*(.*?)\s*</script>'
auth = requests.get("https://gsa.apple.com/auth", headers=headers, verify=False)
match = re.search(pattern, auth.text, re.DOTALL)
boot_args = json.loads(match.group(1).strip())

body = {"phoneNumber": {"id": boot_args["direct"]["phoneNumberVerification"]["trustedPhoneNumber"]["id"]}, "mode": "sms"}

# This will send the 2FA code to the user's phone over SMS
# We don't care about the response, it's just some HTML with a form for entering the code
# Easier to just use a text prompt
t = requests.put(
Copy link

@zerog2k zerog2k Sep 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FDHoho007 curious how this is functional without making the put request here? (I.e. is this intentionally commented out?)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see your comment about getting 2 requests. I got only one request when leaving this uncommented.
Otherwise, I don't see how else you would send the body you constructed with the correct 2fa phoneNumber id without this call.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah thats the funny thing. It seems calling https://gsa.apple.com/auth to get the phoneNumber id is already sufficient to request a 2FA code to your primary trusted device.
So in my case calling https://gsa.apple.com/auth replaced the need for https://gsa.apple.com/auth/verify/phone/. But as mentioned above I'm not certain, that this applies to all users and situations. Thats why explicitly left the code in there.
I'm currently waiting for some kind of suggestions or guidance which approach to choose here, since I am not at all familiar with the Apple APIs and just started using this project.

"https://gsa.apple.com/auth/verify/phone/",
json=body,
headers=headers,
verify=False,
timeout=5
)
#t = requests.put(
# "https://gsa.apple.com/auth/verify/phone/",
# json=body,
# headers=headers,
# verify=False,
# timeout=5
#)
# Prompt for the 2FA code. It's just a string like '123456', no dashes or spaces
code = input("Enter SMS 2FA code: ")

Expand Down