DAST browser-based analyzer: Support multi-step login forms ("Keep me signed in" workflow for Azure)
Hello,
The current implementation is not able to handle the default Azure SSO workflow as described [here](https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-users-profile-azure-portal#learn-about-the-stay-signed-in-prompt).
The KMSI workflow requires a **third** interaction as can be seen in Microsoft's workflow description.

Unfortunately there is no way to bypass this by setting a cookie or similar and there also does not seem to be an easy way to extend/script the DAST analyzer to perform the necessary step.
#### current non-working setup
```yaml
include:
template: DAST.gitlab-ci.yml
variables:
DAST_WEBSITE: "https://some-sso-website.com"
DAST_AUTH_URL: "https://some-sso-website.com"
DAST_USERNAME_FIELD: "css:[id=i0116]" # The ID of the AAD "Username" field
DAST_FIRST_SUBMIT_FIELD: "css:[id=idSIButton9]" # The ID of the "Next" Button
DAST_PASSWORD_FIELD: "css:[id=i0118]" # The ID of the AAD "Password" field
DAST_SUBMIT_FIELD: "css:[id=idSIButton9]" # The ID of the "Sign In" Button
DAST_BROWSER_SCAN: "true"
DAST_USERNAME: "some-user"
DAST_PASSWORD: "some-user-password"
DAST_BROWSER_LOG: "auth:debug"
```
### Proposal
It would be great to extend the implementation to allow for the **three-step-login** as defined by Microsoft. An easy solution might be to add `DAST_KMSI_FIELD`. That field could then be assigned to either
- the `Yes`-Button (`css:[id=i0116]`)
- the `No`-Button (`css:[id=idBtn_Back]`)
The proposed `.gitlab-ci.yml` file would then look like this
```yaml
include:
template: DAST.gitlab-ci.yml
variables:
DAST_WEBSITE: "https://some-sso-website.com"
DAST_AUTH_URL: "https://some-sso-website.com"
DAST_USERNAME_FIELD: "css:[id=i0116]" # The ID of the AAD "Username" field
DAST_FIRST_SUBMIT_FIELD: "css:[id=idSIButton9]" # The ID of the "Next" Button
DAST_PASSWORD_FIELD: "css:[id=i0118]" # The ID of the AAD "Password" field
DAST_SUBMIT_FIELD: "css:[id=idSIButton9]" # The ID of the "Sign In" Button
DAST_KMSI_FIELD: "css:[id=idSIButton9]" # The ID of the "Yes" Button
DAST_BROWSER_SCAN: "true"
DAST_USERNAME: "some-user"
DAST_PASSWORD: "some-user-password"
DAST_BROWSER_LOG: "auth:debug"
```
#### Implementation Plan
- `DAST_AFTER_LOGIN_ACTIONS` will be a list of comma separated actions to be executed after login. Example: "click\[on=css:.remember-me\],click\[on=id:stay-signed-in\]" .
- Add new field to configuration
- Add AfterLoginActions \[\]string to tomlAuthConfig (toml_auth_config.go).
- Add AfterLoginActions browserk.LoginAction to AuthDetails (auth.go). Parse (see new point) and assign this property in toml_auth_config.go.
- Parse `DAST_AFTER_LOGIN_ACTIONS`
- In `scanner/auth`, create a new package `actions`. Create a new struct, `LoginAction`.
- In `browserk/auth.go`, create a new interface called `LoginAction`.
- In the `actions` package, create a `ClickAction`. Ensure that the `click[on=xxxx]` can be parsed into a click login action.
- In the `actions` package, create a `LoginActions` (similar to `selector.QuerySelectors`)
- In the `actions` package, create a `parser.go` with a Parse function. Parse should convert a series of login action strings into `actions.LoginActions`, and the Parse function should return `browser.LoginAction` (similar to `scanner/browser/selector/parser.go#Parse`)
- Parse should return an error with an appropriate error message if unable to be parsed.
- If there is no after login steps, Parse should return an empty `actions.LoginActions`. This way, the service that uses the steps won't need to worry about it being nil.
- In `auth.Service.processLoginSteps`, after attempting login and before navigating to about:blank, ask the login actions to execute.
- Cookies recorded during this process should be captured as part of the `AuthContext`
- Add `Execute(loginCtx *browserk.Context, crawler browserk.Crawler, browser browserk.Browser) ([]*browserk.Navigation, error)` to each browserk.LoginAction.
- The click action will need to create a new click navigation (see how `PathToLoginForm` works in `authenticator.LoginFormFinder`). The crawler will process the navigation.
- Update an end-to-end test to use this new field. Avoid writing a new test if possible to minimize the the number of end-to-end tests required to run in CI.
- In DAST
- Add configuration DAST_AFTER_LOGIN_ACTIONS and pass it on to Browserker.
- Upgrade Browserker
#### Out of scope
- The after login action items will not create separate entries on the auth report (please make sure PM is aware of this, we can create a new issue if required)
epic