Skip to content

Verifying the Untis Platform Identity

Every request the Untis Platform sends to your webhook endpoints is signed with an RSA private key. Your application must verify the signature before trusting or acting on the payload.

Verification is a hard requirement — never skip it, even in development. Your webhook endpoints receive credentials and lifecycle events for your tenants. A forged or replayed request that bypasses verification can cause data loss or credential exposure.

  1. The Untis Platform computes an RSA signature over the raw request body bytes.
  2. The signature is base64-encoded and included in the Authorization request header.
  3. The algorithm name is included in the Algorithm request header (e.g. SHA256withRSA).
  4. You verify the signature using the Untis Platform public key for your environment.
HeaderValue
AuthorizationBase64-encoded RSA signature over the raw request body
AlgorithmThe signing algorithm used, e.g. SHA256withRSA
Content-Typeapplication/json; charset=utf-8

The public keys are environment-specific. Both are X.509 SubjectPublicKeyInfo format, base64-encoded without PEM headers. Treat them as configuration values — do not hardcode them directly in your application logic.

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxmHgTa7Qf4buurWraH9MqcEipr4YrMpIg1NVbV7sx2p1yhZ5HQ5hPfsuRRqk9ss7UYJS4dnTsjLCwJ1j91PmxZBnceSkgjHunZ53AxsQP7h/A8g3igbi+tRw6+9agyM8zRLeAaufQFvm6/81obezB54vjv1qPGXgX07cmgj2w2EMC39Q4S0eKVU8svjw3QTE0ZD7Gc92T+rMIhVrX5sAKviczs8VSA8CZnM7PDASZ/kjZF9umMfEzmxGm5BVCqMqpCTFh3CMljMmoH3lCro3r9Ve2Unl5Cc8wRJekSOIbpKJ54eVL6zwEExfPlTKQZslLKBhaNtquLJJkgV057ANDwIDAQAB
  1. Read the raw request body as bytes before any parsing.

  2. Extract the Authorization and Algorithm headers.

  3. Base64-decode the Authorization header value to get the signature bytes.

  4. Load the public key for your environment (X.509 DER format, base64-decoded).

  5. Initialise an RSA signature verifier with the algorithm from the Algorithm header.

  6. Feed it the raw request body bytes.

  7. Verify the decoded signature against the body.

  8. Reject with 401 if verification fails. Process the payload only if verification succeeds.

sequenceDiagram
    autonumber
    participant WU as Untis Platform
    participant YA as Your App

    WU->>YA: POST /webhook (Authorization + Algorithm headers)
    alt RSA signature valid
        YA-->>WU: 200 OK
        YA->>YA: Process payload
    else RSA signature invalid
        YA-->>WU: 401 Unauthorized
    end
@PostMapping("/credentials")
public ResponseEntity<?> receiveCredentials(
@RequestBody String request,
@RequestHeader("Authorization") String requestSignature,
@RequestHeader("Algorithm") String algorithm
) throws Exception {
// Load public key
byte[] decoded = Base64.getDecoder().decode(PUBLIC_KEY_STRING.getBytes());
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = kf.generatePublic(spec);
// Verify signature
Signature signature = Signature.getInstance(algorithm);
signature.initVerify(publicKey);
signature.update(request.getBytes(StandardCharsets.UTF_8));
byte[] decodedSignature = Base64.getDecoder()
.decode(requestSignature.getBytes(StandardCharsets.UTF_8));
if (!signature.verify(decodedSignature)) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid signature");
}
// Parse payload only after successful verification
ObjectMapper mapper = new ObjectMapper();
CredentialsPayload payload = mapper.readValue(request, CredentialsPayload.class);
// ... handle payload
}

The platform-initiated webhooks do not currently include a request timestamp or nonce. As a baseline precaution:

  • Process deactivation and credentials events idempotently — handling the same event twice should produce the same result as handling it once (see each webhook’s handling requirements).
  • If you build additional infrastructure around webhook endpoints (e.g. an event queue), track and deduplicate event IDs where available.