Platform / Spec2RunAI / User guide / Secrets — testing 2FA-protected accounts

Spec2RunAI user guide · updated 22 October 2026

Secrets — testing 2FA-protected accounts

Two-factor authentication normally stops automated testing dead: the code changes every 30 seconds, so it cannot be written into a test step. Store the account's authenticator key once under Secrets, reference it by name, and the engine types the current code at run time.

Why a literal value cannot work here A password can be typed from a fixed string. An authenticator code cannot — it is derived from the current clock and expires within 30 seconds. Storing yesterday's code is useless, which is why the vault stores the key the code is generated from rather than a code.

Enrolling a test account

Done once per test account. You do not need a phone, and you do not need an authenticator app.

  1. In your application, start 2FA enrollment for the test account and choose Set up authenticator app.
  2. Instead of scanning the QR code, click Can't scan? Enter key manually (wording varies — "enter this text code", "manual entry", "secret key"). Copy the key it shows.
  3. In Test Executor, go to Secrets, give it a short name, paste the key, and press Add secret. Spaces and hyphens are fine — paste it exactly as shown.
  4. A 6-digit code appears with a countdown. Type that into your application's confirmation prompt to finish enrollment.

If the key is mistyped, it is rejected immediately and the offending character is named. That check exists because an invalid key would otherwise produce valid-looking wrong codes, and the resulting sign-in failure looks like an application defect rather than a typo.

Using it in a step

Reference the secret where the code goes. Nothing else about the step changes:

Enter {{secret:meridian-totp}} in the 'Authentication code' field

The quoted 'Authentication code' is still the on-screen label the engine looks for; only the value becomes a token. A full sign-in reads exactly as it would for a person:

1. Navigate to https://portal.example.com
2. Enter claims.tester in the Username field
3. Enter Winter2026! in the Password field
4. Click the Sign in button
5. Enter {{secret:meridian-totp}} in the 'Authentication code' field
6. Click the Verify button

Only the authenticator code comes from the vault — the password is typed from the step, or from a dataset column if you are running the same test across several accounts. The vault stores authenticator keys only.

Escaping follows the same rule as data tokens: to type a literal {{, write {{{{.

Two things the engine does on its own

Both exist because a 30-second credential behaves unlike any other typed value, and both would otherwise surface as intermittent failures with no obvious cause.

GuardWhat happens
Never types a dying codeA code with under 3 seconds left is not used. The engine waits for the next one. A code that expires between the keystroke and the submit is rejected by the application, which looks exactly like a defect in it.
Never replays a used codeMost 2FA implementations reject a code that has already been consumed. If a run signs in twice inside one 30-second window, the engine waits for a fresh code rather than sending the same digits again.

Both appear in the step log with a ⏳ and the reason, so a pause of a few seconds before a sign-in step is expected behavior rather than a hang.

Where the key lives

The key is encrypted before it is stored and is never returned by any screen or API after you save it — not to the Secrets page, not to a report, and not to a local agent machine. Agents receive only the current 6-digit code, computed on the server.

The code is not written to logs either. Run logs show the token and the remaining life with the digits masked:

Secret token: "{{secret:meridian-totp}}" -> ****** [meridian-totp, 24s left]

Step text is never rewritten — only the typed value is substituted. That keeps the step's stored wording stable, so selector memory recipes are reused across runs even though the digits change every 30 seconds.

Evidence screenshots show the code The screenshot taken after the step shows the digits in the field, because it is a picture of your application. Those digits expire within 30 seconds and are of no use afterwards, but be aware of it before sharing a run's evidence outside your team.

Cloud runs and local agents

Behavior is identical either way; the mechanism differs. A cloud run reads and decrypts the key inside Test Executor's own environment. A local agent has no access to the key at all — it asks the platform for a code and receives only that, so no authenticator key is ever present on a machine in your network.

When something goes wrong

What you seeWhat it means
Step fails naming an unresolvable secretNo secret is stored under that name. The literal {{secret:…}} is never typed into your application — it would surface several steps later as an unrelated error.
The application rejects the codeUsually the key does not match the account. Re-enroll from the application's 2FA setup screen and re-add the key. Press Show code and compare against an authenticator app enrolled on the same key to confirm.
"has already been used"The application enforces single-use codes and the run signed in twice in one window. The engine waits for a fresh code; if you see this, the wait was not long enough for that application.
A step pauses for a few seconds before typingOne of the two guards above. Expected, and logged with the reason.

Your BrowserStack account

Runs on real Chrome and Microsoft Edge (see Running tests, step 5) use your organization's own BrowserStack account. Connect it once, at the top of the Secrets page:

  1. On your BrowserStack Automate dashboard, open Access Key and copy the username and the access key.
  2. On the Secrets page, paste both into the BrowserStack card and click Connect.

The username and key are checked with BrowserStack before anything is saved, so a mistyped key is rejected on the spot and nothing is stored. Once connected, the card shows the account, your plan and how many browsers it can run at once.

ButtonWhat it does
Test connectionChecks the saved key with BrowserStack again, for example after you regenerate it there.
Replace keySaves a new username or key over the old one.
DisconnectDeletes the saved key. Runs already in progress are not affected.

The access key is treated like an authenticator key: encrypted when stored, never shown again, and never returned by any screen or API. It is used only by the cloud engine at the moment a run starts. It cannot be referenced as a {{secret:…}} token, and it does not appear in the list of stored secrets.

Runs use your plan's minutes and its number of browsers at once, and each session's video is kept in your BrowserStack account.

Deleting is permanent A stored key cannot be recovered or exported — that is the point of it being write-only. If you delete one, re-enroll from the application's 2FA setup screen to get a fresh key. Steps referencing it fail loudly in the meantime rather than signing in as nobody.
Currently authenticator codes only The vault stores time-based authenticator keys (TOTP), which covers Google Authenticator, Authy, Microsoft Authenticator and most enterprise 2FA. SMS and email codes are not supported, because they arrive out of band rather than being derived from a stored key.
Try it on your own tests

Ten test cases. Untouched. We run them and send the evidence report.