> ## Documentation Index
> Fetch the complete documentation index at: https://docs.d0pam1ne.blackhatethicalhacking.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authenticated testing

> Scan the app from behind the login, as a user or admin, and keep the results separate.

Most of what an anonymous scan can reach is the public surface. The findings that matter on a real engagement, broken access control, IDOR, and post-login injection, live behind the login. **Authenticated testing** lets you run the attack tools as a logged-in role, so they reach that surface.

Anonymous is always the default. Authenticated testing is opt-in: nothing changes until you add an identity and pick it with **Run as**.

## Testing identities

A **testing identity** is a login you scan *as*, such as `user` or `admin`. Identities live on their own **Identities** tab in **Project Data**, next to **Credentials**, separate from the credentials your team finds during the engagement.

> [!NOTE]
>
> Testing identities are the sessions you feed into the tools. The credentials vault above them is for loot you discover. They are kept apart on purpose.

Each identity has a name, a role, and a session supplied one of two ways:

* **Paste a header.** Log in once in your own browser, copy the `Cookie` or `Authorization` header, and paste it. This always works, whatever the login flow.
* **Built-in login.** Give the login page URL, a username and a password, and D0pam1ne captures the session for you.

The session and the stored login password are sealed with the vault. A reveal is recorded in the audit log, the same as any secret.

Each row also shows **which app the identity is for**: the page or API endpoint its session was last tested on, with a green dot when the session held there and a red one when the target did not accept it. **Test session** fills it in, and when you paste a header you can set it yourself as **App URL**. Without either, the row shows the identity's login page. Click it to open the app in a new tab.

### Built-in login capture

Click **Capture** on a login identity and D0pam1ne fetches the login page, finds the form, carries any hidden anti-forgery (CSRF) token forward, submits your credentials, and keeps the session. It confirms success against a string you can set (for example, text that only shows when logged in), or falls back to a sensible heuristic.

The built-in login covers ordinary server-rendered form logins. For a JavaScript or single-page-app login that builds its request in the browser, use **Paste a header** instead.

### Authorization

Before you can run as an identity, confirm you are **authorized** to test the application as that role. This is the signed-engagement gate, the same idea as confirming authorization before an attack run.

## Keeping the session fresh

A stored session can read **Active** and still be dead on the target, because web sessions expire on the server where D0pam1ne cannot see it. So each identity row says where its session stands, based on its last **Test session** rather than the stored status alone:

| Shown | Meaning |
| - | - |
| Green dot | The last Test verified the session after it was last captured |
| **Verify before scan** (amber) | The session has not been tested since it was captured |
| **Unconfirmed** (amber) | A Test ran but could not confirm the session, for example because the target was unreachable |
| **Session dead** (red) | The last Test was rejected, or the session is already marked expired |

The **Run as** picker on Recon and Automated Attacks repeats the same warning for the identity you pick, because an authenticated run on a dead session quietly falls back to logged out and crawls nothing behind the login. Test the session against a protected page, or sign in again to re-capture it, right before a scan.

