Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
This is python library for interacting with the Mozilla Accounts (formerly known as the Firefox Accounts) ecosystem.
Eventually, it is planned to provide easy support for the following features:
But none of that is ready yet; caveat emptor.
Currently, basic auth-server operations should work like so:
.. code-block:: python
from fxa.core import Client
client = Client("https://api.accounts.firefox.com")
client.create_account("test@example.com", "MySecretPassword")
session = client.login("test@example.com", "MySecretPassword")
cert = session.sign_certificate(myPublicKey)
session.change_password("MySecretPassword", "ThisIsEvenMoreSecret")
Trade the authentication code against a longer lived OAuth token:
.. code-block:: python
from fxa.oauth import Client
client = Client()
token = client.trade_code("client-id", "client-secret", "code-1234")
Verify an OAuth token:
.. code-block:: python
from fxa.oauth import Client
from fxa.errors import ClientError
client = Client()
try:
profile = client.verify_token("123456...")
except ClientError:
print "Invalid token"
print("User id", profile["user"])
There's also very basic integration with restmail.net, to allow for testing with live email addresses. It works like this:
.. code-block:: python
from fxa.core import Client
from fxa.tests.utils import TestEmailAccount
# Create a testing account using an @restmail.net address.
acct = TestEmailAccount()
client = Client("https://api.accounts.firefox.com")
session = client.create_account(acct.email, "MySecretPassword")
# Verify the account using the code from email.
acct.fetch()
for m in acct.messages:
if "x-verify-code" in m["headers"]:
session.verify_email_code(m["headers"]["x-verify-code"])
...
# Destroy the account once you're done with it.
acct.clear()
client.destroy_account(acct.email, "MySecretPassword")
PyFxA provides a fxa-client
that you can use to export Bearer
Tokens and Browser ID assertions.
.. code-block:: bash
fxa-client --bearer --auth you@domain.tld \
--account-server https://api.accounts.firefox.com/v1 \
--oauth-server https://oauth.accounts.firefox.com/v1
Please enter a password for you@domain.tld:
# ---- BEARER TOKEN INFO ----
# User: you@domain.tld
# Scopes: profile
# Account: https://api.accounts.firefox.com/v1
# Oauth: https://oauth.accounts.firefox.com/v1
# ---------------------------
export OAUTH_BEARER_TOKEN="3f5106b203c...b728ef93fe29203aad44ee816a45b2f2ff57a6aed7a3"
.. code-block:: bash
fxa-client --bearer --create --prefix hello
# ---- BEARER TOKEN INFO ----
# User: hello-89331eba46e970dc1686ba2dc4583fc9@restmail.net
# Scopes: profile
# Account: https://api-accounts.stage.mozaws.net/v1
# Oauth: https://oauth.stage.mozaws.net/v1
# ---------------------------
export OAUTH_BEARER_TOKEN="ecb5285d59b28e6768fe60d76e6994877ffb16d3232c...72bdee05ea8a5"
.. code-block:: bash
fxa-client --browserid --create --audience https://token.stage.mozaws.net/ --prefix syncto
# ---- BROWSER ID ASSERTION INFO ----
# User: syncto-5bcf63598bf6026a6833035821742d3e@restmail.net
# Audience: https://token.stage.mozaws.net/
# Account: https://api-accounts.stage.mozaws.net/v1
# ------------------------------------
export FXA_BROWSERID_ASSERTION="eyJhbGciOiJSUzI1NiJ9.eyJw......VNKcPu6Uc9Y4pCuGcdM0UwaA"
export FXA_CLIENT_STATE="abaa31cc3b16aaf6759f2cba164a54be"
You can use the FxABrowserIDAuth
to build the BrowserID assertion:
.. code-block:: python
from fxa.core import Client
from fxa.plugins.requests import FxABrowserIDAuth
email = acct.email
password = "MySecretPassword"
raw_resp = requests.get('https://token.services.mozilla.com/1.0/sync/1.5',
auth=FxABrowserIDAuth(email, password,
with_client_state=True))
raw_resp.raise_for_status()
resp = raw_resp.json()
user_id = resp['uid']
You can use the FxABearerTokenAuth
to build the Bearer Token:
.. code-block:: python
from fxa.core import Client
from fxa.plugins.requests import FxABearerTokenAuth
email = acct.email
password = "MySecretPassword"
raw_resp = requests.get('https://profile.accounts.firefox.com/v1/profile',
auth=FxABearerTokenAuth(email, password,
['profile'], client_id))
raw_resp.raise_for_status()
resp = raw_resp.json()
user_id = resp['uid']
You can use the httpie plugin provided with PyFxA to build the BrowserID request:
.. code-block:: http
BID_WITH_CLIENT_STATE=True \
http GET https://token.services.mozilla.com/1.0/sync/1.5 \
--auth-type=fxa-browserid --auth "email:password" -v
GET /1.0/sync/1.5 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: BrowserID eyJhbG..._EqaQ
Connection: keep-alive
Host: token.services.mozilla.com
User-Agent: HTTPie/0.9.2
X-Client-State: 97b945...920fac4d4d5f0dc6...2992
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,X-Conditions-Accepted
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Max-Age: 1728000
Connection: keep-alive
Content-Length: 414
Content-Type: application/json; charset=UTF-8
Date: Tue, 21 Jul 2015 10:48:42 GMT
X-Timestamp: 1437475722
{
"api_endpoint": "https://sync-230-us-west-2.sync.services.mozilla.com/1.5/99283757",
"duration": 3600,
"hashalg": "sha256",
"id": "eyJub2RlI....FlYzdiMCIsICJ1aWQiOiAyMDIzODc3NX2Bvj5zv..7S2jRaw__-....eh3hiSVWA==",
"key": "lSw-MvgK....ebu9JsX-yXS70NkiXu....6wWgVzU0Q=",
"uid": 99283757
}
.. note::
You can configure the audience by settings the ``BID_AUDIENCE``
environment variable.
You can also compute the Token Server client state using the
``BID_WITH_CLIENT_STATE`` environment variable.
You can use the httpie plugin provided with PyFxA to build the Bearer token request:
.. code-block:: http
$ http GET https://profile.accounts.firefox.com/v1/profile \
--auth-type fxa-bearer --auth "email:password" -v
GET /v1/profile HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Bearer 98e05e12ba...0d61231e88daf91
Connection: keep-alive
Host: profile.accounts.firefox.com
User-Agent: HTTPie/0.9.2
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 92
Content-Type: application/json; charset=utf-8
Date: Tue, 21 Jul 2015 14:47:32 GMT
Server: nginx
access-control-allow-headers: Authorization, Content-Type, If-None-Match
access-control-allow-methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
access-control-allow-origin: *
access-control-expose-headers: WWW-Authenticate, Server-Authorization
access-control-max-age: 86400
cache-control: no-cache
content-encoding: gzip
etag: "d1cf22901b3e3be527c06e27689be705bb22a172"
strict-transport-security: max-age=15552000; includeSubdomains
vary: accept-encoding
{
"email": "email@address.com",
"uid": "63b91ca4ec19ad79f320eaf5815d75e9"
}
.. note::
You can configure the following:
- FXA_CLIENT_ID: To choose the CLIENT_ID (default to Firefox Dev id)
- FXA_SCOPES: To choose the list of scopes
- FXA_ACCOUNT_SERVER_URL: To select the account server url
(default to: https://api.accounts.firefox.com/v1)
- FXA_OAUTH_SERVER_URL: To select the oauth server url
(default to: https://oauth.accounts.firefox.com/v1)
The basic requirements are:
To get started:
.. code:: bash
pip install '.[dev]'
pip install .
To run tests:
.. code:: bash
pytest
If you'd like to run all supported versions of Python, install hatch
via pip
or pipx
:
.. code:: bash
pipx install hatch
Once installed you can run the tests in all supported Python environments with:
.. code:: bash
hatch run test:cov
To run the tests with specific Python version you can specify this with hatch:
.. code:: bash
hatch run +py=3.10 test:cov
FAQs
Firefox Accounts client library for Python
We found that pyfxa demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.