Using WSSE

You can get your integration credentials from your profile in Penneo here:

Once you have them, you're almost ready to start sending requests.
Before you do, you have to generate a new set of authentication headers for every API request that you make.

The header looks like this:

X-WSSE: UsernameToken Username="_your_key_", PasswordDigest="_digest_", Nonce="_nonce_", Created="2015-10-19T10:22:35Z"

It contains your username, a calculated Password Digest, a nonce, and the timestamp at which the digest was created.

Requirements for the nonce
You'll need to calculate the value used for PasswordDigest. In order to do that, you'll need to create a nonce. The nonce can be any random string with the following requirements:

  • It should be unique for every request
  • It needs to be a string not longer than 64 chars

Generating the headers

Here are some examples of how you can generate the authentication headers using WSSE:

function generateHeaders($api_key, $api_secret) {
    $rawNonce = random_bytes(8);
    $nonce = base64_encode($rawNonce);

    $created = gmdate("Y-m-d\\TH:i:s.v\\Z");

    $digest = base64_encode(
        sha1($rawNonce . $created . $api_secret, true)
    );

    return [
        "Authorization: WSSE profile=\"UsernameToken\"",
        "X-WSSE: UsernameToken Username=\"{$api_key}\", PasswordDigest=\"{$digest}\", Nonce=\"{$nonce}\", Created=\"{$created}\"",
        "Accept: application/json",
        "Content-Type: application/json",
    ];
}
def generate_headers(key, secret):
    timestamp = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
    nonce = generate_nonce()
    digest = '{}{}{}'.format(base64.b64decode(nonce).decode('utf-8'), timestamp, secret)
    hashed_digest = hashlib.sha1(bytes(digest, 'utf-8')).digest()
    encoded_hashed_digest = base64.b64encode(hashed_digest).decode('utf-8')

    username_token = 'UsernameToken Username="{}", PasswordDigest="{}", Nonce="{}", Created="{}"'.format(key, encoded_hashed_digest, nonce, timestamp)

    headers = {
        'Authorization': 'WSSE profile="UsernameToken"',
        'X-WSSE': username_token,
        'Accept-charset': 'utf-8',
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }

    return headers
// Have look here:
// https://github.com/Penneo/sdk-net/blob/df7e1d523570b189147039e6555044a64826ed58/Src/Penneo/Connector/WSSEAuthenticator.cs#L49
// @see: https://www.npmjs.com/package/wsse
const { UsernameToken } = require('wsse');

// Generates headers to be used in every authenticated request
function generateHeaders(key, secret) {
    const token = new UsernameToken({
        username: key,
        password: secret
    });
    return {
        'Authorization': 'WSSE profile="UsernameToken"',
        'X-WSSE': 'UsernameToken ' + token.getWSSEHeader({nonceBase64: true}),
        'Accept-charset':  'utf-8',
        "Accept":  'application/json',
        'Content-Type': 'application/json'
    };
};

/*
    Example

    request.get('api/v1/casefiles', {
        headers: generateHeaders('myAPIKey', 'myAPISecret')
    });
*/