How Azeroth Auction Assassin Handles Battle.net OAuth Authentication

Azeroth Auction Assassin implements Battle.net OAuth authentication through a client-credentials flow that fetches access tokens from Blizzard's identity server, caches them for 20 hours to minimize API calls, and automatically refreshes them before the 24-hour expiry window while retrying failed requests up to 10 times.

Azeroth Auction Assassin (AAA) requires valid Battle.net OAuth tokens to query World of Warcraft auction house data via Blizzard's public APIs. The Python implementation splits authentication logic between a lightweight token fetcher in utils/api_requests.py and a caching token manager in utils/mega_data_setup.py that ensures continuous uptime during long-running market scans.

Storing Blizzard API Credentials

AAA expects the Battle.net Client ID and Client Secret to be available either as environment variables or within the mega_data.json configuration file. During initialization, the MegaData.__set_mega_vars method validates these credentials and raises an exception immediately if either value is missing, preventing runtime authentication failures during market scans.

Client-Credentials Grant Implementation

The application uses the OAuth 2.0 client-credentials grant to obtain bearer tokens. Both the standalone utility and the centralized manager issue an HTTP POST request to https://oauth.battle.net/token with the form data grant_type=client_credentials and HTTP Basic authentication using the client ID and secret.

The get_wow_access_token function in utils/api_requests.py (lines 58‑64) provides a thin wrapper around this request:

import requests

def get_wow_access_token(client_id, client_secret):
    response = requests.post(
        "https://oauth.battle.net/token",
        data={"grant_type": "client_credentials"},
        auth=(client_id, client_secret),
    )
    return response.json()["access_token"]

Token Caching and Automatic Refresh

To avoid hitting Blizzard's rate limits and reduce latency, the MegaData class implements a 20-hour token cache that stores the access token and its creation timestamp.

The Cache Validation Logic

The check_access_token method in utils/mega_data_setup.py (lines 44‑76) compares the current Unix time against self.access_token_creation_unix_time. If fewer than 20 hours (72,000 seconds) have elapsed, the existing token is returned immediately. Once the cache expires, the method fetches a fresh token and updates the timestamp, providing a four-hour safety buffer before Blizzard's standard 24-hour token expiration.

from datetime import datetime
from tenacity import retry, stop_after_attempt

class MegaData:
    @retry(stop=stop_after_attempt(10))
    def check_access_token(self):
        current_time = int(datetime.now().timestamp())
        
        # Re-use token if it's younger than 20 hours

        if current_time - self.access_token_creation_unix_time < 20 * 60 * 60:
            return self.access_token
            
        # Request new token

        response = requests.post(
            "https://oauth.battle.net/token",
            data={"grant_type": "client_credentials"},
            auth=(self.WOW_CLIENT_ID, self.WOW_CLIENT_SECRET),
        )
        
        if response.status_code != 200:
            raise Exception(
                "Failed to get access token. Check your Battle.net credentials at "
                "https://develop.battle.net/access/clients"
            )
            
        self.access_token = response.json()["access_token"]
        self.access_token_creation_unix_time = current_time
        return self.access_token

Using Tokens in API Requests

All Blizzard API calls attach the cached token as a Bearer token in the Authorization header. The format follows the OAuth 2.0 standard: {"Authorization": f"Bearer {token}"}.

The methods make_ah_api_request, make_commodity_ah_api_request, get_wow_token_price, and get_petnames all invoke self.check_access_token() to ensure valid authentication before executing their respective endpoints.

headers = {"Authorization": f"Bearer {self.check_access_token()}"}
response = requests.get(
    "https://us.api.blizzard.com/data/wow/token/index",
    headers=headers,
    params={"namespace": "dynamic-us", "locale": "en_US"}
)

Error Handling and Retry Logic

Transient Failure Recovery

The authentication layer uses the @retry decorator from the tenacity library to execute up to 10 attempts with exponential backoff before raising an exception. This protects long-running scans against temporary network interruptions or brief Battle.net API outages.

Invalid Credential Detection

When the OAuth endpoint returns a non-200 status code, check_access_token raises an explicit exception containing the URL https://develop.battle.net/access/clients, directing users to verify their Battle.net application credentials are correctly configured in mega_data.json or environment variables.

Code Examples for Battle.net OAuth

Standalone Token Retrieval

Use the utility function directly when building external scripts that don't require the full MegaData stack:

from utils.api_requests import get_wow_access_token
import os

client_id = os.environ.get("WOW_CLIENT_ID")
client_secret = os.environ.get("WOW_CLIENT_SECRET")

token = get_wow_access_token(client_id, client_secret)
print(f"OAuth token: {token}")

Integrated Authentication with MegaData

For production scanning, instantiate MegaData to benefit from automatic caching and refresh:

from utils.mega_data_setup import MegaData

# Credentials loaded automatically from mega_data.json or env vars

mega = MegaData()

# Token is obtained automatically during __init__

auctions = mega.get_listings_single(realm_id=1234)
print(f"Retrieved {len(auctions)} auctions")

Manual API Call with Bearer Token

When debugging or extending functionality, use the raw header format:

import requests

token = "YOUR_ACCESS_TOKEN"
headers = {"Authorization": f"Bearer {token}"}
url = "https://us.api.blizzard.com/data/wow/auctions/commodities"

response = requests.get(url, headers=headers)
commodities = response.json()["auctions"]

Summary

  • Client-credentials flow: AAA authenticates to https://oauth.battle.net/token using HTTP Basic auth with Client ID and Secret.
  • 20-hour cache: The MegaData.check_access_token method caches tokens to reduce API overhead and refreshes them automatically before the 24-hour expiration.
  • Credential validation: Missing or invalid credentials trigger immediate exceptions during initialization via MegaData.__set_mega_vars.
  • Resilient delivery: The @retry decorator from tenacity attempts failed token requests up to 10 times before failing.
  • Standard Bearer usage: All WoW API calls inject the token via the Authorization: Bearer header.

Frequently Asked Questions

What OAuth grant type does Azeroth Auction Assassin use?

AAA uses the client-credentials grant defined in OAuth 2.0. This server-to-server flow is appropriate because AAA operates as a background service without requiring user consent or interactive login sessions.

How long does AAA cache Battle.net access tokens?

The application caches tokens for 20 hours after acquisition. Since Blizzard tokens remain valid for 24 hours, this four-hour buffer prevents edge-case expirations during long-running market scans.

Where does AAA store Blizzard API credentials?

Credentials are read from environment variables (WOW_CLIENT_ID, WOW_CLIENT_SECRET) or the mega_data.json configuration file. The MegaData.__set_mega_vars method validates their presence during class initialization and raises an exception if either value is missing.

How does AAA handle token expiration during a scan?

The check_access_token method automatically refreshes the token when the 20-hour cache expires. Because every API call routes through this method, the scan continues uninterrupted with the new credentials without manual intervention.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →