Implementing new iCloud authentication process
steilerDev opened this issue ยท 7 comments
Describe the ultimate goal you want to achieve
Based on recent network captures, it seems that Apple has changed it's web authentication API flow utilising a new password exchange protocol that does not exchange the plain text password. Based on the current investigations, it seems it is using a variation of the SRP protocol.
How do you think the feature should be implemented
Ongoing reverse engineering efforts:
- POST to
https://idmsa.apple.com/appleauth/auth/signin/init
with the following body:
{
"a": 512 (random?) bytes - base64 encoded,
"accountName": AppleID email,
"protocols": [
"s2k",
"s2k_fo"
]
}
{
"iteration" : 20403,
"salt" : 16 (random?) bytes - base64 encoded,
"protocol" : "s2k",
"b" : 256 (random?) bytes - base64 encoded,
"c" : "x-xxx-xxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxx:RNO" // where x matches [a-z0-9] Looks like some ID - changes slightly on every request
}
- Following this, the iCloud Web app responds to
https://idmsa.apple.com/appleauth/auth/signin/complete?isRememberMeEnabled=true
with the following payload:
{
"accountName": AppleID email,
"rememberMe": false,
"trustTokens": [
Trust Token string, or empty
],
"m1": 32 bytes - base64 encoded,
"c": appears to be the same string as 'c' in previous response,
"m2": 32 bytes - base64 encoded
}
- This endpoint (like the previous
https://idmsa.apple.com/appleauth/auth/signin
) returns either 406 or 200 depending on MFA status
From this my current efforts indicate the following:
a
is the SRP public client ephemeral, derived from the account name and passwordb
is iCloud's public server ephemeralm1
/m2
are the session secrets derived from the challengec
seems to be related to hashcashgen - it's part of the icloud.js attributions, luckily it seems we don't need to care and only hand it back
I'm currently trying to verify these assumption - however I am already seeing issues with this:
- I'm not taking
iterations
into account (afaik there is no modern hashing algorithm that works on iterations?) - I'm ignoring
protocol: s2k
- this might refer to OpenPGP's string-2-key specifiers, which would also allow iterations and salting, which would add another level of complication to the reverse engineering efforts
Given all of this complexity, I was trying to follow the application logic of the iCloud Web App, unfortunately the code is obfuscated in a way that I cannot understand what's going on. You can find some references to srpData
in there, as well as the crypto library and imports of md5
and sha
. The Nt
class is exposing functions that are most likely interesting for us (e.g. _getSRPValues(e)
) - maybe someone with more JS debugging experience could follow this angle.
Implications
The currently implemented authentication flow (that is just sending the plain password) still works - I have no idea if Apple plans to kill off this behaviour / when they will do this. This item nevertheless takes highest priority, because it has the potential to break all iCloud API interactions.
It seems like this protoocol isn't anything new, rather a port of the existing protocol used by Apple devices since 2SV was introduced (i.e. around iOS 9)? to the web, the good thing being there already being documentation for that version (called Grandslam or GSA):
https://github.com/MathewYaldo/Apple-GSA-Protocol
https://github.com/ionescu007/Blackwood-4NT/tree/main
(afaik there is no modern hashing algorithm that works on iterations?)
I hacked on the existing js-srp
package to get it working with the variant Apple uses.
npm i @foxt/js-srp
I left some code samples at https://github.com/foxt/js-srp-gsa
You are a maniac @foxt ! Thank you for your help on this ๐๐ป
Quickly tested it and works like a charm!
This issue should be resolved with version v1.3.0-beta.2, please confirm.
This issue was resolved with version v1.3.0.