Skip to content

Instantly share code, notes, and snippets.

@marcus-crane
Created April 27, 2021 06:16
Show Gist options
  • Save marcus-crane/76235a1c6a7740dc1e103b44ee16513a to your computer and use it in GitHub Desktop.
Save marcus-crane/76235a1c6a7740dc1e103b44ee16513a to your computer and use it in GitHub Desktop.
A python script for bulk deleting old devices
"""
Roughly based off https://gist.github.com/gbaman/b3137e18c739e0cf98539bf4ec4366ad
To grab your access token, log into https://accounts.firefox.com/settings
Open your browser dev tools (Right click -> Inspect Element), go to the Network tab
and refresh the page to populate the network stream.
Click on any one of the POST requests to https://graphql.accounts.firefox.com/graphql
and then under the Request Headers portion (at the bottom of the Headers tab),
copy the value for the Authorization Header. Just the token, not the Bearer text itself.
Paste that where it says "<token_goes_here>" and then you can run the script as normal
> pip install requests
> python3 delete-firefox-devices.py
Found 75 devices
Successfully detached Firefox Nightly on Google Pixel 3a
Successfully detached marcus’s Firefox Developer Edition on skeith
...
NOTE: The script may break if/when it detaches the browser you're actively in.
This seems to cause your token to be revoked causing a catch 22.
Feel free to log back in and continue on.
"""
import requests
token = "<token_goes_here>"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
def run_query(query, variables):
joined_query = {'query': query, 'variables': variables}
request = requests.post(
'https://graphql.accounts.firefox.com/graphql',
json=joined_query,
headers=headers)
res = request.json()
if 'errors' in res:
for error in res['errors']:
raise BaseException(error['message'])
else:
return res
deviceQuery = """
{
account {
attachedClients {
clientId
deviceId
name
sessionTokenId
refreshTokenId
}
}
}
"""
disconnectDeviceMutation = """
mutation attachedClientDisconnect($input: AttachedClientDisconnectInput!) {
attachedClientDisconnect(input: $input) {
clientMutationId
__typename
}
}
"""
deviceResult = run_query(deviceQuery, {})
attachedDevices = deviceResult['data']['account']['attachedClients']
print(f"Found {len(attachedDevices)} devices")
for device in attachedDevices:
disconnectDeviceVariables = {
"input": {
"clientId": device['clientId'],
"deviceId": device['deviceId'],
"sessionTokenId": device['sessionTokenId'],
"refreshTokenId": device['refreshTokenId']
}
}
detachResult = run_query(disconnectDeviceMutation, disconnectDeviceVariables)
if 'errors' in detachResult.keys():
print("Error attempting to detach {}: {}".format(device['name'], detachResult['errors']['message']))
else:
print('Successfully detached {}'.format(device['name']))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment