Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PYTHON_VERSION=3.12
VENV=.venv

.PHONY: all setup install lint test run clean docs
.PHONY: all setup install lint test run clean docs fxa-user-id

all: setup

Expand All @@ -25,6 +25,12 @@ test:
mlpa:
$(VENV)/bin/mlpa

# Example:
# make fxa-user-id ARGS="--token YOUR_BEARER_TOKEN"
# make fxa-user-id ARGS="--email you@example.com --password your_password"
fxa-user-id:
uv run python scripts/fxa_user_id.py $(ARGS)

clean:
rm -rf __pycache__ .cache $(VENV)

Expand Down
35 changes: 35 additions & 0 deletions docs/fxa-user-id.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Get FxA user_id

## Setup

1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/).
2. Clone this repo, then run:
```bash
make setup
```

## Usage

From the repo root:

**With a Bearer token**
```bash
make fxa-user-id ARGS="--token YOUR_BEARER_TOKEN"
```

**With email and password**
```bash
make fxa-user-id ARGS="--email you@example.com --password YOUR_PASSWORD"
```

Output is the FxA user_id (a single line).

## Options

| Option | Short | Description |
|--------|--------|-------------|
| `--token` | `-t` | FxA OAuth Bearer token. Prints the user_id for that token. |
| `--email` | `-e` | FxA account email. Requires `--password`. |
| `--password` | `-p` | FxA account password. Use with `--email`. |

You must provide either `--token` or both `--email` and `--password`.
55 changes: 55 additions & 0 deletions scripts/fxa_user_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
import argparse
import sys

from fxa.oauth import Client
from fxa.tools.bearer import get_bearer_token

CLIENT_ID: str = "5882386c6d801776"
SCOPE: str = "profile:uid"
FXA_API_ACCOUNTS_URL: str = "https://api.accounts.firefox.com"
FXA_OAUTH_SERVER_URL: str = "https://oauth.accounts.firefox.com"

client = Client(f"{FXA_API_ACCOUNTS_URL}/v1")


def token_to_user_id(token: str) -> str:
raw = token.strip().removeprefix("Bearer ").split()
tok = raw[0] if raw else token.strip()
profile = client.verify_token(tok, scope=SCOPE, include_verification_source=False)
return profile["user"]


def main() -> None:
ap = argparse.ArgumentParser(
description="Get FxA user_id from token or email+password."
)
g = ap.add_mutually_exclusive_group(required=True)
g.add_argument("--token", "-t", metavar="TOKEN", help="Bearer token")
g.add_argument(
"--email", "-e", metavar="EMAIL", help="FxA email (use with --password)"
)
ap.add_argument(
"--password", "-p", metavar="PWD", help="FxA password (use with --email)"
)
args = ap.parse_args()

if args.token:
uid = token_to_user_id(args.token)
else:
if not args.password:
ap.error("--password required when using --email")
token = get_bearer_token(
args.email,
args.password,
scopes=[SCOPE],
client_id=CLIENT_ID,
account_server_url=FXA_API_ACCOUNTS_URL,
oauth_server_url=FXA_OAUTH_SERVER_URL,
)
uid = token_to_user_id(token)
print(f"User ID: {uid}")


if __name__ == "__main__":
main()