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.
Enrolling a test account
Done once per test account. You do not need a phone, and you do not need an authenticator app.
- In your application, start 2FA enrollment for the test account and choose Set up authenticator app.
- 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.
- 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.
- 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.
| Guard | What happens |
|---|---|
| Never types a dying code | A 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 code | Most 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.
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 see | What it means |
|---|---|
| Step fails naming an unresolvable secret | No 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 code | Usually 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 typing | One 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:
- On your BrowserStack Automate dashboard, open Access Key and copy the username and the access key.
- 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.
| Button | What it does |
|---|---|
| Test connection | Checks the saved key with BrowserStack again, for example after you regenerate it there. |
| Replace key | Saves a new username or key over the old one. |
| Disconnect | Deletes 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.
