tigrbl_auth 0.3.2.dev4__tar.gz → 0.3.2.dev7__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.
Files changed (87) hide show
  1. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/PKG-INFO +1 -1
  2. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/pyproject.toml +1 -1
  3. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/adapters/local_adapter.py +2 -2
  4. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/app.py +4 -0
  5. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/deps/__init__.py +2 -2
  6. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/deps/tigrbl.py +2 -2
  7. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/oidc_discovery.py +7 -5
  8. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/oidc_userinfo.py +8 -4
  9. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc6749_token.py +4 -4
  10. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7009.py +6 -4
  11. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7662_introspection.py +3 -3
  12. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8414.py +7 -4
  13. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8693.py +6 -4
  14. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8932.py +15 -3
  15. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/routers/auth_flows.py +1 -1
  16. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/routers/authz/__init__.py +2 -2
  17. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/routers/authz/oidc.py +1 -1
  18. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/routers/surface.py +4 -4
  19. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/LICENSE +0 -0
  20. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/README.md +0 -0
  21. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/__init__.py +0 -0
  22. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/adapters/__init__.py +0 -0
  23. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/adapters/auth_context.py +0 -0
  24. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/adapters/remote_adapter.py +0 -0
  25. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/backends.py +0 -0
  26. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/crypto.py +0 -0
  27. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/db.py +0 -0
  28. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/deps/fastapi.py +0 -0
  29. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/deps/pydantic.py +0 -0
  30. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/deps/sqlalchemy.py +0 -0
  31. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/errors.py +0 -0
  32. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/fastapi_deps.py +0 -0
  33. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/jwtoken.py +0 -0
  34. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/oidc_id_token.py +0 -0
  35. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/__init__.py +0 -0
  36. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/api_key.py +0 -0
  37. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/auth_code.py +0 -0
  38. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/auth_session.py +0 -0
  39. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/client.py +0 -0
  40. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/device_code.py +0 -0
  41. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/pushed_authorization_request.py +0 -0
  42. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/revoked_token.py +0 -0
  43. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/service.py +0 -0
  44. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/service_key.py +0 -0
  45. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/tenant.py +0 -0
  46. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/orm/user.py +0 -0
  47. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/principal_ctx.py +0 -0
  48. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/__init__.py +0 -0
  49. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc6749.py +0 -0
  50. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc6750.py +0 -0
  51. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7515.py +0 -0
  52. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7516.py +0 -0
  53. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7517.py +0 -0
  54. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7518.py +0 -0
  55. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7519.py +0 -0
  56. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7520.py +0 -0
  57. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7521.py +0 -0
  58. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7523.py +0 -0
  59. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7591.py +0 -0
  60. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7592.py +0 -0
  61. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7636_pkce.py +0 -0
  62. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7638.py +0 -0
  63. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7662.py +0 -0
  64. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7800.py +0 -0
  65. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc7952.py +0 -0
  66. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8037.py +0 -0
  67. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8176.py +0 -0
  68. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8252.py +0 -0
  69. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8291.py +0 -0
  70. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8414_metadata.py +0 -0
  71. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8523.py +0 -0
  72. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8628.py +0 -0
  73. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8705.py +0 -0
  74. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8707.py +0 -0
  75. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8725.py +0 -0
  76. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc8812.py +0 -0
  77. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc9068.py +0 -0
  78. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc9101.py +0 -0
  79. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc9126.py +0 -0
  80. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc9207.py +0 -0
  81. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc9396.py +0 -0
  82. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/rfc/rfc9449_dpop.py +0 -0
  83. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/routers/__init__.py +0 -0
  84. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/routers/schemas.py +0 -0
  85. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/routers/shared.py +0 -0
  86. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/runtime_cfg.py +0 -0
  87. {tigrbl_auth-0.3.2.dev4 → tigrbl_auth-0.3.2.dev7}/tigrbl_auth/typing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl_auth
