test: update all tests to include CSRF tokens
This commit is contained in:
parent
9e5773f52f
commit
f648422227
12 changed files with 105 additions and 26 deletions
|
|
@ -5,6 +5,7 @@ from urllib.parse import parse_qs, urlparse
|
|||
from argon2 import PasswordHasher
|
||||
from httpx import AsyncClient
|
||||
|
||||
from tests.conftest import get_csrf_token
|
||||
from porchlight.authn.password import PasswordService
|
||||
from porchlight.models import PasswordCredential, User
|
||||
|
||||
|
|
@ -16,10 +17,11 @@ async def test_authorization_shows_consent_for_new_client(client: AsyncClient) -
|
|||
await _create_test_user(app)
|
||||
|
||||
# Login
|
||||
token = await get_csrf_token(client)
|
||||
await client.post(
|
||||
"/login/password",
|
||||
data={"username": "consentuser", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
|
||||
# Authorization request
|
||||
|
|
@ -58,9 +60,11 @@ async def test_consent_allow_redirects_with_code(client: AsyncClient) -> None:
|
|||
await _create_test_user(app)
|
||||
await _login_and_start_auth(client)
|
||||
|
||||
token = await get_csrf_token(client)
|
||||
res = await client.post(
|
||||
"/consent",
|
||||
data={"action": "allow", "scope": ["openid", "profile"]},
|
||||
headers={"X-CSRF-Token": token},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert res.status_code == 303
|
||||
|
|
@ -77,9 +81,11 @@ async def test_consent_deny_redirects_with_error(client: AsyncClient) -> None:
|
|||
await _create_test_user(app)
|
||||
await _login_and_start_auth(client)
|
||||
|
||||
token = await get_csrf_token(client)
|
||||
res = await client.post(
|
||||
"/consent",
|
||||
data={"action": "deny"},
|
||||
headers={"X-CSRF-Token": token},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert res.status_code == 303
|
||||
|
|
@ -97,9 +103,11 @@ async def test_saved_consent_skips_consent_screen(client: AsyncClient) -> None:
|
|||
|
||||
# First flow: login, authorize, consent
|
||||
await _login_and_start_auth(client)
|
||||
token = await get_csrf_token(client)
|
||||
await client.post(
|
||||
"/consent",
|
||||
data={"action": "allow", "scope": ["openid", "profile"]},
|
||||
headers={"X-CSRF-Token": token},
|
||||
follow_redirects=False,
|
||||
)
|
||||
|
||||
|
|
@ -130,9 +138,11 @@ async def test_new_scopes_reshows_consent(client: AsyncClient) -> None:
|
|||
|
||||
# First flow: consent to openid only
|
||||
await _login_and_start_auth(client, scope="openid")
|
||||
token = await get_csrf_token(client)
|
||||
await client.post(
|
||||
"/consent",
|
||||
data={"action": "allow", "scope": ["openid"]},
|
||||
headers={"X-CSRF-Token": token},
|
||||
follow_redirects=False,
|
||||
)
|
||||
|
||||
|
|
@ -158,10 +168,11 @@ async def test_manage_app_skips_consent(client: AsyncClient) -> None:
|
|||
settings = app.state.settings
|
||||
await _create_test_user(app)
|
||||
|
||||
token = await get_csrf_token(client)
|
||||
await client.post(
|
||||
"/login/password",
|
||||
data={"username": "consentuser", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
|
||||
manage_cdb = app.state.oidc_server.context.cdb[settings.manage_client_id]
|
||||
|
|
@ -193,9 +204,11 @@ async def test_partial_consent_filters_scopes(client: AsyncClient) -> None:
|
|||
|
||||
# Request openid + profile + email, approve only openid + profile
|
||||
await _login_and_start_auth(client, scope="openid profile email")
|
||||
token = await get_csrf_token(client)
|
||||
res = await client.post(
|
||||
"/consent",
|
||||
data={"action": "allow", "scope": ["openid", "profile"]},
|
||||
headers={"X-CSRF-Token": token},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert res.status_code == 303
|
||||
|
|
@ -250,10 +263,11 @@ async def _create_test_user(app) -> None:
|
|||
|
||||
|
||||
async def _login_and_start_auth(client: AsyncClient, scope: str = "openid profile") -> None:
|
||||
token = await get_csrf_token(client)
|
||||
await client.post(
|
||||
"/login/password",
|
||||
data={"username": "consentuser", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
await client.get(
|
||||
"/authorization",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from cryptojwt.jwk.jwk import key_from_jwk_dict
|
|||
from cryptojwt.jws.jws import JWS
|
||||
from httpx import AsyncClient
|
||||
|
||||
from tests.conftest import get_csrf_token
|
||||
from porchlight.authn.password import PasswordService
|
||||
from porchlight.models import PasswordCredential, User
|
||||
|
||||
|
|
@ -76,10 +77,11 @@ async def test_full_authorization_code_flow(client: AsyncClient) -> None:
|
|||
assert "/login" in auth_res.headers["location"]
|
||||
|
||||
# -- Step 2: Password login → HX-Redirect to /authorization/complete --
|
||||
token = await get_csrf_token(client)
|
||||
login_res = await client.post(
|
||||
"/login/password",
|
||||
data={"username": "alice", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
assert login_res.status_code == 200
|
||||
hx_redirect = login_res.headers.get("HX-Redirect", "")
|
||||
|
|
@ -95,9 +97,11 @@ async def test_full_authorization_code_flow(client: AsyncClient) -> None:
|
|||
assert "/consent" in complete_res.headers["location"]
|
||||
|
||||
# -- Step 3b: Approve consent → redirect to callback with code + state --
|
||||
token = await get_csrf_token(client)
|
||||
consent_res = await client.post(
|
||||
"/consent",
|
||||
data={"action": "allow", "scope": ["openid", "profile", "email"]},
|
||||
headers={"X-CSRF-Token": token},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert consent_res.status_code in (302, 303)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from datetime import UTC, datetime
|
|||
from argon2 import PasswordHasher
|
||||
from httpx import AsyncClient
|
||||
|
||||
from tests.conftest import get_csrf_token
|
||||
from porchlight.authn.password import PasswordService
|
||||
from porchlight.models import PasswordCredential, User
|
||||
|
||||
|
|
@ -54,10 +55,11 @@ async def test_login_with_pending_oidc_redirects_to_authorization_complete(clien
|
|||
assert auth_res.status_code in (302, 303)
|
||||
|
||||
# Step 2: Login via password
|
||||
token = await get_csrf_token(client)
|
||||
login_res = await client.post(
|
||||
"/login/password",
|
||||
data={"username": "alice", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
assert login_res.status_code == 200
|
||||
redirect_target = login_res.headers.get("HX-Redirect", "")
|
||||
|
|
@ -67,10 +69,11 @@ async def test_login_with_pending_oidc_redirects_to_authorization_complete(clien
|
|||
async def test_login_without_pending_oidc_redirects_to_manage(client: AsyncClient) -> None:
|
||||
await _create_user(client)
|
||||
|
||||
token = await get_csrf_token(client)
|
||||
login_res = await client.post(
|
||||
"/login/password",
|
||||
data={"username": "alice", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
assert login_res.status_code == 200
|
||||
redirect_target = login_res.headers.get("HX-Redirect", "")
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from urllib.parse import parse_qs, urlparse
|
|||
from argon2 import PasswordHasher
|
||||
from httpx import AsyncClient
|
||||
|
||||
from tests.conftest import get_csrf_token
|
||||
from porchlight.authn.password import PasswordService
|
||||
from porchlight.models import PasswordCredential, User
|
||||
|
||||
|
|
@ -47,10 +48,11 @@ async def _create_user_and_login(client: AsyncClient) -> str:
|
|||
svc = PasswordService(hasher=PasswordHasher(time_cost=1, memory_cost=8192))
|
||||
await cred_repo.create_password(PasswordCredential(user_id=user.userid, password_hash=svc.hash("testpass")))
|
||||
|
||||
token = await get_csrf_token(client)
|
||||
await client.post(
|
||||
"/login/password",
|
||||
data={"username": "alice", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
return user.userid
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from urllib.parse import parse_qs, urlparse
|
|||
from argon2 import PasswordHasher
|
||||
from httpx import AsyncClient
|
||||
|
||||
from tests.conftest import get_csrf_token
|
||||
from porchlight.authn.password import PasswordService
|
||||
from porchlight.models import PasswordCredential, User
|
||||
|
||||
|
|
@ -49,10 +50,11 @@ async def _create_user_and_login(client: AsyncClient) -> str:
|
|||
svc = PasswordService(hasher=PasswordHasher(time_cost=1, memory_cost=8192))
|
||||
await cred_repo.create_password(PasswordCredential(user_id=user.userid, password_hash=svc.hash("testpass")))
|
||||
|
||||
token = await get_csrf_token(client)
|
||||
await client.post(
|
||||
"/login/password",
|
||||
data={"username": "alice", "password": "testpass"},
|
||||
headers={"HX-Request": "true"},
|
||||
headers={"HX-Request": "true", "X-CSRF-Token": token},
|
||||
)
|
||||
return user.userid
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue