Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md
ShopifyAutoAuth Banner

ShopifyAutoAuth

Enterprise-Grade Shopify OAuth 2.0 Client Credentials Adapter

A zero-friction, production-hardened bridge connecting legacy Shopify applications to modern Client Credentials Grant authentication.

CI Status PyPI Version Python Versions License Maintainer


Overview

Following Shopify's mandatory authentication migration on January 1, 2026, static shpat_xxx custom app tokens were deprecated in favor of OAuth 2.0 Client Credentials Grant short-lived access tokens (RFC 6749 §4.4).

shopify_auth_adapter provides a transparent authentication proxy. Existing applications can preserve their variable assignment patterns while under the hood tokens are acquired, cached in volatile RAM, and refreshed prior to expiration without runtime interruption.

Migration: Before vs After

# BEFORE (Deprecated static token):
SHOPIFY_ACCESS_TOKEN = "shpat_xxxxxxxxxxxxxxxxxxxxxxxx"

# AFTER (Automatic OAuth 2.0 token with auto-refresh):
from shopify_auth_adapter import get_access_token

SHOPIFY_ACCESS_TOKEN = get_access_token()

⚡ Quick Start: 1 Line of Code

To upgrade any Python application to Shopify's modern OAuth 2.0 authentication, replace your deprecated shpat_xxx string with get_access_token():

from shopify_auth_adapter import get_access_token

# Automatically fetches, caches in RAM, and auto-refreshes OAuth 2.0 tokens:
SHOPIFY_ACCESS_TOKEN = get_access_token()

That's it! Everything else (OAuth 2.0 requests, RAM caching, automatic 24h refresh) happens automatically behind the scenes.

Installation

pip install shopify-auth-adapter

Setting Up Credentials

You can supply your Shopify Dev Dashboard credentials in any of 3 ways:

Option A: In a .env file (Recommended for Local Dev)

Create a .env file in your project root:

SHOPIFY_SHOP=your-store.myshopify.com
SHOPIFY_CLIENT_ID=your_client_id
SHOPIFY_CLIENT_SECRET=your_client_secret

Option B: Environment Variables (Production / Docker / Cloud)

Set variables in your terminal or deployment environment:

export SHOPIFY_SHOP="your-store.myshopify.com"
export SHOPIFY_CLIENT_ID="your_client_id"
export SHOPIFY_CLIENT_SECRET="your_client_secret"

Option C: Pass Directly in Python Code

from shopify_auth_adapter import get_access_token

token = get_access_token(
    shop="your-store.myshopify.com",
    client_id="your_client_id",
    client_secret="your_client_secret",
)

Testing Credentials

You can verify your Dev Dashboard credentials and store connection instantly by running the included tester script:

python examples/test_credentials.py

Usage Examples

1. Drop-In Token Helper

import httpx

from shopify_auth_adapter import get_access_token

# Automatically reads credentials from .env or environment variables:
headers = {"X-Shopify-Access-Token": get_access_token()}
response = httpx.get(
    "https://your-store.myshopify.com/admin/api/2026-07/shop.json",
    headers=headers,
)

2. High-Level Shopify Client

from shopify_auth_adapter import ShopifyClient

# Automatically attaches tokens and retries on 401:
client = ShopifyClient()

# REST API call
blogs = client.get("/blogs.json").json()["blogs"]

# GraphQL API call
shop_info = client.graphql("""
    query {
        shop {
            name
            email
        }
    }
""")

Feature Matrix

DomainCapabilityArchitectural Mechanism
AuthenticationOAuth 2.0 Client Credentials GrantAutomatic POST /admin/oauth/access_token exchange for Dev Dashboard apps.
ConcurrencyThundering Herd ProtectionRe-entrant threading.RLock double-checked locking mechanism.
ResilienceClock-Skew Mitigation300-second (5-minute) proactive expiration cutoff buffer.
Header IntegrationTransparent LiveToken ProxyCustom str subclass executing JIT encoding delegation during HTTP header resolution.
Client AbstractionHigh-Level ShopifyClientIntegrated REST & GraphQL client with automatic 401 cache-invalidation and single retry.
SecurityZero Credential Leak GuaranteeString masking on repr, str, and tracebacks (LiveToken(<masked>)).

System Architecture & Domain Boundaries

The codebase follows domain-driven modularity principles with contract-based interfaces (Protocol) to guarantee zero coupling and total separation of concerns.