3
- Version: 0.3.2.dev4
3
+ Version: 0.3.2.dev7
4
4
  Summary: A Tigrbl Multi‑tenant OpenID‑Connect / OAuth2 Identity‑Provider server by Swarmauri.
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl_auth"
3
- version = "0.3.2.dev4"
3
+ version = "0.3.2.dev7"
4
4
  description = "A Tigrbl Multi‑tenant OpenID‑Connect / OAuth2 Identity‑Provider server by Swarmauri."
5
5
  license = "Apache-2.0"
6
6
  readme = "README.md"
@@ -7,9 +7,9 @@ exist in *tigrbl_auth* so that Tigrbl can consume them automatically.
7
7
 
8
8
  Usage
9
9
  -----
10
- >>> from tigrbl import TigrblApi
10
+ >>> from tigrbl import TigrblRouter
11
11
  >>> from tigrbl_auth.adapters import LocalAuthNAdapter
12
- >>> api = TigrblApi(engine=ENGINE, authn=LocalAuthNAdapter())
12
+ >>> api = TigrblRouter(engine=ENGINE, authn=LocalAuthNAdapter())
13
13
  """
14
14
 
15
15
  from __future__ import annotations
@@ -26,6 +26,7 @@ from .oidc_discovery import include_oidc_discovery
26
26
  from .rfc.rfc8693 import include_rfc8693
27
27
  from .oidc_userinfo import include_oidc_userinfo
28
28
  from .rfc.rfc7009 import include_rfc7009
29
+ from .rfc.rfc8932 import include_rfc8932
29
30
 
30
31
 
31
32
  import logging
@@ -60,6 +61,9 @@ if settings.enable_rfc8414:
60
61
  include_rfc8414(app)
61
62
  include_oidc_discovery(app)
62
63
 
64
+ if settings.enable_rfc8932:
65
+ include_rfc8932(app)
66
+
63
67
 
64
68
  async def _startup() -> None:
65
69
  # 1 – metadata validation / SQLite convenience mode
@@ -31,7 +31,7 @@ from .fastapi import (
31
31
  from .sqlalchemy import IntegrityError, Select, select, or_, delete
32
32
  from .tigrbl import (
33
33
  TigrblApp,
34
- TigrblApi,
34
+ TigrblRouter,
35
35
  op_ctx,
36
36
  hook_ctx,
37
37
  engine_ctx,
@@ -114,7 +114,7 @@ __all__ = [
114
114
  "IntegrityError",
115
115
  # tigrbl
116
116
  "TigrblApp",
117
- "TigrblApi",
117
+ "TigrblRouter",
118
118
  "op_ctx",
119
119
  "hook_ctx",
120
120
  "engine_ctx",
@@ -1,4 +1,4 @@
1
- from tigrbl import TigrblApp, TigrblApi, op_ctx, hook_ctx, engine_ctx
1
+ from tigrbl import TigrblApp, TigrblRouter, op_ctx, hook_ctx, engine_ctx
2
2
  from tigrbl.engine import HybridSession as AsyncSession, engine as build_engine
3
3
  from tigrbl.config.constants import TIGRBL_AUTH_CONTEXT_ATTR
4
4
  from tigrbl.types.authn_abc import AuthNProvider
@@ -39,7 +39,7 @@ from tigrbl.types import (
39
39
 
40
40
  __all__ = [
41
41
  "TigrblApp",
42
- "TigrblApi",
42
+ "TigrblRouter",
43
43
  "op_ctx",
44
44
  "hook_ctx",
45
45
  "engine_ctx",
@@ -11,12 +11,12 @@ import json
11
11
  from functools import lru_cache
12
12
  from typing import Any
13
13
 
14
- from tigrbl_auth.deps import TigrblApi, TigrblApp
14
+ from tigrbl_auth.deps import TigrblRouter, TigrblApp
15
15
 
16
16
  from .rfc.rfc8414_metadata import ISSUER, JWKS_PATH
17
17
  from .runtime_cfg import settings
18
18
 
19
- api = TigrblApi()
19
+ api = TigrblRouter()
20
20
  router = api
21
21
 
22
22
 
@@ -92,13 +92,13 @@ def refresh_discovery_cache() -> None:
92
92
  # ---------------------------------------------------------------------------
93
93
  # Routes
94
94
  # ---------------------------------------------------------------------------
95
- @api.get("/.well-known/openid-configuration", tags=[".well-known"])
95
+ @api.route("/.well-known/openid-configuration", methods=["GET"], tags=[".well-known"])
96
96
  async def openid_configuration():
97
97
  """Return OpenID Connect discovery metadata."""
98
98
  return _cached_openid_config(_settings_signature())
99
99
 
100
100
 
101
- @api.get(JWKS_PATH, tags=[".well-known"])
101
+ @api.route(JWKS_PATH, methods=["GET"], tags=[".well-known"])
102
102
  async def jwks():
103
103
  """Publish all public keys in RFC 7517 JWKS format."""
104
104
  from .oidc_id_token import ensure_rsa_jwt_key, rsa_key_provider
@@ -120,7 +120,9 @@ async def jwks():
120
120
  def include_oidc_discovery(app: TigrblApp) -> None:
121
121
  """Attach OIDC discovery routes to *app* if not already present."""
122
122
  if not any(
123
- route.path == "/.well-known/openid-configuration" for route in app.routes
123
+ (getattr(route, "path", None) or getattr(route, "path_template", None))
124
+ == "/.well-known/openid-configuration"
125
+ for route in app.router.routes
124
126
  ):
125
127
  app.include_router(api)
126
128
 
@@ -14,7 +14,7 @@ from __future__ import annotations
14
14
  import inspect
15
15
 
16
16
  from tigrbl_auth.deps import (
17
- TigrblApi,
17
+ TigrblRouter,
18
18
  TigrblApp,
19
19
  HTTPException,
20
20
  Request,
@@ -28,7 +28,7 @@ from .orm import User
28
28
  from .rfc.rfc6750 import extract_bearer_token
29
29
  from .deps import JWAAlg
30
30
 
31
- api = TigrblApi()
31
+ api = TigrblRouter()
32
32
  router = api
33
33
 
34
34
 
@@ -47,7 +47,7 @@ async def _resolve_current_user(request: Request) -> User:
47
47
  return await get_current_principal(request)
48
48
 
49
49
 
50
- @api.get("/userinfo", response_model=None)
50
+ @api.route("/userinfo", methods=["GET"], response_model=None)
51
51
  async def userinfo(request: Request) -> Response | dict[str, str]:
52
52
  """Return claims about the authenticated user.
