Skip to content

Writing Authentication Procedures

Write custom authentication procedures to define the steps your application needs and combine browser actions with HTTP requests.

A procedure is a sequence of operations to execute against an application, that aims at generating variables to be reused later on to build a user's authentication credentials.

A procedure can include HTTP requests, browser actions, or a combination of both.

A procedure is defined as a JSON object, with the following properties:

  • name: the name of the procedure, used to reference it later on within the configuration file. It must be unique across procedures.
  • operations: an array of operations to execute, in order. Each operation must include a tech property, indicating the type of operation to execute. The operation's tech value determines its configuration structure.

The customer-facing tech values are http, oauth_authz_code_browser, browser_agent, and browser_actions. See the Authentication Reference for each operation's parameters.

It consists of an array of operations. An operation is a single action to execute, like an HTTP request or a browser actions sequence. It also declares how to extract variables from the response of the operation, if any. These variables can then be reused later on to declare users.

Combining Operations

Combine operations of different types within a procedure. For example, an OIDC authorization code flow can use these steps:

  1. Declare a browser actions operation to navigate to the authentication portal of the OIDC server and retrieve an authorization code
  2. Use an HTTP request to trade the retrieved token for an access token and a refresh token.

Understanding Injections and Extractions

Extractions are crucial for deriving variables from the responses of operations. These variables are then available for use in subsequent steps of the procedure. The extraction process involves specifying the location (such as the body or header of a response) and the key for the data to be extracted, and the potential regex to extract specific data within the key.

Injections are used to incorporate extracted variables into the final credentials generated for the user. This process involves specifying the location (such as a header or cookie), the key where the variable should be inserted, and the potential prefix of the token.

HTTP extractions and injections support body, header, cookie, and query. Browser locations are browser_cookies, browser_local_storage, browser_session_storage, and page. A page extraction uses a Playwright selector; browser storage and cookie extractions also specify an origin.

Multiple Variables

Note that if necessary, multiple variables can be injected at the end of the procedure.

Templating in Procedures

Escape's authentication procedures support Jinja templating, allowing the injection of extracted variables into subsequent operations. This templating feature includes all standard Jinja functions, plus the ability to base64 encode values.

Example 1: Token-Based Authentication with HTTP Requests

Use the cURL Sequence Preset for Sequential HTTP Requests

Use the cURL Sequence preset to configure sequential HTTP requests. The custom procedure below shows how operations, extractions, and injections work together.

procedures:
  # (1)
  - name: token-auth-procedure  # (2)
    operations:
      # (3)
      - tech: http
        parameters:
          url: "https://api.example.com/auth/login"  # (4)
          method: POST
          headers:
            - name: Content-Type
              values:
                - application/json
          body: '{"username": "{{ username }}", "password": "{{ password }}"}'  # (5)
        extractions:
          # (6)
          - name: session_token
            location: body
            key: token
          - name: user_id
            location: body
            key: userId
      # (7)
      - tech: http
        parameters:
          url: "https://api.example.com/auth/refresh"
          method: POST
          headers:
            - name: Content-Type
              values:
                - application/json
            - name: X-User-ID
              values:
                - "{{ user_id }}"  # (8)
          body: '{"token": "{{ session_token }}"}'
        extractions:
          - name: access_token
            location: body
            key: accessToken  # (9)
    injections:
      # (10)
      - location: header
        key: Authorization
        prefix: "Bearer "
        variable: access_token
users:
  # (11)
  - name: regular_user
    credentials:
      username: test.user@example.com  # (12)
      password: SecurePassword123!
    procedure: token-auth-procedure  # (13)
  - name: admin_user
    credentials:
      username: admin@example.com
      password: AdminPass456!
    procedure: token-auth-procedure
  1. This authentication procedure demonstrates a common token-based authentication flow with two sequential HTTP requests.
  2. The procedure name token-auth-procedure must be unique across all procedures in the configuration file, as it will be referenced when declaring users.
  3. The first operation is an HTTP POST request to a login endpoint. Each operation in a procedure is executed in the order it appears.
  4. For HTTP requests (with tech set to http), the parameters are url, method, headers, cookies, body, queryParameters, timeout, insecure, follow_redirects, and proxy_override. Only url is required; method defaults to POST. Put user credentials in the user's credentials block and reference them through templates.
  5. The request body uses Jinja templating to inject user credentials. The username and password variables will be automatically provided from the user's credentials defined later in the configuration.
  6. After each operation, you can define extractions to capture data from the response. Here, we extract both a session_token and a user_id from the JSON response body. For HTTP operations, location can be body, header, cookie, or query, and key specifies which field to extract.
  7. The second operation makes another HTTP request, this time to refresh or upgrade the token. This demonstrates how operations can be chained together in a sequence.
  8. Variables extracted in previous operations can be reused in subsequent requests using the Jinja template syntax {{ variable_name }}. Here, we inject the user_id as a header and the session_token in the request body.
  9. The final access token is extracted from the second response and stored in the access_token variable, which will be used for authentication in all subsequent API requests during the scan.
  10. The injections section defines how the extracted variables should be injected into authenticated requests. This example adds the access token as an Authorization header with a Bearer prefix. Multiple injections can be defined if needed (for example, injecting tokens into both headers and cookies).
  11. Users are defined separately from procedures, allowing you to create multiple test users with different credentials, all using the same authentication workflow.
  12. Each user specifies their credentials, which will be injected into the procedure at runtime. The credential fields must match the template variables used in the procedure (in this case, username and password).
  13. The procedure field links each user to their authentication workflow. Multiple users can share the same procedure but with different credentials, which is useful for testing role-based access control (RBAC).

