MIT License

项目介绍

AhmadHassan-BTed/ShopifyAutoAuth 是一个托管在 GitHub 上的开源项目,主要使用 Python 编写,采用 MIT License 许可证,目前获得 4.7k 个 Star、0 次 Fork。

仓库全名
AhmadHassan-BTed/ShopifyAutoAuth
开源许可证
MIT License
Star 数
4.7k
未关闭 Issue
3

README 摘要

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. Overview Following Shopify's mandatory authentication migration on January 1, 2026, static shpatxxx custom app tokens were deprecated in favor of OAuth 2.0 Client Credentials Grant short-lived access tokens…

完整内容见 GitHub 原始 README 或本页 。

常见问题

ShopifyAutoAuth 用什么语言开发?

主要使用 Python 编写,采用 MIT License 许可证,目前有 4.7k 个 Star。

ShopifyAutoAuth 可以免费商用吗?

仓库采用 MIT License 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 ShopifyAutoAuth 的源码?

可以直接克隆仓库:git clone https://github.com/AhmadHassan-BTed/ShopifyAutoAuth.git;安装与运行步骤见仓库 README。

ShopifyAutoAuth 最近还在维护吗?

仓库最近一次更新为 9月10日,当前有 3 个未关闭 Issue;Star 数为 4.7k,可作为社区活跃度的参考。

关于

GitHub 原始描述(英文)

Enterprise-grade Shopify Admin API authentication adapter — OAuth 2.0 Client Credentials Grant with automatic token refresh.

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
4709
价值分
2825
活跃状态
活跃

语言占比

Dockerfile
Makefile
Python

Release

README

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:

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

Domain Capability Architectural Mechanism
Authentication OAuth 2.0 Client Credentials Grant Automatic POST /admin/oauth/access_token exchange for Dev Dashboard apps.
Concurrency Thundering Herd Protection Re-entrant threading.RLock double-checked locking mechanism.
Resilience Clock-Skew Mitigation 300-second (5-minute) proactive expiration cutoff buffer.
Header Integration Transparent LiveToken Proxy Custom str subclass executing JIT encoding delegation during HTTP header resolution.
Client Abstraction High-Level ShopifyClient Integrated REST & GraphQL client with automatic 401 cache-invalidation and single retry.
Security Zero Credential Leak Guarantee String 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

评论

暂无评论