53
53
 
@@ -101,7 +101,11 @@ async def userinfo(request: Request) -> Response | dict[str, str]:
101
101
  def include_oidc_userinfo(app: TigrblApp) -> None:
102
102
  """Attach the UserInfo endpoint to *app* if not already present."""
103
103
 
104
- if not any(route.path == "/userinfo" for route in app.routes):
104
+ if not any(
105
+ (getattr(route, "path", None) or getattr(route, "path_template", None))
106
+ == "/userinfo"
107
+ for route in app.router.routes
108
+ ):
105
109
  app.include_router(api)
106
110
 
107
111
 
@@ -9,7 +9,7 @@ from uuid import UUID
9
9
 
10
10
  from tigrbl.security.dependencies import Depends as TigrblDepends
11
11
  from tigrbl_auth.deps import (
12
- TigrblApi,
12
+ TigrblRouter,
13
13
  AsyncSession,
14
14
  HTTPException,
15
15
  JSONResponse,
@@ -47,7 +47,7 @@ from ..routers.shared import (
47
47
  )
48
48
  from ..runtime_cfg import settings
49
49
 
50
- api = TigrblApi()
50
+ api = TigrblRouter()
51
51
  router = api
52
52
 
53
53
 
@@ -71,7 +71,7 @@ async def _parse_request_form(request: Request) -> tuple[dict[str, str], list[st
71
71
  return data, resources
72
72
 
73
73
 
74
- @api.post("/token", response_model=TokenPair)
74
+ @api.route("/token", methods=["POST"], response_model=TokenPair)
75
75
  async def token(
76
76
  request: Request, db: AsyncSession = TigrblDepends(get_db)
77
77
  ) -> TokenPair:
@@ -295,7 +295,7 @@ async def token(
295
295
  )
296
296
 
297
297
 
298
- @api.post("/token/refresh", response_model=TokenPair)
298
+ @api.route("/token/refresh", methods=["POST"], response_model=TokenPair)
299
299
  async def refresh(body: RefreshIn, request: Request):
300
300
  _require_tls(request)
301
301
  try:
@@ -13,13 +13,13 @@ from urllib.parse import parse_qs
13
13
 
14
14
  from typing import Final, Set
15
15
 
16
- from tigrbl_auth.deps import TigrblApi, TigrblApp, HTTPException, Request, status
16
+ from tigrbl_auth.deps import TigrblRouter, TigrblApp, HTTPException, Request, status
17
17
 
18
18
  from ..runtime_cfg import settings
19
19
 
20
20
  RFC7009_SPEC_URL: Final = "https://www.rfc-editor.org/rfc/rfc7009"
21
21
 
22
- api = TigrblApi()
22
+ api = TigrblRouter()
23
23
  router = api
24
24
 
25
25
  # In-memory set storing revoked tokens for demonstration and testing purposes
@@ -57,7 +57,7 @@ def reset_revocations() -> None:
57
57
  _REVOKED_TOKENS.clear()
58
58
 
59
59
 
60
- @api.post("/revoked_tokens/revoke")
60
+ @api.route("/revoked_tokens/revoke", methods=["POST"])
61
61
  async def revoke(request: Request) -> dict[str, str]:
62
62
  """RFC 7009 token revocation endpoint."""
63
63
  if not settings.enable_rfc7009:
@@ -77,7 +77,9 @@ async def revoke(request: Request) -> dict[str, str]:
77
77
  def include_rfc7009(app: TigrblApp) -> None:
78
78
  """Attach revocation routes to *app* if enabled."""
79
79
  if settings.enable_rfc7009 and not any(
80
- route.path == "/revoked_tokens/revoke" for route in app.routes
80
+ (getattr(route, "path", None) or getattr(route, "path_template", None))
81
+ == "/revoked_tokens/revoke"
82
+ for route in app.router.routes
81
83
  ):
82
84
  app.include_router(api)
83
85
 
@@ -2,18 +2,18 @@ from __future__ import annotations
2
2
 
3
3
  from urllib.parse import parse_qs
4
4
 
5
- from tigrbl_auth.deps import TigrblApi, HTTPException, Request, status
5
+ from tigrbl_auth.deps import TigrblRouter, HTTPException, Request, status
6
6
 
7
7
  from ..runtime_cfg import settings
8
8
  from ..routers.schemas import IntrospectOut
9
9
  from ..routers.shared import _require_tls
10
10
  from ..rfc.rfc7662 import introspect_token
11
11
 
12
- api = TigrblApi()
12
+ api = TigrblRouter()
13
13
  router = api
14
14
 
15
15
 
16
- @api.post("/introspect", response_model=IntrospectOut)
16
+ @api.route("/introspect", methods=["POST"], response_model=IntrospectOut)
17
17
  async def introspect(request: Request):
18
18
  _require_tls(request)
19
19
  if not settings.enable_rfc7662:
@@ -12,7 +12,7 @@ from __future__ import annotations
12
12
 
13
13
  from typing import Final
14
14
 
15
- from tigrbl_auth.deps import TigrblApi, TigrblApp, HTTPException, status
15
+ from tigrbl_auth.deps import TigrblRouter, TigrblApp, HTTPException, status
16
16
 
17
17
  from ..runtime_cfg import settings
18
18
  from ..oidc_discovery import (
@@ -23,15 +23,16 @@ from ..oidc_discovery import (
23
23
 
24
24
  RFC8414_SPEC_URL: Final = "https://www.rfc-editor.org/rfc/rfc8414"
25
25
 
26
- api = TigrblApi()
26
+ api = TigrblRouter()
27
27
  router = api
28
28
 
29
29
 
30
30
  # ---------------------------------------------------------------------------
31
31
  # Routes
32
32
  # ---------------------------------------------------------------------------
33
- @api.get(
33
+ @api.route(
34
34
  "/.well-known/oauth-authorization-server",
35
+ methods=["GET"],
35
36
  include_in_schema=False,
36
37
  tags=[".well-known"],
37
38
  )
@@ -47,7 +48,9 @@ async def authorization_server_metadata():
47
48
  def include_rfc8414(app: TigrblApp) -> None:
48
49
  """Attach discovery routes to *app* if enabled."""
49
50
  if settings.enable_rfc8414 and not any(
50
- route.path == "/.well-known/oauth-authorization-server" for route in app.routes
51
+ (getattr(route, "path", None) or getattr(route, "path_template", None))
52
+ == "/.well-known/oauth-authorization-server"
53
+ for route in app.router.routes
51
54
  ):
52
55
  app.include_router(api)
53
56
 
@@ -13,7 +13,7 @@ from typing import Any, Dict, List, Optional, Union
13
13
  from enum import Enum
14
14
  import warnings
15
15
  from tigrbl_auth.deps import (
16
- TigrblApi,
16
+ TigrblRouter,
17
17
  TigrblApp,
18
18
  Form,
19
19
  HTTPException,
@@ -32,7 +32,7 @@ RFC8693_SPEC_URL = "https://www.rfc-editor.org/rfc/rfc8693"
32
32
  # Token Exchange Grant Type
33
33
  TOKEN_EXCHANGE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange"
34
34
 
35
- api = TigrblApi()
35
+ api = TigrblRouter()
36
36
  router = api
37
37
 
38
38
 
@@ -40,7 +40,9 @@ def include_rfc8693(app: TigrblApp) -> None:
40
40
  """Attach the RFC 8693 router to *app* if enabled."""
41
41
 
42
42
  if runtime_cfg.settings.enable_rfc8693 and not any(
43
- route.path == "/token/exchange" for route in app.routes
43
+ (getattr(route, "path", None) or getattr(route, "path_template", None))
44
+ == "/token/exchange"
45
+ for route in app.router.routes
44
46
  ):
45
47
  app.include_router(api)
46
48
 
@@ -295,7 +297,7 @@ def exchange_token(
295
297
  )
296
298
 
297
299
 
298
- @api.post("/token/exchange")
300
+ @api.route("/token/exchange", methods=["POST"])
299
301
  async def token_exchange_endpoint(
300
302
  request: Request,
301
303
  grant_type: str = Form(...),
@@ -14,14 +14,14 @@ from __future__ import annotations
14
14
 
15
15
 
16
16
  from typing import Any, Dict, List
17
- from tigrbl_auth.deps import TigrblApi, HTTPException, status
17
+ from tigrbl_auth.deps import TigrblRouter, HTTPException, status
18
18
 
19
19
  from ..runtime_cfg import settings
20
20
  from .rfc8414_metadata import ISSUER, JWKS_PATH
21
21
 
22
22
  RFC8932_SPEC_URL = "https://www.rfc-editor.org/rfc/rfc8932"
23
23
 
24
- api = TigrblApi()
24
+ api = TigrblRouter()
25
25
  router = api
26
26
 
27
27
  # Supported encrypted DNS transports per RFC 8932 recommendations
@@ -210,8 +210,9 @@ def get_enhanced_authorization_server_metadata() -> Dict[str, Any]:
210
210
  return result
211
211
 
212
212
 
213
- @api.get(
213
+ @api.route(
214
214
  "/.well-known/oauth-authorization-server-enhanced",
215
+ methods=["GET"],
215
216
  include_in_schema=False,
216
217
  tags=[".well-known"],
217
218
  )
@@ -332,6 +333,16 @@ def get_capability_matrix() -> Dict[str, Dict[str, Any]]:
332
333
  }
333
334
 
334
335
 
336
+ def include_rfc8932(app) -> None:
337
+ """Register RFC 8932 enhanced metadata endpoint on *app* once."""
338
+ if not any(
339
+ (getattr(route, "path", None) or getattr(route, "path_template", None))
340
+ == "/.well-known/oauth-authorization-server-enhanced"
341
+ for route in app.router.routes
342
+ ):
343
+ app.include_router(api)
344
+
345
+
335
346
  __all__ = [
336
347
  "enforce_encrypted_dns",
337
348
  "get_enhanced_authorization_server_metadata",
@@ -341,5 +352,6 @@ __all__ = [
341
352
  "api",
342
353
  "router",
343
354
  "RFC8932_SPEC_URL",
355
+ "include_rfc8932",
344
356
  "enforce_encrypted_dns",
345
357
  ]
@@ -16,7 +16,7 @@ from .authz import router as router
16
16
  api = router
17
17
 
18
18
 
19
- @router.post("/login", request_model=CredsIn, response_model=TokenPair)
19
+ @router.route("/login", methods=["POST"], response_model=TokenPair)
20
20
  async def login(
21
21
  request: Request,
22
22
  creds: CredsIn | None = None,
@@ -1,7 +1,7 @@
1
- from tigrbl_auth.deps import TigrblApi
1
+ from tigrbl_auth.deps import TigrblRouter
2
2
  from tigrbl_auth.rfc import rfc6749_token, rfc7662_introspection
3
3
 
4
- api = TigrblApi()
4
+ api = TigrblRouter()
5
5
  api.include_router(rfc6749_token.api)
6
6
  api.include_router(rfc7662_introspection.api)
7
7
 
@@ -26,7 +26,7 @@ from ..shared import _require_tls
26
26
  from . import api
27
27
 
28
28
 
29
- @api.get("/authorize")
29
+ @api.route("/authorize", methods=["GET"])
30
30
  async def authorize(
31
31
  request: Request,
32
32
  response_type: str | None = None,
@@ -8,7 +8,7 @@ Exports
8
8
  -------
9
9
  Base : Declarative base for all models in **tigrbl_authn**.
10
10
  metadata : Shared SQLAlchemy ``MetaData`` with a sane naming-convention.
11
- surface_api : ``TigrblApi`` combining Tigrbl resources and auth flows.
11
+ surface_api : ``TigrblRouter`` combining Tigrbl resources and auth flows.
12
12
 
13
13
  The resulting ``surface_api`` exposes a symmetrical REST/RPC surface under
14
14
  namespaces like ``surface_api.core.User.create`` and
@@ -25,7 +25,7 @@ Notes
25
25
 
26
26
  from __future__ import annotations
27
27
 
28
- from tigrbl_auth.deps import TigrblApi
28
+ from tigrbl_auth.deps import TigrblRouter
29
29
  from tigrbl_auth.orm import (
30
30
  Tenant,
31
31
  User,
@@ -43,9 +43,9 @@ from .auth_flows import api as flows_api
43
43
  # ----------------------------------------------------------------------
44
44
  # 3. Build Tigrbl instance & router
45
45
  # ----------------------------------------------------------------------
46
- surface_api = TigrblApi(engine=dsn)
46
+ surface_api = TigrblRouter(engine=dsn)
47
47
 
48
- surface_api.include_models(
48
+ surface_api.include_tables(
49
49
  [
50
50
  Tenant,
51
51
  User,