Writing authentication procedures¶
In case you did not find a preset suited for your need, you can write your own procedures manually.
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.
Most of the time, a procedure will be a sequence of one or more HTTP requests, but it can also include other types of operations, like a Selenium script mocking a browser navigation, or a request against a GraphQL server.
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 atechproperty, indicating the type of operation to execute. Depending on the type of operation, the configuration structure might vary.
It consists of an array of operations. An operation is a single action to execute, like a request, a Selenium script, or a GraphQL query. 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
Operations of different types can be combined within a procedure! As an example, authenticating against an OIDC server, using an authorization code flow might require you to:
- Declare a Selenium operation to navigate to the authentication portal of the OIDC server and retrieve an authorization code
- 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.
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¶
Consider Using the cURL Sequence Preset
This example demonstrates how to manually build a token-based authentication flow using HTTP requests. However, this pattern can be implemented more simply using Escape's built-in cURL Sequence Preset, which provides a streamlined configuration for sequential HTTP requests. This example is provided for educational purposes to illustrate how procedures, 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
- This authentication procedure demonstrates a common token-based authentication flow with two sequential HTTP requests.
- The procedure name
token-auth-proceduremust be unique across all procedures in the configuration file, as it will be referenced when declaring users. - The first operation is an HTTP POST request to a login endpoint. Each operation in a procedure is executed in the order it appears.
- For HTTP requests (with
techset tohttp), you can configure any HTTP parameter:url,method,headers,cookies,body,queryParameters,username,password, and even aproxy. Onlyurlandmethodare required. - The request body uses Jinja templating to inject user credentials. The
usernameandpasswordvariables will be automatically provided from the user's credentials defined later in the configuration. - After each operation, you can define extractions to capture data from the response. Here, we extract both a
session_tokenand auser_idfrom the JSON response body. Thelocationcan bebody,header, orcookie, and thekeyspecifies which field to extract. - 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.
- Variables extracted in previous operations can be reused in subsequent requests using the Jinja template syntax
{{ variable_name }}. Here, we inject theuser_idas a header and thesession_tokenin the request body. - The final access token is extracted from the second response and stored in the
access_tokenvariable, which will be used for authentication in all subsequent API requests during the scan. - The
injectionssection defines how the extracted variables should be injected into authenticated requests. This example adds the access token as anAuthorizationheader with aBearerprefix. Multiple injections can be defined if needed (e.g., injecting tokens into both headers and cookies). - Users are defined separately from procedures, allowing you to create multiple test users with different credentials, all using the same authentication workflow.
- 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,
usernameandpassword). - The
procedurefield 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¶
Consider Using the OAuth2 Auth Code Flow Preset
This example demonstrates how to manually implement an OAuth 2.0 Authorization Code flow using browser actions. However, this can be done directly using Escape's built-in OAuth2 Auth Code flow preset, which is simpler and more maintainable. This example is provided for documentation purposes to illustrate advanced workflow combinations.
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)
- This procedure combines browser automation with HTTP requests to implement a complete OAuth 2.0 Authorization Code flow.
- The procedure name
browser_oauthuniquely identifies this workflow and will be referenced in the user configuration. - The
browser_actionstech allows automated browser navigation to handle interactive OAuth login flows that cannot be performed via pure HTTP requests. - The
logged_in_detector_textparameter 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. - 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_codevariable. - The second operation is a standard HTTP request to exchange the authorization code for an access token.
- 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.
- The request body includes all required OAuth parameters, with the authorization code being injected via templating:
{{authorization_code}}. Thegrant_typeis set toauthorization_codeper the OAuth 2.0 specification. - The access token is extracted from the response body and stored in the
access_tokenvariable for later injection. - The
injectionssection defines how the extracted access token should be injected into subsequent authenticated requests. Here, it will be added as anAuthorizationheader with theBearerprefix (including a trailing space). - Users are defined separately, allowing you to declare multiple test users with different credentials, all using the same procedure.
- The
actionsarray 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. - Each user references the procedure they should use, linking the credentials to the authentication workflow.