Modern web applications, especially single-page applications, are often built upon APIs that serve data to more than just HTML-based web browsers. These applications do not rely on web forms for authentication. Instead, a common approach is to create an API route that accepts a POST request with a JSON payload containing the user’s credentials. The server will then return an authorization token as part of the JSON response. After the initial login, the API expects only the token to be sent on all subsequent requests to protected routes.

Stackhawk’s scanner, HawkScan, supports this scenario by default. Here we will focus on how to define both the username and password fields, values, and payload type for HawkScan. We’ll also add a tokenExtraction section for obtaining the value of the token from the JSON response and a tokenAuthorization section for using the token on all subsequent API calls.

Note: This API is designed to be intentionally minimal for authentication testing purposes only. It is not meant to showcase scan results.

Prerequisites:

You will need accounts with StackHawk and GitHub. You will also need some familiarity with Git, Curl, and Docker. Familiarity with Python and Django is helpful, but not necessary.

You should have the following software installed on your computer.

  • Docker: (download from docker.com)
  • Python 3: (brew install python on MacOS)
  • jq: (‘brew install jq’ on MacOS)

Clone and run hawkling-api

Clone the hawkling-api repository and install the project dependencies outlined in the README.md file.

In your terminal, navigate to the hawklingAPI/hawlingAPI/ directory that contains the manage.py file and run the application.

python manage.py runserver

Visit http://localhost:8000/ in your browser and verify you can access the home path.

Navigating hawkling-api

The hawkling-api contains 3 paths: /, login/, and kaakaww/. The first two routes are publicly available, meaning all the content at each path is freely accessible. The third route, kaakaww/, requires a Bearer token in order to display the greeting message.

If you try to access kaakaww/ without a token, you’ll receive a message asking for credentials. While the message says “credentials,” what it really means is an “Authentication token was not provided.”.

{
	"detail": "Authentication credentials were not provided."
}

First, obtain your access token by POSTing credentials to login/

curl -X POST -H "Content-Type: application/json" \
	-d '{"username":"admin", "password":"adminpassword"}' \
	http://localhost:8000/login/ | jq

A successful post should return a response similar to the following

{
	"refresh": "YyyYYYyYY.YyyYYYyYY",
	"access": "xxxXXXxXXxx.xxxXXXxXXxx"
}

Next use the value of the access token to make a request to kaakaww/

curl -X GET http://localhost:8000/kaakaww/ \
	-H 'Authorization: Bearer xxxXXXxXXxx.xxxXXXxXXxx'

A request with a valid token will yield a friendly greeting

{
	"message": "Hello, Hawkling!"
}

Configure and Run HawkScan

To scan the application, you’ll need to add the stackhawk.yml file to your project directory. Filling out the file is as simple as describing the process we just stepped through using cURL.

authentication:

Most often, when a user interacting with your application will innately understand whether they’re logged-in or logged-out based on context clues. To enable HawkScan to simulate scanning your application as an authorized user, we need to specifically define those clues.

In this case, when I made a request to kaakaww/ without a Bearer token, I noticed the response contained the word “detail”. Likewise, when I made a request to kaakaww/ with a Bearer token, the response changed to include the word “message.” Consequently, “detail” becomes my loggedOutIndicator, and “message” becomes my loggedInIndicator.

usernamePassword:

Knowing that the hawkling-api accepts POST requests and expects a JSON payload, we specify the data expected with, type: JSON, and define the loginPath as login/. Next, we need to tell the scanner the names of the credential fields (usernameField and passwordField) to be defined in the JSON payload. Lastly, we’ll specify the actual values of the usernameField and passwordField as scanUsername and scanPassword. Simply put, these fields recreate our cURL command to login/.

tokenExtraction:

Following the POST request to login/, the API returns a token in the response. type: TOKEN_PATH tells the scanner we’re expecting the token to be located in a JSON payload and value defines the name of the token to be extracted.

tokenAuthorization:

After the scanner has extracted the token, it needs to understand how to use it for making subsequent calls to other API routes. type, value, tokenType all describe how the scanner should use the token, similar to the cURL command we previously made to kaakaww/.

testPath:

Once the token is obtained, path tells HawkScan which route to use to verify authentication is working before running a scan and success gives the scanner an indicator that the request to path was successful.

app:
    applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
    env: Development
    host: http://localhost:8000
    authentication:
      loggedInIndicator: ".*message.*"
      loggedOutIndicator: ".*detail.*"
      usernamePassword:
        type: JSON
        loginPath: /login/
        usernameField: username
        passwordField: password
        scanUsername: admin
        scanPassword: adminpassword
      tokenExtraction:
        type: TOKEN_PATH
        value: "access"
      tokenAuthorization:
        type: HEADER
        value: Authorization
        tokenType: Bearer
      testPath:
        path: /kaakaww/
        success: ".*200.*"

Now that you’ve added the stackhawk.yml file to your project directory, replace the value of applicationId for the corresponding value in the StackHawk web platform.

Lastly, in your terminal, navigate to the directory where you saved the stackhawk.yml file and run the docker command to initiate the scanner!

docker run --rm -v $(pwd):/hawk:rw -it \
  -e API_KEY=hawk.xxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxx \
  stackhawk/hawkscan:latest

Notes

cURL is a great way to orient yourself around your applications. As you become more familiar with how your applications work, configuring HawkScan quickly becomes a walk in the park. If you need more help configuring HawkScanyou can always reach out to support@stackhawk.com. We’re more than happy to help get you up and running!

Adding security testing for authenticated app routes to your development processes ensures complete visibility into any vulnerabilities your application has before they’re found in production by the wrong crowd. If you’d like more information on how to move HawkScan from your local environment to your build pipeline, learn how to use StackHawk with Travis CI and Docker-Compose!