Skip to main content

Firefox Accounts client library for Python

Project description

https://travis-ci.org/mozilla/PyFxA.svg?branch=master

This is python library for interacting with the Firefox Accounts ecosystem.

Eventually, it is planned to provide easy support for the following features:

  • being a direct firefox accounts authentication client

  • being an FxA OAuth Service Provider

  • accessing attached services

  • helps interactions with Firefox Account servers wiht requests Authentication plugins.

But none of that is ready yet; caveat emptor.

Firefox Accounts

Currently, basic auth-server operations should work like so:

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")

FxA OAuth Relier

Trade the authentication code against a longer lived OAuth token:

from fxa.oauth import Client

client = Client()
token = client.trade_code("client-id", "client-secret", "code-1234")

Verify an OAuth token:

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"])

Testing email addresses

There’s also very basic integration with restmail.net, to allow for testing with live email addresses. It works like this:

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")

Passing tokens and assertions to other applications

PyFxA provides a fxa-client that you can use to export Bearer Tokens and Browser ID assertions.

Get a Bearer Token for an existing account

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"

Create a new account Bearer Token on stage

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"

Create a new account BrowserID assertion on stage

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"

With Requests

Using Firefox Account BrowserID with Requests

You can use the FxABrowserIDAuth to build the BrowserID assertion:

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']

Using Firefox Account Bearer Token with Requests

You can use the FxABearerTokenAuth to build the Bearer Token:

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']

With HTTPie

Using Firefox Account BrowserID with HTTPie

You can use the httpie plugin provided with PyFxA to build the BrowserID request:

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
}

Using Firefox Account Bearer Tokens with HTTPie

You can use the httpie plugin provided with PyFxA to build the Bearer token request:

$ 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"
}

CHANGELOG

This document describes changes between each past release.

0.7.7 (2020-07-17)

  • Fix incorrect validation of JWKs passed to oauth.Client constructor, which was actually preventing the caller from setting a correct value rather than checking that they did so.

0.7.6 (2020-07-10)

  • Add ability to configure a fixed list of JWT access token keys, by passing them as an argument to oauth.Client() rather than fetching them at runtime from the server.

  • Fix verification of JWT access token typ header. (Thankfully it was failing closed rather than failing open).

  • Fix verification of scope list obtained from a JWT access token. (Thankfully it was failing closed rather than failing open).

0.7.5 (2020-07-06)

  • Add support for reason and verification_method keyword arguments to the login method.

0.7.4 (2020-06-10)

  • Perform more complete checking of the state parameter when authorizing an OAuth code.

  • When verifying OAuth access tokens, try to verify them locally as a JWT rather than passing them to the remote verification endpoint.

0.7.3 (2019-07-26)

  • Allow specifying a ttl when redeeming an authorization code.

0.7.2 (2019-06-03)

  • Several cleans for Python3 compatibility; thanks Tomáš Chvátal!

  • Fix a bug could accidentally introduce multiple slashes into the result of oauth.Client.get_redirect_url.

0.7.1 (2019-03-18)

  • Fix test bustage due to session verification.

0.7.0 (2019-03-18)

  • Add support for TOTP.

0.6.0 (2018-05-04)

  • Add support for PKCE challenge and response in the OAuth flow.

  • Add ability to supply keys_jwk when starting an OAuth flow.

  • Improve scope-matching logic based on new FxA testcases, including handling of URL-format scopes.

0.5.0 (2018-01-12)

  • Add ability to login with unblock codes.

  • Tell testrunners to ignore some test helper utilities.

0.4.0 (2017-??-??)

  • Use pkg_resources to handle package version. (#45)

  • Add a shortcut for authorizing oauth codes directly from a core.Session, rater than requiring the caller to explicitly create an assertion.

0.3.0 (2016-09-07)

  • Add a verify_email_code(uid, code) method to the core.Client (#43).

0.2.0 (2016-05-11)

  • Make sure fxa.tests.utils can be used without installing PyFxA tests dependencies. (#41)

0.1.3 (2016-04-22)

  • Update the User-Agent so that we can detect PyFxA calls. (#40)

0.1.2 (2016-04-21)

  • Correctly send request to the Auth server.

0.1.1 (2016-01-13)

  • Correctly configure cert duration while generating BrowserID Assertion (#39)

0.1.0 (2016-01-07)

  • Add fxa-client CLI tool (#36)

  • Remove support for Python 2.6 (#38)

0.0.9 (2015-08-15)

  • Remove the mention stating that PyFxA is still highly experimental (#31)

  • Do not rely on the package to be installed in order to be used (#32)

0.0.8 (2015-08-14)

  • Update setup.py to handle utf-8 characters in README and CHANGES files (#29)

  • Add cache functionality to the Auth plugins (#30)

0.0.7 (2015-07-23)

  • Use grequests if available to use PyFxA with the gevent ecosystem.

  • Add the oauth /destroy operation.

  • Profile fetch skips fields you don’t have permission to read.

  • Add the BrowserID requests Auth module and related HTTPie plugin.

  • Add the BearerToken requests Auth module and related HTTPie plugin.

  • Add PyOpenSSL support for secure SSL requests handling with Python 2.

0.0.6 (2015-03-20)

  • Expose unicode in oauth cache, not bytestrings.

0.0.5 (2015-03-19)

  • Specify minimum required version of requests dependency.

0.0.4 (2015-03-11)

  • Add a basic API for retrieving profile information

    with an OAuth token.

0.0.3 (2015-02-20)

  • Refacotor oauth.Client to take id/secret as constructor args.

  • Add basic caching on oauth token verification.

  • Accept option “/v1” suffix on server URLs.

  • Add get_identity_assertion() method to core.Session.

  • Add methods to oauth.Client for authorizing codes and tokens.

  • Add a new error hierarchy for trust-related errors.

  • Additional sanity-checking in oauth scope checks.

0.0.2 (2015-01-05)

  • Initial release; includes basic auth and oauth functionality.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

PyFxA-0.7.7.tar.gz (39.1 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page