shark-auth
Python SDK for SharkAuth agent-auth primitives.
Implements the four primitives most agent builders reach for:
DPoPProver— RFC 9449 DPoP proof JWTs (no more hand-rolled JWK x/y /ath/jti).DeviceFlow— RFC 8628 device authorization grant withslow_down+expired_tokenhandling.VaultClient— fetch auto-refreshed 3rd-party OAuth credentials from Shark's Token Vault.decode_agent_token— verify a Shark-issued agent access token (signature, exp, iss, aud) with a cached JWKS.
Targets Python 3.9+.
New to SharkAuth? The Hello Agent walkthrough takes you from zero to a working DPoP-bound agent token in 15 minutes using this SDK.
Install
pip install shark-auth
Quickstart 1 — DPoP-bound device flow
Get a DPoP-bound agent token and call a resource server with it.
from shark_auth import DPoPProver, DeviceFlow
import requests
prover = DPoPProver.generate()
flow = DeviceFlow(
auth_url="https://auth.example",
client_id="agent_abc",
scope="resource:read",
dpop_prover=prover,
)
init = flow.begin()
print(f"Visit {init.verification_uri_complete or init.verification_uri} "
f"and enter code {init.user_code}")
token = flow.wait_for_approval(timeout_s=300)
# Call a resource with DPoP + bearer
proof = prover.make_proof(
"GET",
"https://api.example/data",
access_token=token.access_token,
)
r = requests.get(
"https://api.example/data",
headers={
"Authorization": f"DPoP {token.access_token}",
"DPoP": proof,
},
)
r.raise_for_status()
print(r.json())
Quickstart 2 — DPoPProver standalone
from shark_auth import DPoPProver
# Fresh P-256 keypair
prover = DPoPProver.generate()
# Persist the private key
pem = prover.private_key_pem()
# ...store `pem` safely, then later:
prover = DPoPProver.from_pem(pem)
# Build a proof for a token-endpoint request
proof = prover.make_proof(htm="POST", htu="https://auth.example/oauth/token")
# Include the confirmation claim in your authorization request if the
# server supports `dpop_jkt`:
print("jkt:", prover.jkt)
Quickstart 3 — VaultClient
Fetch a fresh 3rd-party access token from the vault using a DPoP-bound agent token.
from shark_auth import VaultClient, VaultError, OAuthClient, DPoPProver
prover = DPoPProver.generate()
oauth = OAuthClient("https://auth.example")
agent_token = oauth.get_token_with_dpop(
grant_type="client_credentials",
dpop_prover=prover,
client_id="shark_agent_xxx",
client_secret="...",
scope="vault:read",
)
vault = VaultClient(base_url="https://auth.example")
try:
fresh = vault.fetch_token(
provider="google_gmail",
bearer_token=agent_token.access_token,
prover=prover,
)
except VaultError as e:
print(f"vault error: {e} (status={e.status_code})")
raise
print(fresh.access_token[:12] + "...")
Quickstart 4 — decode_agent_token
Resource servers verify agent tokens locally via cached JWKS.
from shark_auth import decode_agent_token, TokenError
try:
claims = decode_agent_token(
token=jwt_string,
jwks_url="https://auth.example/.well-known/jwks.json",
expected_issuer="https://auth.example",
expected_audience="https://api.my-app.example",
)
except TokenError as e:
return 401, str(e)
print(claims.sub, claims.scope, claims.agent_id)
print("DPoP-bound jkt:", claims.jkt)
print("RFC 8693 actor:", claims.act)
print("RFC 9396 authz details:", claims.authorization_details)
Publishing (maintainers)
python -m build
python -m twine upload dist/*
License
MIT — see LICENSE.
Metadata
Release files for shark-auth 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shark_auth-0.1.1.tar.gz | 61.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shark_auth-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 128.0 kB