Authentication SDK for integrating with Herfy Control Center
Project description
Herfy Auth SDK
Authentication SDK for integrating applications with the Herfy Control Center.
Features
- Local JWT Validation: Validate tokens locally using a shared secret (fast, no network calls)
- Remote Token Validation: Validate tokens via Control Center API (always up-to-date)
- OAuth2 Authorization Code Flow: Redirect users to Control Center for authentication
- Client Credentials Flow: App-to-app authentication
- FastAPI Integration: Ready-to-use dependencies and middleware
- Token Caching: Built-in caching to reduce validation overhead
Installation
# From PyPI (recommended for app repos)
pip install herfy-auth==1.0.0
# With FastAPI support
pip install "herfy-auth[fastapi]==1.0.0"
# Local editable install (monorepo development)
pip install -e packages/auth-sdk
Publishing
Create a PyPI API token and add it as a GitHub repository secret:
PYPI_API_TOKEN
Quick Start
1. Environment Configuration
Set these environment variables:
# Required
CONTROL_CENTER_URL=https://control.herfy.com
SECRET_KEY=your-shared-jwt-secret # Same as Control Center
# For OAuth flows (optional)
AUTH_CLIENT_ID=your-app-id
AUTH_CLIENT_SECRET=your-app-secret
# Optional settings
TOKEN_VALIDATION_MODE=local # "local" or "remote"
TOKEN_CACHE_TTL=300 # seconds
2. FastAPI Integration
from fastapi import FastAPI, Depends
from herfy_auth import init_auth, get_current_user, require_auth, UserInfo
app = FastAPI()
# Initialize auth (call once at startup)
init_auth(
public_routes=["/health", "/api/public"],
public_prefixes=["/static/"],
)
# Protect routes with authentication
@app.get("/api/profile")
async def get_profile(user: UserInfo = Depends(get_current_user)):
return {
"id": user.id,
"email": user.email,
"roles": user.roles,
}
# Require specific roles
@app.get("/api/admin")
async def admin_only(user: UserInfo = Depends(require_auth(roles=["admin"]))):
return {"admin": True}
# Require any of multiple roles
@app.get("/api/staff")
async def staff_route(
user: UserInfo = Depends(require_auth(roles=["admin", "agent"], any_role=True))
):
return {"staff": True}
3. OAuth2 Login Flow
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
from herfy_auth import HerfyAuthClient, AuthConfig
app = FastAPI()
auth_client = HerfyAuthClient(
control_center_url="https://control.herfy.com",
client_id="your-app-id",
client_secret="your-app-secret",
)
@app.get("/login")
async def login():
# Redirect user to Control Center login
login_url = auth_client.get_login_url(
redirect_uri="https://your-app.com/callback",
state="random-csrf-token",
)
return RedirectResponse(login_url)
@app.get("/callback")
async def callback(code: str, state: str):
# Exchange authorization code for tokens
tokens = await auth_client.exchange_code(
code=code,
redirect_uri="https://your-app.com/callback",
)
# Get user info
user = await auth_client.validate_token(tokens.access_token)
return {
"access_token": tokens.access_token,
"user": {
"id": user.id,
"email": user.email,
}
}
4. App-to-App Authentication
from herfy_auth import HerfyAuthClient
# For backend services that need to call the helpdesk API
auth_client = HerfyAuthClient(
control_center_url="https://control.herfy.com",
client_id="your-service-app-id",
client_secret="your-service-app-secret",
)
# Get a token for API calls
async def call_helpdesk_api():
tokens = await auth_client.get_client_credentials_token()
# Use the token to call other APIs
async with httpx.AsyncClient() as client:
response = await client.get(
"https://helpdesk-api.herfy.com/api/tickets",
headers={"Authorization": f"Bearer {tokens.access_token}"}
)
return response.json()
API Reference
HerfyAuthClient
Main client class for authentication operations.
client = HerfyAuthClient(
control_center_url="https://control.herfy.com",
client_id="app-id", # Optional: for OAuth flows
client_secret="app-secret", # Optional: for OAuth flows
jwt_secret="shared-secret", # Optional: for local validation
)
# Validate a token
user = await client.validate_token(token)
# Get OAuth login URL
url = client.get_login_url(redirect_uri, state)
# Exchange authorization code
tokens = await client.exchange_code(code, redirect_uri)
# Get client credentials token
tokens = await client.get_client_credentials_token()
# Refresh a token
tokens = await client.refresh_token(refresh_token)
UserInfo
User information model returned from token validation.
user = await client.validate_token(token)
user.id # User ID
user.email # Email address
user.roles # List of roles
user.org_roles # Organization roles
user.permissions # List of permissions
user.is_admin() # Check if admin
user.has_role("agent") # Check specific role
user.has_permission("tickets:read") # Check permission
FastAPI Dependencies
from herfy_auth import get_current_user, get_optional_user, require_auth, require_admin
# Basic auth required
user = Depends(get_current_user)
# Optional auth (returns None if not authenticated)
user = Depends(get_optional_user)
# Require specific roles
user = Depends(require_auth(roles=["admin"]))
# Require any of multiple roles
user = Depends(require_auth(roles=["admin", "manager"], any_role=True))
# Require specific permissions
user = Depends(require_auth(permissions=["tickets:write"]))
# Convenience admin check
user = Depends(require_admin())
Configuration
AuthConfig
from herfy_auth import AuthConfig
config = AuthConfig(
control_center_url="https://control.herfy.com",
client_id="app-id",
client_secret="app-secret",
jwt_secret="shared-secret",
jwt_algorithm="HS256",
token_validation_mode="local", # "local" or "remote"
cache_ttl_seconds=300,
)
# Or load from environment
config = AuthConfig.from_env()
Environment Variables
| Variable | Description | Default |
|---|---|---|
CONTROL_CENTER_URL |
Control Center API URL | http://localhost:8001 |
AUTH_CLIENT_ID |
OAuth client ID | - |
AUTH_CLIENT_SECRET |
OAuth client secret | - |
SECRET_KEY / JWT_SECRET |
JWT signing secret | - |
JWT_ALGORITHM |
JWT algorithm | HS256 |
TOKEN_VALIDATION_MODE |
local or remote |
local |
TOKEN_CACHE_TTL |
Cache TTL in seconds | 300 |
Token Validation Modes
Local Validation (Recommended)
Validates JWT tokens locally using a shared secret. Fast and doesn't require network calls.
TOKEN_VALIDATION_MODE=local
SECRET_KEY=same-key-as-control-center
Remote Validation
Validates tokens by calling the Control Center's /oauth/userinfo endpoint. Always up-to-date but requires network calls.
TOKEN_VALIDATION_MODE=remote
CONTROL_CENTER_URL=https://control.herfy.com
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file herfy_auth-1.0.0.tar.gz.
File metadata
- Download URL: herfy_auth-1.0.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
768d058cc3084bbf8128c06f35e45f22161cd8d01c26344c4b7974697efb3541
|
|
| MD5 |
c38e680211e03944ae052b90f8b07c77
|
|
| BLAKE2b-256 |
aaf3a9cbb24b9b17d862c8d09ed2e67289761cd9e6468c2f79e54c6dfd32fefe
|
Provenance
The following attestation bundles were made for herfy_auth-1.0.0.tar.gz:
Publisher:
publish-auth-sdk.yml on Herfy-Food-Services/herfy-shared-library
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
herfy_auth-1.0.0.tar.gz -
Subject digest:
768d058cc3084bbf8128c06f35e45f22161cd8d01c26344c4b7974697efb3541 - Sigstore transparency entry: 1494976321
- Sigstore integration time:
-
Permalink:
Herfy-Food-Services/herfy-shared-library@2a31d28136c49af9779978bcf34e3f291170992e -
Branch / Tag:
refs/heads/master - Owner: https://github.com/Herfy-Food-Services
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-auth-sdk.yml@2a31d28136c49af9779978bcf34e3f291170992e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file herfy_auth-1.0.0-py3-none-any.whl.
File metadata
- Download URL: herfy_auth-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8c815b8b592c75c037a28a0fb5583a7adbae8e91d8933f3a47b925260850b06
|
|
| MD5 |
ab25867d944dae3d01282a2582cdb928
|
|
| BLAKE2b-256 |
556602514b4b0802e0088b3f279ff3fab56c03dbd4b20f52c8d8c76bc6dcd631
|
Provenance
The following attestation bundles were made for herfy_auth-1.0.0-py3-none-any.whl:
Publisher:
publish-auth-sdk.yml on Herfy-Food-Services/herfy-shared-library
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
herfy_auth-1.0.0-py3-none-any.whl -
Subject digest:
c8c815b8b592c75c037a28a0fb5583a7adbae8e91d8933f3a47b925260850b06 - Sigstore transparency entry: 1494976349
- Sigstore integration time:
-
Permalink:
Herfy-Food-Services/herfy-shared-library@2a31d28136c49af9779978bcf34e3f291170992e -
Branch / Tag:
refs/heads/master - Owner: https://github.com/Herfy-Food-Services
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-auth-sdk.yml@2a31d28136c49af9779978bcf34e3f291170992e -
Trigger Event:
workflow_dispatch
-
Statement type: