memydev-auth-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memydev_auth_sdk-0.1.0/.gitignore +8 -0
- memydev_auth_sdk-0.1.0/PKG-INFO +86 -0
- memydev_auth_sdk-0.1.0/README.md +69 -0
- memydev_auth_sdk-0.1.0/pyproject.toml +34 -0
- memydev_auth_sdk-0.1.0/requirements-release.in +13 -0
- memydev_auth_sdk-0.1.0/requirements-release.lock +562 -0
- memydev_auth_sdk-0.1.0/scripts/gen_sync.py +147 -0
- memydev_auth_sdk-0.1.0/src/memyauth/__init__.py +144 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_client.py +169 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_config.py +407 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_discovery.py +172 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_errors.py +270 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_iam.py +298 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_idtoken.py +165 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_oidc.py +237 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_pkce.py +61 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_roles.py +109 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_session.py +149 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_state.py +139 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_sync/__init__.py +3 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_sync/_client.py +171 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_sync/_discovery.py +174 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_sync/_iam.py +300 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_sync/_idtoken.py +167 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_sync/_oidc.py +239 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_sync/_transport.py +223 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_transport.py +221 -0
- memydev_auth_sdk-0.1.0/src/memyauth/_types.py +309 -0
- memydev_auth_sdk-0.1.0/src/memyauth/py.typed +0 -0
- memydev_auth_sdk-0.1.0/src/memyauth/sync/__init__.py +147 -0
- memydev_auth_sdk-0.1.0/tests/conftest.py +67 -0
- memydev_auth_sdk-0.1.0/tests/test_client.py +147 -0
- memydev_auth_sdk-0.1.0/tests/test_config.py +395 -0
- memydev_auth_sdk-0.1.0/tests/test_contract_parity.py +93 -0
- memydev_auth_sdk-0.1.0/tests/test_discovery.py +233 -0
- memydev_auth_sdk-0.1.0/tests/test_errors.py +113 -0
- memydev_auth_sdk-0.1.0/tests/test_iam.py +330 -0
- memydev_auth_sdk-0.1.0/tests/test_idtoken.py +247 -0
- memydev_auth_sdk-0.1.0/tests/test_oidc.py +297 -0
- memydev_auth_sdk-0.1.0/tests/test_pkce.py +76 -0
- memydev_auth_sdk-0.1.0/tests/test_roles.py +117 -0
- memydev_auth_sdk-0.1.0/tests/test_session.py +145 -0
- memydev_auth_sdk-0.1.0/tests/test_state.py +128 -0
- memydev_auth_sdk-0.1.0/tests/test_sync_functional.py +139 -0
- memydev_auth_sdk-0.1.0/tests/test_sync_parity.py +79 -0
- memydev_auth_sdk-0.1.0/tests/test_transport.py +231 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: memydev-auth-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official MemyAuth (OIDC + IAM) client SDK for Python
|
|
5
|
+
License: Proprietary and unlicensed pending approved service terms.
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: httpx<1,>=0.27
|
|
8
|
+
Requires-Dist: pyjwt[crypto]<3,>=2.9
|
|
9
|
+
Provides-Extra: dev
|
|
10
|
+
Requires-Dist: editables==0.5; extra == 'dev'
|
|
11
|
+
Requires-Dist: hatchling==1.27.0; extra == 'dev'
|
|
12
|
+
Requires-Dist: pytest-asyncio==0.24.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: pytest==8.3.5; extra == 'dev'
|
|
14
|
+
Requires-Dist: respx==0.22.0; extra == 'dev'
|
|
15
|
+
Requires-Dist: unasync==0.6.0; extra == 'dev'
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# memydev-auth-sdk
|
|
19
|
+
|
|
20
|
+
Official Python client for **MemyAuth** — the estate's OIDC + IAM provider. Import name: `memyauth`.
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
import asyncio
|
|
24
|
+
from memyauth import MemyAuth
|
|
25
|
+
|
|
26
|
+
async def main() -> None:
|
|
27
|
+
async with MemyAuth(
|
|
28
|
+
issuer_url="https://auth.memy.dev/oidc",
|
|
29
|
+
client_id="my-app",
|
|
30
|
+
client_secret="...",
|
|
31
|
+
public_base_url="https://my-app.example.com",
|
|
32
|
+
id_token_validation="local-jwks", # or "tls-token-endpoint" — see below, no default
|
|
33
|
+
) as auth:
|
|
34
|
+
req = await auth.oidc.build_authorization_url()
|
|
35
|
+
# redirect the browser to req.url, persist req via auth.state.sign(...)
|
|
36
|
+
...
|
|
37
|
+
|
|
38
|
+
asyncio.run(main())
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A synchronous facade is available for non-async callers:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from memyauth.sync import MemyAuth
|
|
45
|
+
|
|
46
|
+
with MemyAuth(issuer_url=..., client_id=..., client_secret=..., id_token_validation="local-jwks") as auth:
|
|
47
|
+
tokens = auth.oidc.exchange_code(code=..., code_verifier=...)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Choosing `id_token_validation`
|
|
51
|
+
|
|
52
|
+
MemyAuth signs ID tokens with **ES384 only**. Two ID-token trust strategies are both in production
|
|
53
|
+
use across the estate and neither is a silent default — you must choose:
|
|
54
|
+
|
|
55
|
+
- `local-jwks` (**recommended for new consumers**): verifies the ID token's signature locally
|
|
56
|
+
against the provider's JWKS, with an explicit algorithm allow-list (`["ES384"]` by default).
|
|
57
|
+
Stateless, no extra round trip, defends against ID-token substitution.
|
|
58
|
+
- `tls-token-endpoint`: performs **no** local signature verification; identity is derived from the
|
|
59
|
+
direct TLS channel to the token endpoint (OIDC Core §3.1.3.7 item 6) plus `/oidc/me` or
|
|
60
|
+
`/iam/me`. Choose this only when you never process the ID token directly.
|
|
61
|
+
|
|
62
|
+
An `allowed_algorithms` pin that cannot verify any token this provider issues (e.g. `["RS256"]`)
|
|
63
|
+
fails loudly at construction with `UnsupportedAlgorithmPinError` — this SDK exists in large part to
|
|
64
|
+
make that historically-real defect (shipped twice against this provider) impossible to repeat
|
|
65
|
+
silently.
|
|
66
|
+
|
|
67
|
+
## Async is the source of truth
|
|
68
|
+
|
|
69
|
+
`memyauth/_*.py` are hand-written and authoritative. `memyauth/_sync/*.py` and the `memyauth.sync`
|
|
70
|
+
facade are **mechanically generated** from them by `scripts/gen_sync.py` (via `unasync`) — never
|
|
71
|
+
hand-edit `_sync/`. Regenerate after any async change:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
python scripts/gen_sync.py # write the twins
|
|
75
|
+
python scripts/gen_sync.py --check # verify no drift; exits non-zero if the twins are stale
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Development
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
python3 -m venv .venv
|
|
82
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
83
|
+
.venv/bin/python -m pip install hatchling==1.27.0 editables==0.5
|
|
84
|
+
.venv/bin/python -m pip install --no-build-isolation -e ".[dev]"
|
|
85
|
+
.venv/bin/python -m pytest -q
|
|
86
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# memydev-auth-sdk
|
|
2
|
+
|
|
3
|
+
Official Python client for **MemyAuth** — the estate's OIDC + IAM provider. Import name: `memyauth`.
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import asyncio
|
|
7
|
+
from memyauth import MemyAuth
|
|
8
|
+
|
|
9
|
+
async def main() -> None:
|
|
10
|
+
async with MemyAuth(
|
|
11
|
+
issuer_url="https://auth.memy.dev/oidc",
|
|
12
|
+
client_id="my-app",
|
|
13
|
+
client_secret="...",
|
|
14
|
+
public_base_url="https://my-app.example.com",
|
|
15
|
+
id_token_validation="local-jwks", # or "tls-token-endpoint" — see below, no default
|
|
16
|
+
) as auth:
|
|
17
|
+
req = await auth.oidc.build_authorization_url()
|
|
18
|
+
# redirect the browser to req.url, persist req via auth.state.sign(...)
|
|
19
|
+
...
|
|
20
|
+
|
|
21
|
+
asyncio.run(main())
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
A synchronous facade is available for non-async callers:
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from memyauth.sync import MemyAuth
|
|
28
|
+
|
|
29
|
+
with MemyAuth(issuer_url=..., client_id=..., client_secret=..., id_token_validation="local-jwks") as auth:
|
|
30
|
+
tokens = auth.oidc.exchange_code(code=..., code_verifier=...)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Choosing `id_token_validation`
|
|
34
|
+
|
|
35
|
+
MemyAuth signs ID tokens with **ES384 only**. Two ID-token trust strategies are both in production
|
|
36
|
+
use across the estate and neither is a silent default — you must choose:
|
|
37
|
+
|
|
38
|
+
- `local-jwks` (**recommended for new consumers**): verifies the ID token's signature locally
|
|
39
|
+
against the provider's JWKS, with an explicit algorithm allow-list (`["ES384"]` by default).
|
|
40
|
+
Stateless, no extra round trip, defends against ID-token substitution.
|
|
41
|
+
- `tls-token-endpoint`: performs **no** local signature verification; identity is derived from the
|
|
42
|
+
direct TLS channel to the token endpoint (OIDC Core §3.1.3.7 item 6) plus `/oidc/me` or
|
|
43
|
+
`/iam/me`. Choose this only when you never process the ID token directly.
|
|
44
|
+
|
|
45
|
+
An `allowed_algorithms` pin that cannot verify any token this provider issues (e.g. `["RS256"]`)
|
|
46
|
+
fails loudly at construction with `UnsupportedAlgorithmPinError` — this SDK exists in large part to
|
|
47
|
+
make that historically-real defect (shipped twice against this provider) impossible to repeat
|
|
48
|
+
silently.
|
|
49
|
+
|
|
50
|
+
## Async is the source of truth
|
|
51
|
+
|
|
52
|
+
`memyauth/_*.py` are hand-written and authoritative. `memyauth/_sync/*.py` and the `memyauth.sync`
|
|
53
|
+
facade are **mechanically generated** from them by `scripts/gen_sync.py` (via `unasync`) — never
|
|
54
|
+
hand-edit `_sync/`. Regenerate after any async change:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
python scripts/gen_sync.py # write the twins
|
|
58
|
+
python scripts/gen_sync.py --check # verify no drift; exits non-zero if the twins are stale
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Development
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
python3 -m venv .venv
|
|
65
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
66
|
+
.venv/bin/python -m pip install hatchling==1.27.0 editables==0.5
|
|
67
|
+
.venv/bin/python -m pip install --no-build-isolation -e ".[dev]"
|
|
68
|
+
.venv/bin/python -m pytest -q
|
|
69
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling==1.27.0"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "memydev-auth-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Official MemyAuth (OIDC + IAM) client SDK for Python"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "Proprietary and unlicensed pending approved service terms." }
|
|
12
|
+
dependencies = [
|
|
13
|
+
"httpx>=0.27,<1",
|
|
14
|
+
"pyjwt[crypto]>=2.9,<3",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
dev = [
|
|
19
|
+
"editables==0.5",
|
|
20
|
+
"hatchling==1.27.0",
|
|
21
|
+
"pytest==8.3.5",
|
|
22
|
+
"pytest-asyncio==0.24.0",
|
|
23
|
+
"respx==0.22.0",
|
|
24
|
+
"unasync==0.6.0", # generates the sync twins in _sync/ (scripts/gen_sync.py); dev-only — the
|
|
25
|
+
# generated files are committed. Pulls tokenize-rt transitively.
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[tool.hatch.build.targets.wheel]
|
|
29
|
+
packages = ["src/memyauth"]
|
|
30
|
+
|
|
31
|
+
[tool.pytest.ini_options]
|
|
32
|
+
asyncio_mode = "auto"
|
|
33
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
34
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Exact top-level inputs for the Python SDK release and subscriber-install gate.
|
|
2
|
+
# Compile with hashes into requirements-release.lock; the protected-tag release workflow installs
|
|
3
|
+
# only that lock (mirrors memybase/sdk/py/requirements-release.in — dossier §8.1/§10).
|
|
4
|
+
build==1.2.2.post1
|
|
5
|
+
editables==0.5
|
|
6
|
+
hatchling==1.27.0
|
|
7
|
+
httpx==0.28.1
|
|
8
|
+
pyjwt[crypto]==2.13.0
|
|
9
|
+
pytest==8.3.5
|
|
10
|
+
pytest-asyncio==0.24.0
|
|
11
|
+
respx==0.22.0
|
|
12
|
+
twine==7.0.0
|
|
13
|
+
unasync==0.6.0
|