Test the complete integration against the Parkour Design test environment before production credentials are issued. Automated checks prove protocol and contract behavior; manual acceptance proves the user journey and operational recovery.
Release rule: A successful authorization callback is not sufficient acceptance. Launch requires identity validation, user isolation, token rotation, resource-contract tests, failure recovery, and approval from both teams.
Test prerequisites
Parkour Design and the partner must prepare:
- a registered test client and securely delivered secret;
- an exact test redirect URI;
- the approved scope set;
- at least two Parkour Design test users;
- Events and designs owned separately by each user;
- one empty account or Event where relevant;
- technical and incident contacts;
- expected results for every acceptance case.
Use the test issuer:
https://parkour-test.web.app
Do not reuse test credentials, callback URLs, tokens, or user data in production.
Preflight checks
Discovery
curl --fail-with-body \
"https://parkour-test.web.app/.well-known/openid-configuration"
Verify that:
issuerexactly equals the configured test issuer;- authorization, token, UserInfo, and JWKS endpoints use HTTPS;
code,authorization_code,refresh_token,RS256, andS256are present;- no client secret or environment-specific private value appears in discovery.
Signing keys
Fetch jwks_uri from discovery and verify that each usable key has a kid, kty, signing use, and an approved algorithm. The client must handle an unknown kid by refreshing JWKS once before rejecting the token.
Unauthenticated resource request
curl --include "https://parkour-test.web.app/api/events"
Expected result:
HTTP/2 401
Content-Type: application/json
{"error":"invalid_token"}
Automated OAuth tests
Automate these cases at the partner boundary. Use controlled fixtures and mock only the external browser step when a full browser test is impractical.
Authorization request
- includes exact client ID, redirect URI, and approved scopes;
- generates unique high-entropy
state,nonce, and PKCE verifier values; - sends
code_challenge_method=S256; - does not put the client secret or verifier in the URL;
- rejects an unregistered or subtly different redirect URI during a negative environment test.
Callback
- accepts the correct state once;
- rejects missing, mismatched, expired, and reused state;
- handles
access_deniedwithout exchanging a code; - rejects a missing code on an otherwise successful callback;
- preserves only a validated local return path;
- does not expose protocol diagnostics or personal data to the browser.
Code exchange
- authenticates with
client_secret_basic; - uses the same redirect URI as the authorization request;
- sends the original PKCE verifier;
- rejects expired, reused, wrong-client, and wrong-verifier codes;
- treats token responses as non-cacheable and keeps them server-side.
ID-token validation
Reject tokens with:
- an invalid signature;
- an unknown signing key after one JWKS refresh;
- the wrong issuer;
- the wrong audience;
- an algorithm other than
RS256; - a missing or wrong nonce;
- expired or implausible time claims;
- a missing subject.
Verify that account linking uses the pair iss and sub, not email alone.
Refresh rotation
- a valid refresh token returns a new access token and replacement refresh token;
- the replacement is committed atomically;
- refresh operations are serialized for each user and client session;
- reuse of the old refresh token is rejected;
- a token issued to another client is rejected;
- an expired token requires a new authorization flow;
- a timeout or lost refresh response with an unknown outcome clears local token state and starts a new authorization flow instead of retrying the old token;
- concurrent refresh attempts cannot race with the same token;
- local disconnect deletes the active refresh token and session data.
Parkour Design currently has no public revocation endpoint. Tests must not report local deletion as server-side revocation.
Automated resource tests
Authentication and isolation
- no token returns
401 invalid_token; - an expired or malformed token returns
401 invalid_token; - an ID token used as a bearer API token is rejected;
- user A sees only user A’s Events and designs;
- user B cannot retrieve user A’s Event by copying its ID;
- inaccessible and nonexistent Events both return
404 not_found.
Schema contract
Validate every response against a partner-owned schema fixture:
- required properties are present;
- nullable properties accept
null; - dates parse as ISO 8601 values;
- unknown additional properties do not break the client;
- empty collections return an empty
itemsarray; - identifiers are treated as opaque strings;
- text supports Unicode and is rendered safely.
Do not derive a complete course design from the summary schema.
Limits and failures
- the client handles the largest approved Event list;
- the 500-design current detail limit is represented in the launch risk assessment;
401,404,405,429, and5xxresponses follow the agreed retry policy;- timeouts do not trigger unbounded retries;
- malformed JSON fails safely and records a sanitized diagnostic;
- repeated idempotent
GETrequests do not mutate partner state.
Tests for Parkour Design-to-partner exports
When Parkour Design sends data to a partner, add bilateral contract tests for:
- destination listing and identifier validation;
- file-only delivery;
- structured-data-only delivery;
- successful delivery of all parts;
- each possible partial-success combination;
- malformed structured data;
- empty and oversized files;
- partner
401,403,404,409,413,429, and5xxresponses; - connection timeout and response timeout;
- duplicate submission and idempotency behavior;
- disconnect, reconnect, and token expiry.
Manual acceptance
Perform the following in a real browser against the hosted test environment.
| Scenario | Expected result |
|---|---|
| Correct account | Consent completes and only that user’s resources are returned |
| Consent denied | Partner shows a recoverable cancellation state and stores no tokens |
| Wrong Parkour Design account | Partner shows the signed-in identity and allows a safe restart |
| Existing partner session for another account | Account-switching behavior matches the approved support instructions |
| Back and refresh | No authorization code or state value is accepted twice |
| Duplicate connect click | One browser transaction remains authoritative |
| Concurrent tabs | A callback cannot attach to the wrong local transaction |
| Expired callback | User can restart without stale connection state |
| Expired access token | Partner refreshes once or asks for authorization again |
| Partner or Parkour Design outage | User receives a recoverable message without sensitive diagnostics |
| Disconnect and reconnect | Local tokens are removed and a new identity can be established |
Repeat the core flow in every supported user-interface language. Protocol values must remain unchanged while user-facing messages are localized.
Security review evidence
Provide the reviewers with:
- a data-flow diagram showing browser, both backends, identity provider, APIs, and token storage;
- redirect URI and origin allowlists;
- requested scopes and resource mapping;
- token encryption and retention configuration;
- ID-token validation configuration;
- sanitized examples of logs and alerts;
- dependency and secret-scanning results;
- automated test results;
- completed manual acceptance record;
- credential rotation and incident procedures.
Never attach live codes, tokens, client secrets, private keys, raw UserInfo responses, or customer payloads as evidence.
Observability
Record enough information to diagnose failures without recording credentials or personal data:
- correlation ID generated by the partner;
- environment and integration direction;
- operation name;
- upstream endpoint category, not query parameters;
- HTTP status and safe OAuth error code;
- duration and retry count;
- sanitized resource count when operationally useful.
Do not log authorization codes, access tokens, refresh tokens, ID tokens, client secrets, state, nonce, PKCE verifier, full redirect URLs, email addresses, or course-design payloads.
Alerts should distinguish authentication failures, authorization failures, partner outages, latency, schema errors, and sustained rate limiting.
Production readiness
Before production credentials are issued, both teams must approve:
- exact production issuer and redirect URI;
- client authentication and credential owner;
- scopes and accessible resources;
- expected volume and current API limits;
- privacy, retention, unlinking, and deletion behavior;
- timeout, retry, idempotency, and partial-success rules;
- monitoring and incident escalation;
- user-facing support instructions;
- rollback or integration-disable procedure;
- production smoke-test window and owner.
Use different client credentials for test and production. Deliver them through the approved secret channel and verify rotation before launch.
Production smoke test
Keep the first production test narrow:
- authorize one approved internal account;
- validate the ID token and retrieve UserInfo;
- request the Event list;
- request one known Event’s design summaries;
- verify user isolation and expected fields;
- refresh once and persist the replacement token;
- disconnect and remove locally stored credentials;
- inspect sanitized logs and alerts;
- record the result and decide whether to enable broader access.
Do not test destructive or high-volume behavior in production unless it is explicitly part of the approved launch procedure.
Acceptance record
For every scenario, record:
- environment and build version;
- test owner and date;
- anonymized fixture identity;
- expected result;
- actual result;
- evidence location;
- defect or accepted limitation;
- approval owner.
An undocumented limitation is not an accepted limitation. Add unresolved contract or security issues to the launch decision before enabling production access.