Appearance
Authentication
OwlFlow uses a dual-layered authentication model.
1. Partner Authentication (API Key)
All requests to the production and staging environments require a valid API key provided via the x-api-key header. This is enforced by the Google API Gateway.
http
x-api-key: YOUR_PARTNER_API_KEY2. User Authentication (JWT)
For user-specific operations (viewing profile, applying to scholarships), you must provide a Bearer token obtained from the login or googleAuth mutations.
Obtaining a Token
graphql
mutation Login($input: LoginInput!) {
auth {
login(input: $input) {
token
expiresAt
}
}
}Using the Token
Include the token in the Authorization header of your requests:
http
Authorization: Bearer <your_token_here>Internal Session and Identity Bootstrap
The client contract is unchanged: applications send the OwlFlow JWT as a Bearer token and never send Laravel cookies.
For each authenticated request, OwlFlow:
- verifies the JWT signature and reads its
subaccount id andjtisession id; - resolves the
jtito the existing Laravel session cookie through token storage, backed by Firestore in deployed environments; - uses the feature-flagged Core MySQL repository to bootstrap the account identity when
owlflow-db-account-bootstrapis enabled; - falls back to Core's account-info endpoint when the database is unavailable.
A missing or soft-deleted database account is an authentication failure and does not fall back to Core. Raw Laravel cookie requests continue to validate through Core. The mapped Laravel session cookie is retained for downstream REST and JSON:API calls, so existing Core authorization and session behavior remain unchanged.
GraphQL account reads use the same primary MySQL connection when owlflow-db-account-me is enabled for the authenticated account. The database repository returns profile dictionaries, the top-priority active subscription, its package and status, and linked social accounts. Infrastructure failures fall back to /jsonapi/account/me; missing or soft-deleted accounts do not. Set DB_ACCOUNT_ME_PARITY_LOGGING_ENABLED=true temporarily to compare database and legacy mapped outputs without changing the database-backed response.
Native Registration Auth Compatibility
NATIVE_REGISTRATION_ENABLED is the deployment kill switch and owlflow-native-registration is the Unleash rollout switch. Both must be enabled before Owlflow can use native registration. SD-8872 does not create accounts yet; it lets Owlflow mint the authentication artifacts Core expects after a native registration commit.
The compatibility layer reproduces Core's Laravel session contract:
- Owlflow writes a PHP-serialized web-guard session into Core's session Redis.
- Owlflow encrypts the session id into a Laravel-compatible
sowlcookie using Core'sAPP_KEY,AES-256-CBC, and Laravel's v2 cookie prefix. - Owlflow creates an
account_login_tokenrow and encrypts that token intoreg_auth. - Owlflow stores the
jti -> sowlmapping in persistent token storage and issues the existing JWT. - A resumable
owlflow_registration_operationrow records the post-commit auth issuance state, stable session id, and an expiring issuance lease.
Database transactions only claim or finalize issuance. Redis and Firestore work runs outside row locks and is idempotently retried with the persisted session id and JTI. An ambiguous final commit is resolved by rereading the operation rather than deleting potentially valid authentication artifacts.
Core owns the migration for owlflow_registration_operation; Owlflow only keeps the matching Drizzle schema and repository. Deployed native registration must use durable token storage. In-memory token storage remains local/test only.
Startup validation requires a valid CORE_APP_KEY, JWT secret, primary database, durable token storage, Core session Redis, and a shared cookie domain. Startup also verifies the operation schema and Redis connectivity before serving when the deployment kill switch is enabled. Secret values must be provided through the owlflow-env secret and must not be logged.