The [Command Center](https://docs.d0pam1ne.blackhatethicalhacking.com/concepts/command-center.md#needs-you-now) raises the same thing across every client: a **Login sessions to check** card in Needs you now counts the dead and unverified sessions on live engagements and lists each one, one click to its project's Identities tab.

## Did the login hold?

A session that was alive at the start can still expire part way through a run. The tools do not stop when that happens: they keep going, and every page answers with the login screen or access denied, so the run still says it ran as **admin** while most of it tested the login page.

So once an authenticated recon or automated attack run ends, D0pam1ne checks whether the login held, two ways:

* It looks at every page the run reached as that identity: a login page title (in English, French, Greek, German, Spanish, Italian or Portuguese), the same title and size as the identity's login page, or a 401, 403 or 440. From when those start to dominate it works out roughly when the session died.
* It makes one read-only request with the stored session, the same single GET that **Test** makes, against the page the identity was already tested on, and only when that page is in scope.

| Shown on the run | Meaning |
| - | - |
| **Logged out about 12 minutes in** (red) | Most pages after that point answered with the login page or access denied, or the session is now rejected. The identity turns **Session dead** and the bell tells you. **Refresh session** opens the Identities tab; then run it again. |
| **The login may have dropped** (amber) | A good share of pages looked logged out. Check the session before trusting what the run did not find. |
| **Login held as admin** (green, next to What this run found) | The pages looked logged in and the session is still accepted. |

**Check again** on the run repeats the check. Unauthenticated runs are not checked. The verdict also goes into the run's [What this run found](https://docs.d0pam1ne.blackhatethicalhacking.com/ai/local-ai.md#what-this-run-found) note.

## Run as

On the **Automated Attacks** launcher, use the **Run as** selector to pick an identity. It stays inert until you add one, and anonymous is always the first choice.

When you run as an identity, its session is added to every attack tool that takes a request header: **nuclei**, **httpx**, **ffuf**, **feroxbuster**, **katana**, **sqlmap**, **ghauri**, **commix**, **sstimap**, **wapiti**, **crlfuzz**, **dalfox** and **wpscan**. The session is only ever added on top of the command that would run anyway, so an anonymous run is exactly as it was before. A tool that takes no per-request header (**nikto**, **testssl**, **nmap** and the like) simply runs unauthenticated, even on an authenticated run.

> [!NOTE]
>
> **Recon** takes the same **Run as** picker (on the Recon start card). Running recon as an identity lets the engine crawl and probe behind the login, so pages, endpoints and parameters that only exist once signed in reach the URL inventory. Run authenticated recon first to map the logged-in surface, then run Automated Attacks as the same identity to test it.

## Authenticated recon

Pick an identity with **Run as** on the Recon start card and the engine adds the session to its web stages: the live-web probe and fingerprint (**httpx**, **nuclei**), the crawler (**katana**), and content and parameter discovery (**ffuf**, **feroxbuster**, **x8**, **arjun**). So the crawler follows links that only appear once signed in, and discovery finds the authenticated endpoints and parameters, all folded into the URL inventory the attack phase then targets.

* **Scope-bound.** The session is only ever sent to in-scope hosts: every tool runs on scope-built target lists, and the crawler is held to the in-scope names and paths.
* **Anonymous stages stay anonymous.** Subdomain enumeration, DNS and port scans send no session; passive URL sources (gau, waybackurls, urlfinder) read third-party archives and get nothing.
* **No self-logout.** The crawler skips logout, sign-out and delete-style links so it never ends its own session.
* The run and its history show which identity it ran as, and the run prints a note naming it.

Anonymous is the default on both Recon and Automated Attacks.

## Separated results

Everything an authenticated run files is tagged with the identity it was found as, and kept apart from anonymous results:

* **Issues** and **Traffic** gain a **Context** filter: Anonymous, or each identity. An authenticated issue also shows an **as `role`** badge in the list.
* An authenticated finding keeps its own dedupe namespace, so the same issue found as `admin` and found anonymously are two findings, never merged.
* Findings stay **external** or **internal** as before. The identity is a separate axis, recording who you were when you found it, not where.
* The report's **What was checked** section notes that the application was tested behind the login, and the roles tested.

## Access-control check (IDOR)

Authenticated recon maps the URLs that exist behind a login. The **access-control check**, at the foot of the **Identities** tab, uses those URLs to find the opposite problem: pages that answer to someone who should not see them.

It works in two halves, like the silent-logout check:

* It gathers the recorded URLs worth a look: the ones with an id in the path or a parameter (such as `/invoice/1043`, `/profile?user=55`), or a page a logged-in run reached. This half reads data already collected and sends nothing to the target.
* On **Check access control** it replays each endpoint, read-only, three ways: as the login that recorded it, as every other authorised login, and with no session. When a second login, or no login, gets back the same page as the owner, that endpoint is a candidate.

Each candidate is filed into **Needs Review** as *Possible broken access control* (or *IDOR* when another login saw the owner's page), with every request and response kept as evidence.

| Shown | Meaning |
| - | - |
| **reachable with no login** | The same page loaded with no session. The access check is missing or not enforced. |
| **also returned to `role`** | A different authorised login got the owner's page. A likely IDOR if the id can be changed to reach another user's data. |

* **GET only, in scope, read-only.** It never sends anything but GET, never leaves scope, paces itself between requests, and only runs when you press the button.
* **One login is enough for the logged-out half.** The cross-login comparison needs a second authorised login.
* **Dead sessions are labelled, not guessed.** The same login-page check runs on every replay, not just the owner. A cross-login whose session is not live reads **session dead** (a void comparison, re-capture it) instead of a misleading "differs", and a logged-out request that correctly bounces to the login reads **login required**. A dead session never counts as a hit, so it cannot create a false IDOR, and the run lists any login that was not live so you re-capture it.
* **Filed at medium until confirmed.** A hit is filed at medium, not high, because a cross-login match is only a real IDOR when the two logins are **different users with different data**; the same account seeing the same page is expected. A match with no login at all is the stronger signal. Confirm whose data the response holds, then raise or lower the severity.
* **Never verified.** The check compares responses; it does not know whose data is shown. It always leaves the finding in Needs Review for you to confirm by hand.
* **You choose the logins, and watch it live.** Tick which authorised logins to test as before you start. While it runs, a live request log, a real table with the method, path, who it ran as, the role, the status code and whether the page came back the same, shows each GET as it is sent, like a proxy, with the rows that answered the same highlighted.
* **Summarize and export the run.** When the check finishes, **AI summarize** writes a short, plain-language read-out of what it found from the local AI, grounded in the run's own facts. **Export** hands you the whole run as JSON, CSV, Markdown, HTML or PDF, named after the client and date, carrying every request sent and the findings filed with their full request and response evidence.

## Safety

Running as an identity requires that identity to be authorized and to have a session. The normal, anonymous flow is never altered by any of this: the auth header is added to a command, never woven into it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.