mcp-authkit 0.2.2__tar.gz → 0.2.3__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 (34) hide show
  1. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/PKG-INFO +1 -1
  2. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcp_authkit.egg-info/PKG-INFO +1 -1
  3. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/auth_routes.py +26 -0
  4. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/pyproject.toml +1 -1
  5. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/tests/test_auth_routes.py +60 -0
  6. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/LICENSE +0 -0
  7. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/README.md +0 -0
  8. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcp_authkit.egg-info/SOURCES.txt +0 -0
  9. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcp_authkit.egg-info/dependency_links.txt +0 -0
  10. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcp_authkit.egg-info/requires.txt +0 -0
  11. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcp_authkit.egg-info/top_level.txt +0 -0
  12. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/__init__.py +0 -0
  13. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/auth_middleware.py +0 -0
  14. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/jwt_validator.py +0 -0
  15. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/__init__.py +0 -0
  16. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/credentials_provider.py +0 -0
  17. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/oauth_provider.py +0 -0
  18. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/templates/base.html +0 -0
  19. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/templates/credentials_entry.html +0 -0
  20. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/templates/credentials_error.html +0 -0
  21. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/templates/credentials_success.html +0 -0
  22. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/templates/oauth_error.html +0 -0
  23. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/providers/templates/oauth_success.html +0 -0
  24. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/py.typed +0 -0
  25. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/store/__init__.py +0 -0
  26. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/store/base.py +0 -0
  27. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/store/encryption.py +0 -0
  28. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/store/factory.py +0 -0
  29. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/store/file_store.py +0 -0
  30. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/store/memory.py +0 -0
  31. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/mcpauthkit/store/redis_store.py +0 -0
  32. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/setup.cfg +0 -0
  33. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/tests/test_auth_middleware.py +0 -0
  34. {mcp_authkit-0.2.2 → mcp_authkit-0.2.3}/tests/test_jwt_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-authkit
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Pluggable OAuth 2.0 + credentials elicitation library for FastMCP servers
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/masterela/mcp-authkit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-authkit
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Pluggable OAuth 2.0 + credentials elicitation library for FastMCP servers
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/masterela/mcp-authkit
@@ -24,6 +24,7 @@ from __future__ import annotations
24
24
 
25
25
  import logging
26
26
  import time
27
+ from urllib.parse import urlencode
27
28
 
28
29
  import httpx
29
30
  from fastapi import APIRouter, Request
@@ -37,6 +38,7 @@ def oauth_meta_router(
37
38
  server_base_url: str,
38
39
  issuer_url: str,
39
40
  client_id: str,
41
+ extra_authorize_params: dict[str, str] | None = None,
40
42
  ) -> APIRouter:
41
43
  """
42
44
  Return an ``APIRouter`` with well-known OAuth metadata routes and a DCR
@@ -52,6 +54,26 @@ def oauth_meta_router(
52
54
  ``"https://login.microsoftonline.com/{tenant}/v2.0"``.
53
55
  client_id
54
56
  Pre-registered public client ID returned by the DCR façade.
57
+ extra_authorize_params
58
+ Optional extra query parameters appended to the
59
+ ``authorization_endpoint`` in the
60
+ ``/.well-known/oauth-authorization-server`` response. MCP clients
61
+ read that URL and use it verbatim when redirecting the user to the
62
+ OIDC provider, so any hint placed here is automatically forwarded.
63
+
64
+ Use this for provider-specific routing parameters that fall outside
65
+ the standard OAuth 2.0 / OIDC spec. For example, Okta's ``idp``
66
+ parameter bypasses the Okta login page and routes users directly to
67
+ a configured external Identity Provider::
68
+
69
+ app.include_router(oauth_meta_router(
70
+ server_base_url=settings.server_base_url,
71
+ issuer_url="https://your-org.okta.com/oauth2/default",
72
+ client_id=settings.okta_client_id,
73
+ extra_authorize_params={"idp": "0oaz2r21a8RBmZyOL0h7"},
74
+ ))
75
+
76
+ Default: ``None`` (no extra params — fully retro-compatible).
55
77
  """
