Add account recovery, visible access records and shared sign-out handoff
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
This commit is contained in:
parent
7330c25d80
commit
e54b6ee970
5 changed files with 169 additions and 13 deletions
48
tests/test_account_recovery.py
Normal file
48
tests/test_account_recovery.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import unittest
|
||||
import test_portal_navigation
|
||||
from test_web import invoke
|
||||
|
||||
class AccountRecoveryTests(unittest.TestCase):
|
||||
setUp = test_portal_navigation.PortalNavigationTests.setUp
|
||||
get = test_portal_navigation.PortalNavigationTests.get
|
||||
def test_recovery_is_public_and_never_trusts_query_identity(self):
|
||||
response, body = invoke(self.app, '/access-recovery', query='username=forged&code=private&next=https://evil.example')
|
||||
self.assertEqual('200 OK', response['status'])
|
||||
for marker in [b'forged', b'private', b'evil.example']:
|
||||
self.assertNotIn(marker, body)
|
||||
self.assertIn(b'/logout', body)
|
||||
self.assertNotIn('Location', response['headers'])
|
||||
|
||||
def test_signed_in_recovery_has_verified_identity_and_access_link(self):
|
||||
response, body = self.get('/access-recovery')
|
||||
self.assertEqual('200 OK', response['status'])
|
||||
self.assertIn(b'/onboarding', body)
|
||||
self.assertIn(b'This portal is signed in as', body)
|
||||
_, body = self.get('/onboarding')
|
||||
self.assertIn(b'Current identity', body)
|
||||
self.assertIn(b'Workload access', body)
|
||||
self.assertIn(b'No workload-specific access is recorded', body)
|
||||
|
||||
def test_shared_logout_clears_portal_then_uses_provider_confirmation(self):
|
||||
response, _ = invoke(self.app, '/logout', method='POST', cookie='ue_session=operator', form={'csrf_token':'wrong','scope':'shared'})
|
||||
self.assertEqual('403 Forbidden', response['status'])
|
||||
self.assertIsNotNone(self.oidc.claims('operator'))
|
||||
response, _ = invoke(self.app, '/logout', method='POST', cookie='ue_session=operator', form={'csrf_token':'operator-csrf','scope':'shared','return':'https://evil.example'})
|
||||
self.assertEqual('https://kc.example/account/logout', response['headers']['Location'])
|
||||
self.assertIsNone(self.oidc.claims('operator'))
|
||||
self.assertIsNotNone(self.oidc.claims('member'))
|
||||
_, body = invoke(self.app, '/logged-out')
|
||||
self.assertIn(b'https://kc.example/account/logout',body)
|
||||
|
||||
def test_failed_callback_has_clean_recovery_and_no_loop(self):
|
||||
response, _ = invoke(self.app, '/oidc/callback', query='error=access_denied&state=private&code=private')
|
||||
self.assertEqual('/access-recovery', response['headers']['Location'])
|
||||
|
||||
def test_account_workload_list_is_scoped_to_current_user(self):
|
||||
from user_engine.domain import Membership
|
||||
session = self.app.service.me(self.oidc.claims('operator'), correlation_id='synthetic')
|
||||
for user, scope, label in [(session.user.user_id,'service','own-workload'),('someone-else','service','private-workload')]:
|
||||
self.app.service.store.save_membership(Membership(membership_id=label, user_id=user, tenant='tenant:platform:root', scope_type=scope, scope_id=label, kind='user'))
|
||||
_, body = self.get('/onboarding')
|
||||
self.assertIn(b'own-workload', body)
|
||||
self.assertNotIn(b'private-workload', body)
|
||||
Loading…
Add table
Add a link
Reference in a new issue