feat: register OIDC clients from config file
This commit is contained in:
parent
61ca3063ca
commit
eeb09321e2
2 changed files with 66 additions and 0 deletions
|
|
@ -56,6 +56,20 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||||
oidc_server = create_oidc_server(settings)
|
oidc_server = create_oidc_server(settings)
|
||||||
app.state.oidc_server = oidc_server
|
app.state.oidc_server = oidc_server
|
||||||
|
|
||||||
|
# Register configured clients
|
||||||
|
for client_id, client_cfg in settings.clients.items():
|
||||||
|
oidc_server.context.cdb[client_id] = {
|
||||||
|
"client_id": client_id,
|
||||||
|
"client_secret": client_cfg.client_secret,
|
||||||
|
"redirect_uris": [(uri, {}) for uri in client_cfg.redirect_uris],
|
||||||
|
"response_types_supported": client_cfg.response_types,
|
||||||
|
"token_endpoint_auth_method": client_cfg.token_endpoint_auth_method,
|
||||||
|
"scope": client_cfg.scope,
|
||||||
|
"allowed_scopes": client_cfg.scope,
|
||||||
|
"client_salt": secrets.token_hex(8),
|
||||||
|
}
|
||||||
|
oidc_server.keyjar.add_symmetric(client_id, client_cfg.client_secret)
|
||||||
|
|
||||||
# Register management client
|
# Register management client
|
||||||
manage_secret = settings.session_secret or secrets.token_hex(32)
|
manage_secret = settings.session_secret or secrets.token_hex(32)
|
||||||
oidc_server.context.cdb[settings.manage_client_id] = {
|
oidc_server.context.cdb[settings.manage_client_id] = {
|
||||||
|
|
|
||||||
52
tests/test_client_registration.py
Normal file
52
tests/test_client_registration.py
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from httpx import ASGITransport, AsyncClient
|
||||||
|
|
||||||
|
from porchlight.app import create_app
|
||||||
|
from porchlight.config import Settings
|
||||||
|
|
||||||
|
|
||||||
|
async def test_configured_clients_are_registered(tmp_path: Path) -> None:
|
||||||
|
"""Clients defined in config should be registered in the OIDC server."""
|
||||||
|
toml_content = """\
|
||||||
|
issuer = "https://test.example.com"
|
||||||
|
|
||||||
|
[clients.test-rp]
|
||||||
|
client_secret = "test-secret-0123456789abcdef"
|
||||||
|
redirect_uris = ["https://app.example.com/callback"]
|
||||||
|
scope = ["openid", "profile"]
|
||||||
|
"""
|
||||||
|
toml_file = tmp_path / "test.toml"
|
||||||
|
toml_file.write_text(toml_content)
|
||||||
|
|
||||||
|
settings = Settings(_toml_file=str(toml_file)) # type: ignore[call-arg]
|
||||||
|
app = create_app(settings)
|
||||||
|
|
||||||
|
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||||
|
# Trigger lifespan
|
||||||
|
async with app.router.lifespan_context(app):
|
||||||
|
response = await client.get("/health")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
oidc_server = app.state.oidc_server
|
||||||
|
assert "test-rp" in oidc_server.context.cdb
|
||||||
|
cdb_entry = oidc_server.context.cdb["test-rp"]
|
||||||
|
assert cdb_entry["client_id"] == "test-rp"
|
||||||
|
assert cdb_entry["client_secret"] == "test-secret-0123456789abcdef"
|
||||||
|
assert ("https://app.example.com/callback", {}) in cdb_entry["redirect_uris"]
|
||||||
|
assert cdb_entry["scope"] == ["openid", "profile"]
|
||||||
|
assert cdb_entry["allowed_scopes"] == ["openid", "profile"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_manage_app_always_registered() -> None:
|
||||||
|
"""The internal manage-app client is always registered, even without config file clients."""
|
||||||
|
settings = Settings(issuer="https://test.example.com")
|
||||||
|
app = create_app(settings)
|
||||||
|
|
||||||
|
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||||
|
async with app.router.lifespan_context(app):
|
||||||
|
response = await client.get("/health")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
oidc_server = app.state.oidc_server
|
||||||
|
assert "manage-app" in oidc_server.context.cdb
|
||||||
Loading…
Add table
Add a link
Reference in a new issue