Revyl Documentation

Runtime / Mobile

Auth bypass deep links

Use launch variables and deep links to reach authenticated app states in test builds

Auth bypass deep links let Revyl start a test from a signed-in app state without automating every login screen.

The easiest implementation is:

  1. Add a test-only deep link handler in your app.
  2. Gate that handler with Revyl launch variables.
  3. Open one deep link from revyl device navigate or a YAML navigate step.

Only enable this in simulator, staging, debug, or explicit test builds. Do not ship a permanent auth bypass in production.

Set up with an agent

Paste one prompt and your coding agent does the rest.

Setup prompt

Add a test-only auth bypass deep link to this app, so Revyl sessions can start signed in.

Read https://docs.revyl.com/devices/auth-bypass.md and follow it. It's the current Revyl guide for this, so prefer it over anything you remember about Revyl.

Install the `revyl-cli-auth-bypass` skill for this agent and follow it. Gate the link with the `REVYL_AUTH_BYPASS_ENABLED` and `REVYL_AUTH_BYPASS_TOKEN` launch variables, keep it out of production builds, and never commit a real token.

You're done when every check in the page's What To Verify section passes.

Ask me before anything that needs my login or approval.

Fastest Path For Expo Cloud Agents

Use this path when you already run an Expo development client through revyl dev.

npx expo start --tunnel --dev-client

revyl dev --no-build --tunnel "<expo-dev-client-link>" \
  --launch-var REVYL_AUTH_BYPASS_ENABLED \
  --launch-var REVYL_AUTH_BYPASS_TOKEN

revyl device navigate \
  --url "myapp://revyl-auth?token=$REVYL_AUTH_BYPASS_TOKEN&role=buyer&redirect=%2Fcheckout"

Load the Expo dev client project first, then send the app-specific auth deep link. In managed Expo apps, JavaScript may not automatically see native launch values; use a small native config bridge, verify the token with a staging backend, or use a local demo fallback for sample apps only.

Copy This Contract

Use one route shape across every framework:

myapp://revyl-auth?token=<token>&role=<role>&redirect=<allowlisted-route>

Create these launch variables:

revyl global launch-var create REVYL_AUTH_BYPASS_ENABLED=true
revyl global launch-var create REVYL_AUTH_BYPASS_TOKEN=revyl-demo-token --secret

Then start a device with the variables attached and open the bypass link:

revyl device start \
  --platform ios \
  --launch-var REVYL_AUTH_BYPASS_ENABLED \
  --launch-var REVYL_AUTH_BYPASS_TOKEN

revyl device navigate \
  --url "myapp://revyl-auth?token=revyl-demo-token&role=buyer&redirect=%2Fcheckout"

Use the same URL in YAML tests:

test:
  metadata:
    name: "Auth bypass to checkout"
    platform: ios

  build:
    name: "Shopping App"

  env_vars:
    - REVYL_AUTH_BYPASS_ENABLED
    - REVYL_AUTH_BYPASS_TOKEN

  variables:
    auth_bypass_token: revyl-demo-token

  blocks:
    - type: manual
      step_type: navigate
      step_description: "myapp://revyl-auth?token={{auth_bypass_token}}&role=buyer&redirect=%2Fcheckout"

    - type: validation
      step_description: "The checkout screen is visible and the user is signed in"

App Checklist

Your app owns four small pieces:

  • Read REVYL_AUTH_BYPASS_ENABLED and REVYL_AUTH_BYPASS_TOKEN at app launch.
  • Register a handler for myapp://revyl-auth.
  • Verify the token, role, and redirect before changing app state.
  • Create a test-only session and route only to an allowlisted destination.

Invalid links should fail visibly in test builds. Show a debug banner, account-screen status, toast, or log line that says why the link was rejected.

Framework Recipes

Pick the recipe closest to your app. The session creation and route names are app-specific, but the Revyl contract stays the same.

Mint The Token Per Session

The contract above expects REVYL_AUTH_BYPASS_TOKEN to already exist as an organization launch variable. That works while the token is long-lived, but breaks as soon as it expires or has to be minted per run. Add session.before_script and the CLI mints it for you before every iOS or Android device session. Web (alpha) starts do not run session.before_script; use session.auth_bypass.sign_in for worker-minted Web sign-in, and make sure any data a Web proof needs already exists in the preview environment, for example seeded by the preview's own deploy or a test-login route. For the exact attach order on revyl device start (config discovery, mint → launch env → deep link), see Auth And Session Prep.

session:
  before_script:
    script_path: "./scripts/prepare-test-session.sh"
    timeout_seconds: 120 # optional; defaults to 120
  auth_bypass:
    launch_vars: [REVYL_AUTH_BYPASS_ENABLED, REVYL_AUTH_BYPASS_TOKEN]
    deep_link: "myapp://revyl-auth?token=${REVYL_AUTH_BYPASS_TOKEN}"

session.before_script produces values and session.auth_bypass consumes them.

The script is any executable resolved relative to the Revyl project root (the directory that owns .revyl/) and run with that directory as the working directory. The path may leave the project directory via ../ as long as it stays inside the git worktree. Every KEY=VALUE line it prints on standard output becomes a launch variable for that one session; every other line is ignored, so it can log freely:

#!/usr/bin/env bash
set -euo pipefail

echo "Minting a session token..."   # ignored: not KEY=VALUE
TOKEN="$(curl -fsSL --max-time 20 "$STAGING_URL/test-tokens" | jq -r .token)"

echo "REVYL_AUTH_BYPASS_ENABLED=true"
echo "REVYL_AUTH_BYPASS_TOKEN=$TOKEN"

Because the values belong to the session rather than your organization, concurrent runs never overwrite each other's tokens. That is what makes it safe for several pull requests to prove themselves at the same time.

  • A non-zero exit fails session start. Validating an unprepared app is worse than not validating it, so setup failures are never downgraded to warnings. - A deep link must take all of its ${VAR} placeholders from the script or none of them. Mixing the two sources is rejected before the session starts, because only organization launch variables resolve server-side. - Keep the script executable (chmod +x). Resolve it relative to the Revyl project root; it may leave that directory via ../ but paths outside the git worktree are rejected. - Depend only on credentials already in the environment, such as REVYL_API_KEY. A coding agent running revyl device start in a fresh checkout has no other repository secrets.

The script runs wherever the CLI runs: your machine, your CI, or a coding agent's checkout. It does not run for the preview link in a pull request comment, which has no checkout; that path still reads organization launch variables. Values never appear in CLI output, and revyl dev status reports the produced key names only (the runtime status field remains before_session):

{
  "before_session": {
    "configured": true,
    "script": "./scripts/prepare-test-session.sh",
    "keys": ["REVYL_AUTH_BYPASS_ENABLED", "REVYL_AUTH_BYPASS_TOKEN"],
    "state": "ready"
  }
}

revyl dev auth refresh re-fires the configured deep link; it does not remint before-script values. Launch environment is fixed at session start. If a minted token expired, run revyl dev stop then revyl dev so a fresh mint is applied.

Give Proofs An Account That Can Reach The Change

Auth bypass decides which account a session signs in to. A proof of changes can only exercise the screens that account can reach. A bypass can work and still block the proof when the account is in the wrong state. For example, it may still be in a setup or calibration period, have no data for the changed screens, or have already finished the onboarding a pull request changes.

Use one of these, simplest first:

  • A dedicated proof account. Create a non-production account that already has the data, progress, and permissions your proofs need. Use it only for Revyl sessions, so people and other tests do not change its state.
  • Reset the account when the link signs in. Have the revyl-auth handler call a staging-only endpoint that checks the bypass token, resets or seeds the proof account, and returns its session. For example, the endpoint can finish calibration, add sample data, or clear onboarding.
  • Reset it before the device starts. Add a session.before_script that resets or seeds the account and prints the launch values for that session (see Mint The Token Per Session). The script runs in the proof's checkout with only credentials already in its environment, such as REVYL_API_KEY, so the endpoint it calls cannot need another repository secret.
  • One account per state. Use the contract's role parameter to choose between prepared accounts, for example role=onboarded and role=new-user. Allowlist each role in the handler.

When an iOS or Android proof stops at sign-in, or its account cannot reach the change, the pull request comment adds a collapsed setup section under the proof that links back here.

What To Verify

Before relying on the bypass in a test, confirm each case is visible:

  • Valid token, role, and redirect signs in and routes to the target screen.
  • Wrong token is rejected.
  • Missing or disabled REVYL_AUTH_BYPASS_ENABLED is rejected.
  • Unknown role is rejected.
  • Unknown redirect is rejected.
  • The handler is unavailable in production builds.

Bug Bazaar Sample

The public Bug Bazaar repository is a runnable Expo sample of this pattern:

revyl device navigate \
  --url "bug-bazaar://revyl-auth?token=revyl-demo-token&role=collector&redirect=%2Fcheckout"

The Account tab shows whether the auth bypass link is idle, accepted, or rejected.

Bug Bazaar is a managed Expo sample, so it uses a demo fallback token when no native launch-config bridge is present. Customer apps should wire REVYL_AUTH_BYPASS_TOKEN into native launch config or verify the token with a staging backend.

On this page