LumoAuth Python SDK
The official Python SDK for LumoAuth: authorization checks (RBAC, Zanzibar-style ReBAC, ABAC), sign-in for FastAPI apps, and a complete identity toolkit for AI agents, including push approvals, Just-in-Time permissions, delegation and cryptographic AAuth identity.
from lumoauth import LumoAuth
client = LumoAuth(api_key="lk_…", org_id="acme-corp")
if client.permissions.check("document.edit"):
...
One dependency (requests), fully typed, Python 3.9 to 3.13.
Contents
- Which entry point do I need?
- Installation
- Configuration
- Quick start
- Guides
- End-to-end example
- API reference
- Changelog
- License
Which entry point do I need?
Everything lives in one package. Pick the row that matches what you are building and jump to its guide.
| You are building… | Start with | Guide |
|---|---|---|
| A backend service that checks what users may do | LumoAuth |
Authorization checks |
| A FastAPI web app with sign-in | lumoauth.fastapi |
FastAPI integration |
| An AI agent with its own identity | LumoAuthAgent |
Agents |
| An agent that must ask a human before acting | require_approval |
Human approvals |
| An agent that needs short-lived, scoped access | JITContext |
Just-in-Time permissions |
| An agent acting on behalf of a user or sub-agents | DelegationChain |
Delegation |
| An agent with a cryptographic key that signs requests | AAuthClient |
AAuth cryptographic identity |
Still unsure? Services and apps use LumoAuth. Anything autonomous uses
LumoAuthAgent, and the other agent helpers build on top of it.
Installation
pip install lumoauth
Optional extras add features on demand:
| Extra | Install | Adds |
|---|---|---|
aauth |
pip install "lumoauth[aauth]" |
Ed25519 signing for the AAuth protocol (cryptography) |
fastapi |
pip install "lumoauth[fastapi]" |
Login, callback and logout routes for FastAPI |
api |
pip install "lumoauth[api]" |
Generated client for the full REST API behind client.api |
Extras combine: pip install "lumoauth[aauth,fastapi]".
From a local checkout:
pip install -e ./sdk-python # core
pip install -e "./sdk-python[aauth,dev]" # core + AAuth + test tooling
Configuration
Every client accepts its settings as constructor arguments and falls back to environment variables, so production code can stay credential-free:
| Variable | Used by | Description | Default |
|---|---|---|---|
LUMOAUTH_URL |
all | LumoAuth instance URL | https://app.lumoauth.dev |
LUMOAUTH_ORG_ID |
all | Organization ID | (required) |
LUMOAUTH_API_KEY |
LumoAuth |
API key, sent as X-API-Key |
— |
AGENT_CLIENT_ID |
LumoAuthAgent |
Agent OAuth client ID | (required for agents) |
AGENT_CLIENT_SECRET |
LumoAuthAgent |
Agent OAuth client secret | (required for agents) |
# Explicit…
client = LumoAuth(api_key="lk_…", org_id="acme-corp", base_url="https://auth.acme.com")
# …or from the environment
client = LumoAuth()
Quick start
1. Check permissions from a backend
LumoAuth is the general-purpose client. It is organised into resource
namespaces, one per LumoAuth feature.
from lumoauth import LumoAuth
client = LumoAuth(api_key="lk_…", org_id="acme-corp")
# RBAC: does the caller hold this permission?
if client.permissions.check("document.edit"):
...
# ReBAC (Zanzibar): is bob a viewer of this document?
if client.zanzibar.is_viewer("document:readme", "user:bob"):
...
# ABAC: evaluate attribute-based policy for a resource
decision = client.abac.check("document", "read", "doc-123")
if decision["allowed"]:
...
Namespaces: auth, permissions, zanzibar, abac, agents,
delegation, jit, approvals, mcp, plus api for the full generated
client.
2. Add sign-in to a FastAPI app
Three routes and one dependency give you a complete OAuth 2.0 + PKCE login.
import os
from fastapi import Depends, FastAPI
from starlette.middleware.sessions import SessionMiddleware
from lumoauth.fastapi import User, lumo_auth_router, require_auth
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key=os.environ["SESSION_SECRET"])
app.include_router(
lumo_auth_router(
base_url="https://app.lumoauth.dev",
organization="acme-corp",
client_id=os.environ["LUMOAUTH_CLIENT_ID"],
client_secret=os.environ["LUMOAUTH_CLIENT_SECRET"],
callback_path="/auth/callback",
),
prefix="/auth",
)
@app.get("/api/me")
def me(user: User = Depends(require_auth())):
return user.model_dump()
Visit /auth/login to sign in and /auth/logout to sign out.
3. Authenticate an AI agent
LumoAuthAgent gives an agent its own identity via the OAuth 2.0
client-credentials flow, then keeps the token fresh for you.
from lumoauth import LumoAuthAgent
agent = LumoAuthAgent() # reads LUMOAUTH_* and AGENT_* env vars
agent.authenticate()
# Preflight: ask LumoAuth before calling a tool
if agent.is_allowed("document.read", context={"id": "doc_99"}):
resp = agent.api_request("GET", "https://api.acme.com/documents/doc_99")
print(resp.json())
Guides
Authorization checks
All three authorization models are available on LumoAuth. Each has a
boolean fast path and a *_detailed variant that returns the full decision.
RBAC checks permission slugs:
client.permissions.check("document.edit")
client.permissions.check("document.edit", user_id="user_42") # on behalf of a user
client.permissions.check_any(["document.edit", "document.admin"])
client.permissions.check_all(["document.read", "document.edit"])
client.permissions.check_bulk(["document.edit", "document.delete"])
# → {"document.edit": True, "document.delete": False}
detail = client.permissions.check_detailed("document.edit")
ReBAC (Zanzibar) checks relationships between objects and subjects:
client.zanzibar.check("document:readme", "viewer", "user:bob")
client.zanzibar.is_viewer("document:readme", "user:bob")
client.zanzibar.is_editor("document:readme", "user:bob")
client.zanzibar.is_owner("folder:finance", "user:alice")
client.zanzibar.is_member("team:platform", "user:alice")
client.zanzibar.is_admin("org:acme", "user:alice")
ABAC evaluates policies over user and resource attributes:
decision = client.abac.check("document", "read", "doc-123", context={"ip": "10.0.0.8"})
if client.abac.is_allowed("document", "read", "doc-123"):
...
# Manage the attributes policies evaluate
client.abac.set_user_attribute("user_42", "department", "finance")
client.abac.set_resource_attribute("document", "doc-123", "classification", "internal")
print(client.abac.get_my_attributes())
Agents
Authentication and token refresh
Call authenticate() once at startup. Every other method calls
ensure_authenticated() for you, so refreshes are transparent.
agent = LumoAuthAgent(client_id="agt_…", client_secret="…", org_id="acme-corp")
agent.authenticate()
print(agent.access_token) # current bearer token
print(agent.token_scopes) # granted scopes
Capabilities, budget and identity
info = agent.get_agent_info() # sub, name, capabilities, budget_policy, …
if agent.has_capability("tool:search_web"):
...
if agent.is_budget_exhausted():
print("Daily token budget reached, backing off")
me = agent.get_identity() # GET /agents/me
print(me["identity"]["id"], me["capabilities"], me["workspace"])
Ask API: preflight checks for tool calls
The Ask API is a fast "may I do this?" check designed for LLM tool dispatch. Ask before you act, and the decision is audited either way.
result = agent.ask("document.read", context={"id": "doc_99"})
# {"allowed": True, "action": "document.read", "reason": "capability granted",
# "audit_id": "…", "context": {…}}
def dispatch_tool(tool_name: str, args: dict):
if not agent.is_allowed(tool_name, context=args):
return {"error": f"Agent is not authorised to run {tool_name}"}
# … execute the tool
Authenticated HTTP requests
api_request() adds the Authorization header and accepts either a full URL
or a path relative to your LumoAuth instance.
resp = agent.api_request("GET", "https://api.acme.com/documents/123")
resp = agent.api_request(
"POST",
"https://api.acme.com/documents",
data={"query": "quarterly revenue"},
)
Capability gates with a decorator
@require_capability raises PermissionError when the agent lacks the named
capability.
from lumoauth import LumoAuthAgent, require_capability
class ResearchAgent(LumoAuthAgent):
@require_capability("tool:search_web")
def search(self, query: str) -> dict:
return self.api_request("POST", "https://api.acme.com/search", data={"query": query}).json()
MCP token exchange
Exchange the agent token for one scoped to a secured MCP server (RFC 8693):
mcp_token = agent.get_mcp_token("urn:mcp:financial-data")
Human approvals
Before an irreversible action, ask a human. require_approval() sends a push
notification with the action context and blocks until the user approves,
denies, or the request expires.
from lumoauth import LumoAuthAgent, require_approval
agent = LumoAuthAgent()
agent.authenticate()
result = require_approval(
agent,
task_id="wire-2026-05-07-001",
reason="Wire $4,500 to vendor INV-7741",
impact="high", # low | medium | high | critical
on_behalf_of="ada@acme.com",
meta={"action": "wire-transfer", "amount": 4500},
timeout_s=90,
)
if result.status != "approved":
raise RuntimeError(f"Denied: {result.status} ({result.reason})")
# result.token authorises the side-effecting call
Need finer control? agent.approvals.create(), .get_status() and .wait()
expose the individual steps.
Just-in-Time permissions
JIT permissions let an agent request exactly the access it needs, when it needs it, for a short window. Each request creates an ephemeral task, asks for specific permissions using RFC 9396 authorization details, and receives a short-lived token that is revoked when the task completes.
from lumoauth import LumoAuthAgent, JITContext
agent = LumoAuthAgent()
agent.authenticate()
with JITContext(agent) as jit:
jit.create_task(name="Analyse Q4 financial report", task_type="analysis")
result = jit.request_permission(
{
"type": "file_access",
"actions": ["read"],
"identifier": "quarterly_report_q4_2024.pdf",
"locations": ["https://storage.acme-corp.com/finance/"],
},
justification="User asked: 'What were our Q4 revenues?'",
)
if result["status"] == "approved":
token = jit.get_token(result["request_id"])
resp = jit.call(token, "GET", "https://storage.acme-corp.com/finance/quarterly_report_q4_2024.pdf")
print(f"Read {len(resp.content)} bytes")
elif result["status"] == "denied":
print("Denied:", result.get("deny_reason"))
# Leaving the block completes the task and revokes every JIT token
Auto-escalate on 403. When a resource answers 403 with an
Insufficient-Authorization-Details header, call_with_escalation() parses
it, requests the missing permission, and retries:
with JITContext(agent) as jit:
jit.create_task(name="Ad-hoc data access")
resp = jit.call_with_escalation(
"GET",
"https://api.acme-corp.com/v1/documents/doc_9982",
justification="User asked for a summary of doc_9982",
)
Human-in-the-loop. High-risk requests enter a pending state until an
approver acts. request_permission() polls by default; pass
wait_for_approval=False to return immediately and check status_url
yourself.
result = jit.request_permission(
{"type": "database_access", "actions": ["write"], "identifier": "users_table"},
justification="Update email for user 42",
ttl=300,
poll_timeout=300,
)
On behalf of a user. Call jit.delegate_on_behalf_of(user_token) first
and every subsequent request is made "as the user, via the agent".
Without the context manager. Call jit.create_task(...) and make sure
jit.complete_task() runs in a finally block.
Delegation
Delegation (Chain of Agency) lets an agent act on behalf of a user and,
optionally, hand off to sub-agents. It uses RFC 8693 token exchange, and every
resulting JWT carries an act claim so LumoAuth can trace who is behind each
action.
from lumoauth import LumoAuthAgent, DelegationChain
agent = LumoAuthAgent()
agent.authenticate()
chain = DelegationChain(agent, redirect_uri="https://agent.example.com/callback")
# 1. Send the user to consent
url = chain.get_consent_url("session_1", scopes=["read:documents", "write:documents"])
# 2. Handle the callback
chain.handle_consent_callback("session_1", authorization_code)
# 3. Exchange for a delegated token and use it
token = chain.exchange("session_1", scopes=["read:documents"])
resp = chain.request("session_1", "GET", "https://api.acme.com/documents/abc")
Already hold a user token from another OAuth session? Skip consent:
chain.set_user_token("session_1", user_access_token)
token = chain.exchange("session_1")
Nested delegation (user → orchestrator → specialist, up to three levels):
sub_agent = LumoAuthAgent(client_id="agt_specialist", client_secret="…")
sub_agent.authenticate()
nested = chain.delegate_to_sub_agent("session_1", sub_agent.access_token, scopes=["read:documents"])
DelegationChain.get_subject(nested) # "user:alice"
DelegationChain.parse_actor_chain(nested) # ["agent:orchestrator", "agent:specialist"]
Housekeeping: chain.revoke("session_1"), chain.revoke_all(),
chain.active_sessions, chain.has_delegation("session_1").
AAuth cryptographic identity
AAuth extends OAuth 2.1 with cryptographic agent identity. The agent holds an Ed25519 private key, signs every HTTP request (RFC 9421), and receives proof-of-possession tokens that cannot be replayed.
Requires
pip install "lumoauth[aauth]".
Generate a key pair once, store the private key securely, and publish the
JWKS at https://<agent>/.well-known/jwks.json:
from lumoauth import AAuthClient
private_pem, jwks = AAuthClient.generate_keypair()
Create a client and obtain tokens:
client = AAuthClient(
agent_identifier="https://my-agent.example.com",
private_key_pem=open("agent-key.pem").read(),
org_id="acme-corp",
)
result = client.request_authorization(
resource_token=resource_tok,
scope="read write",
agent_token=agent_tok,
redirect_uri="https://my-agent.example.com/callback",
)
if result.get("authorization_required"):
# Send the user to result["auth_url"]; on return, redeem the code.
# redirect_uri must match the URI the code was delivered to.
tokens = client.exchange_code(code, "https://my-agent.example.com/callback", agent_token=agent_tok)
else:
tokens = result # pre-approved: tokens returned directly
Call protected resources with both a Bearer token and an Agent-Auth signature:
resp = client.signed_request(
"POST",
"https://api.example.com/v1/actions",
auth_token=tokens["access_token"],
data={"action": "analyse", "target": "report_q4"},
)
Refresh needs a fresh resource token for the target resource; the refresh token itself is not rotated:
new_tokens = client.refresh(tokens["refresh_token"], fresh_resource_tok, agent_token=agent_tok)
Discovery: client.discover_issuer() and
client.discover_resource("https://api.example.com") fetch the
.well-known metadata documents.
FastAPI integration
Requires
pip install "lumoauth[fastapi]".
lumo_auth_router() mounts /login, /callback and /logout under the
prefix you choose and completes the OAuth 2.0 + PKCE dance. The PKCE verifier
and state live in the Starlette session, never in URLs or cookies, so the
app must add SessionMiddleware.
| Helper | Purpose |
|---|---|
lumo_auth_router(...) |
Builds the router. callback_path must match a redirect URI registered on the OAuth client. |
get_current_user |
Dependency returning the signed-in User, or None. |
require_auth(scopes=None) |
Dependency that responds 401 when signed out and 403 when a scope is missing. |
User |
Pydantic model of the /userinfo claims (sub, email, name, …). Extra claims are preserved. |
@app.get("/api/admin")
def admin(user: User = Depends(require_auth(scopes=["admin"]))):
return {"hello": user.name}
@app.get("/")
def home(user: User | None = Depends(get_current_user)):
return {"signed_in": user is not None}
Pass ?return_to=/dashboard to /login to land somewhere specific after
sign-in. Only same-site paths are honoured.
Error handling
Every HTTP failure raises a subclass of LumoAuthError, so you can catch
exactly what you care about.
LumoAuthError
├── LumoAuthApiError .status_code, .code, .body
│ ├── LumoAuthAuthenticationError 401
│ ├── LumoAuthPermissionDeniedError 403
│ ├── LumoAuthNotFoundError 404
│ └── LumoAuthRateLimitError 429, .retry_after
├── LumoAuthValidationError .issues
├── LumoAuthConfigError
├── LumoAuthNetworkError
├── LumoAuthApprovalDeniedError
├── LumoAuthApprovalTimeoutError
└── LumoAuthBudgetExceededError
import time
from lumoauth import LumoAuthPermissionDeniedError, LumoAuthRateLimitError
try:
client.permissions.check_detailed("document.edit")
except LumoAuthRateLimitError as err:
time.sleep(err.retry_after or 1)
except LumoAuthPermissionDeniedError as err:
print(err.status_code, err.code, err.body)
For backwards compatibility LumoAuthApiError also subclasses
RuntimeError, and LumoAuthConfigError / LumoAuthValidationError also
subclass ValueError.
Beyond the curated surface
The namespaces above cover the common surface. For anything else, client.api
exposes the generated OpenAPI client, configured lazily with the same base
URL and credentials. Agent tokens are resolved per request, so refreshes keep
working.
pip install "lumoauth[api]"
client = LumoAuth(api_key="lk_…", org_id="acme-corp")
client.api # lumoauth_api_client.ApiClient, ready to use
Prefer a bearer token over an API key? Pass token_provider=lambda: my_token
to LumoAuth. When both are set, the provider wins.
End-to-end example
A research agent that preflights its tools with the Ask API, gates a method with a capability, and reads a protected document through JIT with automatic escalation.
from lumoauth import LumoAuthAgent, JITContext, require_capability
class ResearchAgent(LumoAuthAgent):
@require_capability("tool:search_web")
def search_web(self, query: str) -> dict:
return self.api_request(
"POST",
f"/orgs/{self.org_id}/api/v1/tools/search",
data={"query": query},
).json()
def read_document(self, doc_url: str, justification: str) -> bytes:
with JITContext(self) as jit:
jit.create_task(name=f"Read {doc_url}")
resp = jit.call_with_escalation("GET", doc_url, justification=justification)
resp.raise_for_status()
return resp.content
agent = ResearchAgent()
agent.authenticate()
if agent.is_allowed("tool:search_web"):
print(agent.search_web("LumoAuth JIT permissions"))
content = agent.read_document(
"https://storage.acme-corp.com/reports/q4.pdf",
justification="User asked for a Q4 summary",
)
API reference
LumoAuth
LumoAuth(*, api_key=None, base_url=None, org_id=None, token_provider=None,
timeout=30, skip_cert_validation=False)
| Namespace | Methods |
|---|---|
client.auth |
authorization_url(…), exchange_code(code, redirect_uri, …), refresh_token(…), client_credentials(client_id, client_secret, scopes=None), token_exchange(subject_token, …), revoke(token, …), userinfo(access_token=None) |
client.permissions |
check(permission, context=None, *, user_id=None), check_detailed, check_bulk, check_any, check_all, check_any_detailed, check_all_detailed, list(), list_slugs() |
client.zanzibar |
check(object, relation, subject), check_detailed, is_viewer, is_editor, is_owner, is_member, is_admin |
client.abac |
check(resource_type, action, resource_id=None, context=None), is_allowed, check_bulk(requests), get_my_attributes(), set_user_attribute(user_id, slug, value), get_resource_attributes(type, id), set_resource_attribute(type, id, slug, value), get_attribute_definitions(type=None) |
client.agents |
ask(action, context=None), is_allowed, me(), register(name, *, client_id, …), info(), capabilities(), budget() |
client.delegation |
consent_url(…), exchange_code(…), exchange(subject_token, actor_token, scopes=None), refresh_user_token(…), revoke(token, …), parse_actor_chain(token), get_subject(token) |
client.jit |
create_task(…), complete_task(task_id), evaluate_task(task_id, …), request(task_id, authorization_details, …), get_status(request_id), get_token(request_id), pending() |
client.approvals |
create(…), get_status(token), wait(token, …), require(*, task_id, reason, on_behalf_of, …) |
client.mcp |
get_token(server_id, *, subject_token=None) |
client.api |
Generated OpenAPI client (lazy; requires lumoauth[api]) |
LumoAuthAgent
LumoAuthAgent(base_url=None, org_id=None, client_id=None, client_secret=None,
skip_cert_validation=False)
| Method | Description |
|---|---|
authenticate(scopes=None) |
OAuth 2.0 client-credentials authentication |
ensure_authenticated() |
Transparent token refresh |
get_agent_info() |
Identity and capabilities from UserInfo |
has_capability(cap) |
Check a single capability |
get_budget_status() / is_budget_exhausted() |
Budget policy and exhaustion check |
ask(action, context=None) / is_allowed(…) |
Ask API preflight check |
get_identity() |
Agent self-inspection (GET /agents/me) |
api_request(method, endpoint, …) |
Authenticated HTTP request |
get_mcp_token(mcp_server_id) |
RFC 8693 token exchange for MCP servers |
register(name, …) |
Register or update the agent record |
.jit / .delegation / .mcp / .approvals |
Raw resource namespaces (same objects as on LumoAuth) |
JITContext
JITContext(agent, *, delegated_token=None)
| Method | Description |
|---|---|
delegate_on_behalf_of(user_token) |
RFC 8693 token exchange for delegation |
create_task(name=…, task_type=…, on_behalf_of=…) |
Create an ephemeral task |
complete_task() |
Complete the task and revoke all JIT tokens |
request_permission(authorization_details, …) |
RFC 9396 permission request with optional HITL polling |
get_token(request_id) |
Exchange an approval for a short-lived JIT token |
call(jit_token, method, url, …) |
API call with a JIT token |
call_with_escalation(method, url, …) |
Auto-escalate on 403 and retry |
DelegationChain
DelegationChain(agent, *, redirect_uri=None)
| Method | Description |
|---|---|
get_consent_url(session_id, scopes=…) |
Build the user consent URL |
handle_consent_callback(session_id, code) |
Redeem the authorization code |
set_user_token(session_id, token) |
Use an existing user token |
exchange(session_id, scopes=None) |
Obtain a delegated token |
request(session_id, method, url, …) |
HTTP request with the delegated token |
delegate_to_sub_agent(session_id, sub_agent_token, scopes=…) |
Nested delegation |
revoke(session_id) / revoke_all() |
Revoke delegations |
parse_actor_chain(token) / get_subject(token) (static) |
Inspect any delegated JWT |
AAuthClient
AAuthClient(agent_identifier, private_key_pem, *, base_url=None, org_id=None,
kid="key-1", skip_cert_validation=False)
| Method | Description |
|---|---|
generate_keypair() (static) |
Ed25519 key pair plus JWKS |
sign_request(method, url, …) |
RFC 9421 HTTP message signature headers |
request_authorization(resource_token, scope, …) |
Obtain tokens (direct or via user consent) |
exchange_code(code, redirect_uri, *, agent_token) |
Redeem a consent code |
refresh(refresh_token, resource_token, *, scope=None, agent_token) |
Refresh with a fresh resource token |
signed_request(method, url, auth_token=…, …) |
Authenticated and signed HTTP request |
discover_issuer() / discover_resource(url) |
Fetch .well-known metadata |
Helpers
| Name | Description |
|---|---|
require_capability(cap) |
Decorator for LumoAuthAgent methods; raises PermissionError when the capability is missing |
require_approval(agent, *, task_id, reason, on_behalf_of, impact="medium", meta=None, poll_interval_s=1.5, timeout_s=90) |
Push approval that blocks until resolved; returns ApprovalResult |
ApprovalResult |
Frozen dataclass: status, token, task_id, impact, reason, responded_at, approved_by |
lumoauth.fastapi
| Name | Description |
|---|---|
lumo_auth_router(*, base_url, organization, client_id, client_secret=None, callback_path="/auth/callback", scope="openid profile email", post_login_redirect="/", post_logout_redirect="/") |
Router with /login, /callback, /logout |
get_current_user(request) |
Dependency returning User or None |
require_auth(scopes=None) |
Dependency factory raising 401 / 403 |
User |
Pydantic model of the signed-in principal |
LumoAuthFastAPI |
Configuration container, for sharing settings with custom dependencies |
Changelog
1.0.0
- New
LumoAuthclient with resource namespaces (auth,permissions,zanzibar,abac,agents,delegation,jit,approvals,mcp) and a lazyclient.apiescape hatch to the generated OpenAPI client (pip install "lumoauth[api]"). - Typed error taxonomy (
LumoAuthError/LumoAuthApiError/LumoAuthAuthenticationError/ …) replacing bareValueError/RuntimeError. The new classes subclass the builtins they replaced, so existingexceptclauses keep working. - All endpoint paths centralised in
lumoauth._routes.ROUTESwith an OpenAPI drift test. LumoAuthAgentmoved tolumoauth.agent(importing it fromlumoauth.clientorlumoauthstill works) and is now a thin layer overLumoAuth. Every existing method keeps its name, signature and behaviour.DelegationChainandJITContextkeep their ergonomic surfaces but delegate to the shared resources internally.
0.2.0
Breaking fixes. The AAuth client now matches the AAuth 1.0 server contract for the agent token endpoint:
AAuthClient.exchange_code(code, redirect_uri, *, agent_token): the second parameter is nowredirect_uri(previouslyrequest_token). The code is bound to the exact redirect URI it was delivered to.AAuthClient.refresh(refresh_token, resource_token, *, scope=None, agent_token): a freshresource_tokenfor the target resource is now a required second positional parameter, andscopebecame keyword-only.
License
Apache-2.0
Metadata
Release files for lumoauth 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| lumoauth-1.0.0.tar.gz | 65.6 kB | Without provenance | Details for lumoauth-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| lumoauth-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for lumoauth-1.0.0-py3-none-any.whl |
Total release size: 125.6 kB
Release files / lumoauth-1.0.0.tar.gz
| Download URL | lumoauth-1.0.0.tar.gz |
|---|---|
| Size | 65.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
149fc567276bc1c62eca95451fae6be6c4a4359d420aa3fcce80f69dcd7f47e0
|
|
BLAKE2b-256 checksum How to use checksums |
fe38e1d03e3e474bae13bfa6d2904844ceda3445a0d7c82a7d015c2945e2a30f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / lumoauth-1.0.0-py3-none-any.whl
| Download URL | lumoauth-1.0.0-py3-none-any.whl |
|---|---|
| Size | 60.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d575fcc33db9b3d6dae8007a1150aac43c7e3c349f88b1c33929b184940121f2
|
|
BLAKE2b-256 checksum How to use checksums |
83f4ce589a70728e54a11bb8e7d1719c516c3c14b9a8b1ba32bb24c5e495f5c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Security for lumoauth 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.