56
78
  router = APIRouter()
57
79
  base = server_base_url.rstrip("/")
@@ -85,6 +107,10 @@ def oauth_meta_router(
85
107
  except Exception as exc:
86
108
  logger.warning("Could not fetch OIDC metadata: %s", exc)
87
109
 
110
+ if extra_authorize_params:
111
+ sep = "&" if "?" in auth_ep else "?"
112
+ auth_ep += sep + urlencode(extra_authorize_params)
113
+
88
114
  return JSONResponse(
89
115
  {
90
116
  "issuer": base,
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mcp-authkit"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Pluggable OAuth 2.0 + credentials elicitation library for FastMCP servers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -85,6 +85,66 @@ def test_authorization_server_pkce_supported(client):
85
85
  assert "S256" in data["code_challenge_methods_supported"]
86
86
 
87
87
 
88
+ def test_authorization_server_no_extra_params_by_default(client):
89
+ """Default (extra_authorize_params=None) does not append any extra query params."""
90
+ data = client.get("/.well-known/oauth-authorization-server").json()
91
+ assert "idp=" not in data["authorization_endpoint"]
92
+
93
+
94
+ def test_authorization_server_extra_params_appended():
95
+ """extra_authorize_params are appended to authorization_endpoint."""
96
+ from unittest.mock import AsyncMock, MagicMock, patch
97
+
98
+ app = FastAPI()
99
+ app.include_router(
100
+ oauth_meta_router(
101
+ server_base_url=SERVER,
102
+ issuer_url=ISSUER,
103
+ client_id=CLIENT_ID,
104
+ extra_authorize_params={"idp": "0oaz2r21a8RBmZyOL0h7"},
105
+ )
106
+ )
107
+ tc = TestClient(app, raise_server_exceptions=False)
108
+
109
+ oidc_doc = {
110
+ "authorization_endpoint": "https://org.okta.com/oauth2/default/v1/authorize",
111
+ "token_endpoint": "https://org.okta.com/oauth2/default/v1/token",
112
+ "jwks_uri": "https://org.okta.com/oauth2/default/v1/keys",
113
+ }
114
+ mock_resp = MagicMock()
115
+ mock_resp.status_code = 200
116
+ mock_resp.json.return_value = oidc_doc
117
+ mock_client = MagicMock()
118
+ mock_client.get = AsyncMock(return_value=mock_resp)
119
+ mock_client.__aenter__ = AsyncMock(return_value=mock_client)
120
+ mock_client.__aexit__ = AsyncMock(return_value=None)
121
+
122
+ with patch("mcpauthkit.auth_routes.httpx.AsyncClient", return_value=mock_client):
123
+ data = tc.get("/.well-known/oauth-authorization-server").json()
124
+
125
+ assert "idp=0oaz2r21a8RBmZyOL0h7" in data["authorization_endpoint"]
126
+ # Standard OIDC fields are still present
127
+ assert data["token_endpoint"] == "https://org.okta.com/oauth2/default/v1/token"
128
+
129
+
130
+ def test_authorization_server_extra_params_fallback_no_oidc():
131
+ """extra_authorize_params appended even when OIDC discovery is unreachable."""
132
+ app = FastAPI()
133
+ app.include_router(
134
+ oauth_meta_router(
135
+ server_base_url=SERVER,
136
+ issuer_url=ISSUER,
137
+ client_id=CLIENT_ID,
138
+ extra_authorize_params={"idp": "abc123", "prompt": "login"},
139
+ )
140
+ )
141
+ tc = TestClient(app, raise_server_exceptions=False)
142
+ data = tc.get("/.well-known/oauth-authorization-server").json()
143
+ auth_ep = data["authorization_endpoint"]
144
+ assert "idp=abc123" in auth_ep
145
+ assert "prompt=login" in auth_ep
146
+
147
+
88
148
  def test_authorization_server_uses_oidc_config(client):
89
149
  """When OIDC discovery returns 200, its endpoints override the defaults."""
90
150
  from unittest.mock import AsyncMock, MagicMock, patch
File without changes
File without changes
File without changes