Skip to content

Commit 589fe77

Browse files
authored
Merge pull request #178 from malmeloo/feat/docs
Feat/docs
2 parents 8692ecc + 2997757 commit 589fe77

File tree

9 files changed

+441
-7
lines changed

9 files changed

+441
-7
lines changed

docs/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
"sphinx.ext.autodoc",
2525
"sphinx.ext.inheritance_diagram",
2626
"autoapi.extension",
27+
"sphinx_togglebutton",
28+
"sphinx_design",
2729
]
2830

2931
templates_path = ["_templates"]

docs/getstarted/00-install.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Installation
2+
3+
FindMy.py is available in the standard PyPi repositories. You can install it using the following command:
4+
5+
```bash
6+
pip install -U findmy
7+
```
8+
9+
We highly recommend using a [virtual environment](https://docs.python.org/3/library/venv.html) for your project
10+
if you want to use FindMy.py. This reduces the chance of dependency conflicts.

docs/getstarted/01-account.md

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,122 @@
11
# Logging in
22

3-
Some useful features of this library require an active login session with Apple in order to work correctly.
3+
Most useful features of this library require an active login session with Apple in order to work correctly.
44
The reason for this is that the remote endpoints require authentication to actually retrieve data.
55
This page will guide you through the steps needed to log into an Apple account using FindMy.py.
66

7+
## Step 0: Account Requirements
78

9+
FindMy.py requires an **active** Apple Account which has had a device attached to it **at least once**.
10+
It is OK if there are currently no devices signed into the account, as long as a device has signed into
11+
it at least once in the past. Note that this does not have to be a _real_ device: a hackintosh using e.g.
12+
[Docker-OSX](https://github.com/sickcodes/Docker-OSX) may also work for you if the VM is configured correctly.
13+
We do not and will not provide support regarding setting this up.
14+
15+
Additionally, if you want to track your AirTags, iDevices or other FindMy-compatible 3rd party devices,
16+
the account used for FindMy.py does _not_ have to be the same one as the one that the devices are attached to.
17+
Given the right decryption keys, any Apple account can query the location history of any FindMy device.
18+
However, if you want to track such an official device, you currently must have access to a machine that is
19+
running a compatible version of MacOS in order to extract the decryption keys (see later sections).
20+
21+
## Step 1: Creating an AppleAccount instance
22+
23+
The first time we want to sign in, we must manually construct an instance of the [AppleAccount](#findmy.AppleAccount)
24+
class. Creating such a class requires specifying an [Anisette](../technical/15-Anisette.md) provider. Anisette
25+
data is usually generated on-device, and identifies our virtual device when we make a request to Apple's servers.
26+
27+
There are two different Anisette providers included in FindMy.py: [LocalAnisetteProvider](#findmy.LocalAnisetteProvider)
28+
and [RemoteAnisetteProvider](#findmy.RemoteAnisetteProvider). The local provider is much easier to use,
29+
so we will be utilizing it in this example.
30+
31+
```python
32+
from findmy import AppleAccount, LocalAnisetteProvider
33+
34+
ani = LocalAnisetteProvider(libs_path="ani_libs.bin")
35+
account = AppleAccount(ani)
36+
```
37+
38+
Note the `libs_path` argument: the local Anisette provider needs to use some proprietary libraries
39+
from Apple, which will be stored in this file. They will be automatically downloaded if the file is missing.
40+
While the argument is technically optional, it is highly recommended to provide it; otherwise, the library
41+
will need to re-download the bundle every time. The size of the bundle is approximately 2,1 MB.
42+
43+
## Step 2: Logging in
44+
45+
Logging into an Apple Account is an interactive process: depending on the circumstances, 2FA may or may
46+
not be required, and there are multiple different methods to perform 2FA authentication. FindMy.py supports
47+
both SMS and Trusted Device challenges to pass the 2FA check, but you must handle the sign-in flow manually in your application.
48+
49+
```{attention}
50+
FindMy.py currently does not support passkey authentication: [#159](https://github.com/malmeloo/FindMy.py/issues/159).
51+
If you use a passkey to secure your Apple Account, you must disable it to use FindMy.py. This is because enabling
52+
passkeys for your account will disable other 2FA mechanisms.
53+
```
54+
55+
To start the authentication process, provide your email and password as follows:
56+
57+
```python
58+
state = account.login(email, password)
59+
```
60+
61+
The `state` variable will now contain a [LoginState](#findmy.LoginState). If `value == LoginState.LOGGED_IN`, you're
62+
good! Continue to the next step. If `value == LoginState.REQUIRE_2FA`, we need to pass a 2FA challenge first.
63+
Read on to learn how to do this.
64+
65+
In order to pass the 2FA challenge, we first need to find out which challenges Apple provides to us. We can use either
66+
one of these challenges to continue the login flow.
67+
68+
```python
69+
from findmy import LoginState, TrustedDeviceSecondFactorMethod, SmsSecondFactorMethod
70+
71+
if state == LoginState.REQUIRE_2FA: # Account requires 2FA
72+
methods = account.get_2fa_methods()
73+
74+
for i, method in enumerate(methods):
75+
if isinstance(method, TrustedDeviceSecondFactorMethod):
76+
print(f"{i} - Trusted Device")
77+
elif isinstance(method, SmsSecondFactorMethod):
78+
print(f"{i} - SMS ({method.phone_number})")
79+
80+
# example output:
81+
# 0 - Trusted Device
82+
# 1 - SMS (+31 •• ••••••55)
83+
# 2 - SMS (+31 •• ••••••32)
84+
```
85+
86+
Depending on your account configuration, you will either get more or fewer 2FA challenge options.
87+
In order to pass one of these challenges, we will first call its `request()` method to request a code
88+
(on a Trusted Device or via SMS), and then use the `submit()` method to submit the code and pass the challenge.
89+
90+
```python
91+
ind = int(input("Method? > "))
92+
93+
method = methods[ind]
94+
method.request()
95+
code = input("Code? > ")
96+
97+
method.submit(code)
98+
```
99+
100+
If all went well, you should now be logged in!
101+
102+
## Step 3: Saving / restoring the session
103+
104+
Before we continue to fetching device locations, I first want to talk about properly closing and restoring sessions.
105+
Apple Account sessions are precious, and you shall not create more of them than necessary. Each time we go through the
106+
steps outlined above, a new 'device' is added to your account, and you will need to go through the 2FA flow again.
107+
This is inefficient and simply unnecessary.
108+
109+
Therefore, once you are done, it is good practice to save the current state of the account to a file, as well as close
110+
any resources that the instance may be holding onto:
111+
112+
```python
113+
acc.to_json("account.json")
114+
115+
acc.close()
116+
```
117+
118+
Then, if you want to pick up the session again later:
119+
120+
```python
121+
acc = AppleAccount.from_json("account.json", anisette_libs_path="ani_libs.bin")
122+
```

0 commit comments

Comments
 (0)