# Authentication

### Aurinko Signature Validation Steps

To verify that a request truly came from Aurinko, follow these four steps:

#### 1. Extract the Components

You will need three specific pieces of information from the incoming HTTP request:

* **Timestamp:** The value of the <mark style="color:red;">X-Aurinko-Request-Timestamp</mark> header.
* **Signature:** The value of the <mark style="color:red;">X-Aurinko-Signature</mark> header (this is your target for comparison).
* **Raw Body:** The exact, unparsed byte array of the request body.&#x20;

{% hint style="info" %}
**Note:** Do not use a JSON-deserialized object, as whitespace differences will cause the hash to fail.
{% endhint %}

#### 2. Create the Base String

Concatenate the version, the timestamp, and the raw body using <mark style="color:red;">a colon (:)</mark> as a delimiter.

* **Current Version:** v0
* **Format:** v0:{timestamp}:{raw\_body}

#### 3. Compute the HMAC SHA256 Hash

Using your <mark style="color:red;">Aurinko Signing Secret</mark> as the key, sign the base string created in Step 2.<br>

**Java Example:**

```java
final byte[] signData = org.apache.commons.lang3.ArrayUtils.addAll(
    ("v0:" + timestampSeconds + ":").getBytes(StandardCharsets.UTF_8),
    payloadBytes
);
```

{% hint style="info" %}
Then hash signData using HMAC SHA256 and your Signing Secret
{% endhint %}

#### 4. Compare and Verify

Compare your computed hash against the X-Aurinko-Signature header.

* **Match:** The request is authentic; proceed with processing.
* **Mismatch:** The request is invalid and should be discarded (return a 401 or 403 status).

#### Quick Reference Table

| <h4><strong>Element</strong></h4> | <h4><strong>Source</strong></h4>       |
| --------------------------------- | -------------------------------------- |
| **Version**                       | Static string v0                       |
| **Key**                           | Your unique **Aurinko Signing Secret** |
| **Algorithm**                     | HMAC SHA256                            |
| **Delimiter**                     | Colon :                                |

**Java example:**

```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.ArrayUtils;

public class AurinkoValidator {

    private static final String HMAC_ALGO = "HmacSHA256";
    private static final String VERSION = "v0";

    public boolean isValidRequest(String signingSecret, String timestamp, String headerSignature, byte[] rawBody) {
        try {
            // 1. Prepare the prefix: "v0:timestamp:"
            String prefix = VERSION + ":" + timestamp + ":";
            byte[] prefixBytes = prefix.getBytes(StandardCharsets.UTF_8);

            // 2. Concatenate prefix bytes with raw body bytes
            byte[] dataToSign = ArrayUtils.addAll(prefixBytes, rawBody);

            // 3. Initialize HMAC SHA256 with your Secret
            SecretKeySpec secretKeySpec = new SecretKeySpec(
                signingSecret.getBytes(StandardCharsets.UTF_8), 
                HMAC_ALGO
            );
            Mac mac = Mac.getInstance(HMAC_ALGO);
            mac.init(secretKeySpec);

            // 4. Compute the hash
            byte[] computedHashBytes = mac.doFinal(dataToSign);
            String computedSignature = Hex.encodeHexString(computedHashBytes);

            // 5. Compare computed signature with the header
            // Use MessageDigest.isEqual for a time-constant comparison (prevents timing attacks)
            return java.security.MessageDigest.isEqual(
                computedSignature.getBytes(StandardCharsets.UTF_8),
                headerSignature.getBytes(StandardCharsets.UTF_8)
            );

        } catch (Exception e) {
            // Log the error and reject the request
            return false;
        }
    }
}
```