Example 2: OAuth Authorization Code Flow with Browser Actions

Use the OAuth Authorization Code Preset for Standard Flows

Use the OAuth Authorization Code preset to configure this flow directly. The custom procedure below shows how to combine browser actions with HTTP requests.

procedures:
  # (1)
  - name: browser_oauth  # (2)
    operations:
      - tech: browser_actions  # (3)
        parameters:
          login_url: https://oauth.example.com/authorize?client_id=your-client-id&redirect_uri=https://httpbin.tools.escape.tech/get&scope=oauth
          logged_in_detector_text: code  # (4)
          logged_in_detector_timeout: 10
          stealth_mode: false
        extractions:
          # (5)
          - location: page
            origin: https://httpbin.tools.escape.tech/get
            key: body
            name: authorization_code
            regex: '"code": "([\w\d-]+)"'
      # (6)
      - tech: http
        parameters:
          url: https://api.example.com/oauth/v1/token  # (7)
          method: POST
          headers:
            - name: Content-Type
              values:
                - application/x-www-form-urlencoded
          cookies: []
          queryParameters: []
          body: grant_type=authorization_code&client_id=your-client-id&client_secret=your-client-secret&redirect_uri=https://httpbin.tools.escape.tech/get&code={{authorization_code}}  # (8)
        extractions:
          - location: body
            key: access_token
            name: access_token  # (9)
    injections:
      # (10)
      - location: header
        key: Authorization
        prefix: "Bearer "
        variable: access_token
users:
  # (11)
  - name: user1
    credentials:
      username: user@example.com
      password: SecureP@ssw0rd123
      actions:
        # (12)
        - action: goto
          url: https://oauth.example.com/authorize?client_id=your-client-id&redirect_uri=https://httpbin.tools.escape.tech/get&scope=oauth
        - action: click
          locator: button[data-test-id="login-button"]
        - action: fill
          locator: input[data-test-id="email-input-field"]
          value: user@example.com
        - action: click
          locator: button[data-test-id="password-login-button"]
        - action: fill
          locator: input[data-test-id="password-input-field"]
          value: SecureP@ssw0rd123
        - action: click
          locator: button[data-test-id="password-login-button"]
        - action: goto
          url: https://oauth.example.com/authorize?client_id=your-client-id&redirect_uri=https://httpbin.tools.escape.tech/get&scope=oauth
    procedure: browser_oauth  # (13)
  1. This procedure combines browser automation with HTTP requests to implement a complete OAuth 2.0 Authorization Code flow.
  2. The procedure name browser_oauth uniquely identifies this workflow and will be referenced in the user configuration.
  3. The browser_actions tech automates browser navigation for interactive OAuth login flows.
  4. The logged_in_detector_text parameter specifies text that should appear on the page to confirm successful authentication. Here, we wait for the word "code" to appear after the OAuth redirect, indicating we've received an authorization code.
  5. After the browser operation completes, we extract the authorization code from the redirect URL's response body using a regex pattern. This code is stored in the authorization_code variable.
  6. The second operation is a standard HTTP request to exchange the authorization code for an access token.
  7. The token endpoint URL is specific to your OAuth provider. This is where you'll receive the access token in exchange for the authorization code.
  8. The request body includes all required OAuth parameters, with the authorization code being injected via templating: {{authorization_code}}. The grant_type is set to authorization_code per the OAuth 2.0 specification.
  9. The access token is extracted from the response body and stored in the access_token variable for later injection.
  10. The injections section defines how the extracted access token should be injected into subsequent authenticated requests. Here, it will be added as an Authorization header with the Bearer prefix (including a trailing space).
  11. Users are defined separately, allowing you to declare multiple test users with different credentials, all using the same procedure.
  12. The actions array defines the sequence of browser interactions needed to complete the OAuth login flow. These actions include navigation, clicking buttons, and filling form fields. This is where the actual user credentials are used to log in through the OAuth provider's interface.
  13. Each user references the procedure they should use, linking the credentials to the authentication workflow.