flowchart TD
    subgraph AppLayer["Client Application Layer"]
        App["Application Codebase"]
        Env["Environment Config (.env)"]
    end

    subgraph PkgDomain["shopify_auth_adapter Package"]
        Facade["API Facade"]
        Config["ShopifyConfig"]
        Proxy["LiveToken Proxy"]
        Manager["TokenManager"]
        Cache["InMemoryTokenCache"]
        Provider["OAuth2ClientCredentialsProvider"]
        Client["ShopifyClient"]
    end

    subgraph ExtInfra["External Infrastructure"]
        ShopifyAuth["Shopify OAuth Endpoint"]
        ShopifyAPI["Shopify Admin API"]
    end

    Env --> Config
    App --> Facade
    Facade --> Manager
    Manager --> Provider
    
    App --> Proxy
    Proxy --> Manager
    Manager --> Cache
    Manager --> Provider
    Provider --> ShopifyAuth

    App --> Client
    Client --> Proxy
    Client --> ShopifyAPI

Request Lifecycle & Token Resolution

The diagram below illustrates the exact sequence executed when an HTTP request header formats the LiveToken string proxy:

sequenceDiagram
    autonumber
    participant App as Client Application
    participant Proxy as LiveToken Proxy
    participant Manager as TokenManager
    participant Cache as InMemoryTokenCache
    participant Provider as OAuth2Provider
    participant Shopify as Shopify Server

    App->>Proxy: Header resolution (.encode)
    Proxy->>Manager: get_token()
    Manager->>Cache: get()
    
    alt Cache Hit (Valid Token)
        Cache-->>Manager: CachedToken
    else Cache Miss / Expired
        Manager->>Manager: Acquire Lock
        Manager->>Provider: fetch_token()
        Provider->>Shopify: POST /admin/oauth/access_token
        Shopify-->>Provider: 200 OK Token Response
        Provider-->>Manager: access_token
        Manager->>Cache: set()
    end
    
    Manager-->>Proxy: access_token string
    Proxy-->>App: Encoded Token Bytes

Repository Structure

ShopifyAutoAuth/
├── src/
│   └── shopify_auth_adapter/      # Primary Python package
│       ├── auth/                  # OAuth2 provider, token manager, LiveToken proxy
│       ├── cache/                 # In-memory token cache implementation
│       ├── client/                # ShopifyClient REST and GraphQL helper
│       └── core/                  # Configuration, constants, exceptions, protocols
├── docs/                          # In-depth technical documentation
├── tests/                         # Unit and integration test suite
├── .github/                       # GitHub Actions workflows & community templates
├── pyproject.toml                 # Packaging & tool configurations
└── README.md                      # Project overview & documentation

Technical Deep Dives

Clock-Skew Math & Expiration Buffer

Shopify Client Credentials Grant tokens carry a fixed duration of 86,399 seconds (~24 hours).

To prevent edge cases where a token is valid when read from cache but expires while in flight across the network, the expiration cutoff is calculated as:

$$\text{Cutoff} = T_{\text{expiry}} - 300\text{ seconds}$$

Any token within 5 minutes of expiration is treated as invalid, forcing a fresh token fetch prior to request dispatch.

Security Invariants & Token Masking

Credentials and raw access tokens are strictly protected against unintentional exposure in logs, error reports, and inspection tools:

  • repr(LiveToken) returns "LiveToken(<masked>)".
  • repr(ShopifyConfig) outputs client_secret=<redacted>.
  • repr(CachedToken) outputs access_token=<redacted>.
  • Exception messages exclude credential strings under all circumstances.
Development & Tooling Shortcuts

Common developer tasks are managed via the project Makefile:

# Install editable package with dev tools
make install

# Run linter and type checks
make lint
make typecheck

# Run full test suite with coverage
make test

Build & CI/CD Pipeline

The project utilizes GitHub Actions for continuous quality verification and release automation:

flowchart LR
    Push["Code Push / Tag"] --> Lint["Ruff Linter"]
    Push --> TypeCheck["Mypy Strict Check"]
    Push --> Test["Pytest Suite"]
    
    Lint --> Build["Hatchling Build"]
    TypeCheck --> Build
    Test --> Build

    Build --> PyPI["Publish to PyPI Registry"]

License

This project is licensed under the terms of the MIT License.


Engineered by Ahmad Hassan (B-Ted) 💚

GitHub Profile • PyPI Package • LinkedIn

关于 About

Enterprise-grade Shopify Admin API authentication adapter — OAuth 2.0 Client Credentials Grant with automatic token refresh.
authenticationclient-credentialshttpxoauth2pypi-packagepythonshopifyshopify-apishopify-app

语言 Languages

Python95.2%
Makefile3.2%
Dockerfile1.6%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
40
Total Commits
峰值: 39次/周
Less
More

核心贡献者 Contributors