test(lasuite-docs): update stale OIDC tests for impress v5.4.0 Bearer-auth removal
Some checks are pending
continuous-integration/drone/push Build is running
Some checks are pending
continuous-integration/drone/push Build is running
test_oidc_login_via_keycloak and test_create_doc_and_read_back authenticated with 'Authorization: Bearer <password-grant JWT>'; impress v5.4.0 removed Bearer/JWT auth on the API (SessionAuthentication only), so both went RED with 401 on the v5.4.1 upgrade. Updated to the successor auth path: a new recipe-local _oidc_session.py drives the real OIDC authorization-code flow (app -> keycloak login form -> callback -> Django session cookie, with CSRF headers on unsafe methods). - test_oidc_login: still asserts the unauth challenge redirect; NOW also asserts a raw Bearer JWT is REJECTED (401/403 - the v5.4.0 hardening, asserted as the new correct behavior); then asserts the session-authenticated whoami returns the provisioned user. No assertion weakened - the auth proof is stronger than before. - test_create_doc: same create+read-back round-trip assertions, now over the session-authenticated API. Stale-test fix for recipe PR recipe-maintainers/lasuite-docs#7 (carry-over from /upgrade-all 2026-07-24).
This commit is contained in:
@ -3,12 +3,13 @@
|
||||
Plan §4.3 explicitly names this test for lasuite-docs: "create a doc, edit via the API, confirm
|
||||
persistence". This is the canonical create-an-object + read-it-back for lasuite-docs.
|
||||
|
||||
Flow (uses an OIDC token from the dep keycloak):
|
||||
1. Obtain a JWT via OIDC password grant against the dep keycloak (the test user is provisioned
|
||||
by the orchestrator's dep-provisioning step).
|
||||
2. POST `/api/v1.0/documents/` with `Authorization: Bearer <jwt>` to create a new doc with a
|
||||
Flow (updated for impress v5.4.0, which removed Bearer/JWT auth on the API — the doc CRUD now
|
||||
runs on the app's session cookie from the real OIDC authorization-code login):
|
||||
1. Log in via the OIDC authorization-code flow against the dep keycloak (the test user is
|
||||
provisioned by the orchestrator's dep-provisioning step) → session cookie.
|
||||
2. POST `/api/v1.0/documents/` with the session (+ CSRF header) to create a new doc with a
|
||||
unique title; capture the returned `id`.
|
||||
3. GET `/api/v1.0/documents/<id>/` with the same Bearer token; assert the returned title and
|
||||
3. GET `/api/v1.0/documents/<id>/` with the same session; assert the returned title and
|
||||
id match.
|
||||
|
||||
Non-vacuous: a misconfigured OIDC, broken backend, or missing endpoint fails at the layer it's
|
||||
@ -26,9 +27,9 @@ import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "runner"))
|
||||
from harness import http as harness_http # noqa: E402
|
||||
from harness import sso
|
||||
from _oidc_session import OidcSession # noqa: E402 (recipe-local helper, same dir)
|
||||
|
||||
|
||||
@pytest.mark.requires_deps
|
||||
@ -36,43 +37,29 @@ def test_create_doc_and_read_back(live_app, deps):
|
||||
"""Create a doc via the authenticated API; fetch it back; assert round-trip."""
|
||||
kc = deps["keycloak"]
|
||||
|
||||
# Obtain a JWT via OIDC password grant
|
||||
access_token = sso.oidc_password_grant(
|
||||
{
|
||||
"client_id": kc["client_id"],
|
||||
"client_secret": kc["client_secret"],
|
||||
"user": kc["user"],
|
||||
"password": kc["password"],
|
||||
"token_url": kc["token_url"],
|
||||
}
|
||||
)
|
||||
auth = {"Authorization": f"Bearer {access_token}"}
|
||||
# Session login via the OIDC authorization-code flow (impress v5.4.0+ rejects Bearer JWTs)
|
||||
sess = OidcSession(f"https://{live_app}")
|
||||
sess.login(kc["user"], kc["password"])
|
||||
|
||||
# Create a doc with a unique title
|
||||
title = f"ccci-doc-{uuid.uuid4().hex[:8]}"
|
||||
s, body = harness_http.http_post(
|
||||
f"https://{live_app}/api/v1.0/documents/",
|
||||
data={"title": title},
|
||||
headers=auth,
|
||||
)
|
||||
s, body = sess.post("/api/v1.0/documents/", {"title": title})
|
||||
assert s in (200, 201), f"POST /api/v1.0/documents/ HTTP {s}: {body!r}"
|
||||
assert isinstance(body, dict), f"unexpected response shape: {body!r}"
|
||||
doc_id = body.get("id")
|
||||
assert doc_id, f"created doc has no id: {body!r}"
|
||||
assert (
|
||||
body.get("title") == title
|
||||
), f"created doc title mismatch: created={title!r}, response={body.get('title')!r}"
|
||||
assert body.get("title") == title, (
|
||||
f"created doc title mismatch: created={title!r}, response={body.get('title')!r}"
|
||||
)
|
||||
|
||||
# Fetch it back via the dedicated GET endpoint
|
||||
s, fetched = harness_http.http_get(
|
||||
f"https://{live_app}/api/v1.0/documents/{doc_id}/", headers=auth
|
||||
)
|
||||
s, fetched = sess.get(f"/api/v1.0/documents/{doc_id}/")
|
||||
assert s == 200, f"GET /api/v1.0/documents/{doc_id}/ HTTP {s}: {fetched!r}"
|
||||
assert isinstance(fetched, dict), f"unexpected GET response: {fetched!r}"
|
||||
assert fetched.get("id") in (
|
||||
doc_id,
|
||||
str(doc_id),
|
||||
), f"fetched id mismatch: created={doc_id!r}, fetched={fetched.get('id')!r}"
|
||||
assert (
|
||||
fetched.get("title") == title
|
||||
), f"fetched title mismatch: created={title!r}, fetched={fetched.get('title')!r}"
|
||||
assert fetched.get("title") == title, (
|
||||
f"fetched title mismatch: created={title!r}, fetched={fetched.get('title')!r}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user