#!/usr/bin/env python3 """CryptPad SSO/OIDC integration test.""" import argparse import os import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) from utils.tests.helpers import ( http_get, http_post, load_toml_credentials, resolve_domain, ) def main(): if os.environ.get('SKIP_INTEGRATION') == '1': print("SKIP: OIDC integration test (SKIP_INTEGRATION=1)") return parser = argparse.ArgumentParser() parser.add_argument('--domain', default=os.environ.get('TEST_DOMAIN')) args = parser.parse_args() domain = args.domain or resolve_domain('cryptpad') url = f"https://{domain}" recipe_dir = os.path.join(os.path.dirname(__file__), '..') creds = load_toml_credentials(recipe_dir, 'authentik') if creds is None: print("FAIL: Credentials file not found: authentik-test-credentials..toml") print("Run setup_authentik_integration.py first.") sys.exit(1) print("=== CryptPad SSO/OIDC Integration Test ===") print() # Step 1: Check CryptPad is deployed print("Step 1: Checking CryptPad is deployed ...") status, _ = http_get(url) if status == 0: print(f" FAIL: CryptPad is not reachable at {url}") sys.exit(1) elif status >= 500: print(f" FAIL: CryptPad returned HTTP {status}") sys.exit(1) print(f" OK: CryptPad is reachable (HTTP {status})") # Step 2: Verify Authentik OIDC discovery print("Step 2: Checking Authentik OIDC discovery ...") discovery_url = creds["ak_discovery_endpoint"] status, _ = http_get(discovery_url) if status != 200: print(f" FAIL: OIDC discovery returned HTTP {status}") print(f" URL: {discovery_url}") sys.exit(1) print(f" PASS: OIDC discovery endpoint OK (app '{creds['ak_app_slug']}')") # Step 3: Obtain token from Authentik print("Step 3: Obtaining token from Authentik for test user ...") print(" Using APP_PASSWORD for password grant (authentik requirement)") status, data = http_post( creds["ak_token_endpoint"], data={ "grant_type": "password", "client_id": creds["ak_client_id"], "client_secret": creds["ak_client_secret"], "username": creds["ak_test_user"], "password": creds["ak_test_app_password"], "scope": "openid email profile", }, content_type="application/x-www-form-urlencoded", ) access_token = (data or {}).get("access_token", "") if not access_token: error = (data or {}).get("error_description", (data or {}).get("error", "unknown")) print(f" FAIL: Token request failed: {error}") sys.exit(1) print(f" PASS: Got access token ({len(access_token)} chars)") # Step 4: Verify CryptPad's /ssoauth endpoint (SSO plugin loaded) print("Step 4: Checking CryptPad /ssoauth endpoint ...") status, _ = http_get(f"{url}/ssoauth") if status == 404: print(" FAIL: /ssoauth returned 404 — SSO plugin may not be loaded") sys.exit(1) print(f" PASS: /ssoauth endpoint exists (HTTP {status})") print() print("PASS: CryptPad SSO/OIDC integration test passed") print(" Authentik OIDC discovery OK, token grant OK, /ssoauth endpoint exists.") if __name__ == '__main__': main()