Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

666
Visualizações
How to verify discord endpoint using php?

I am having some issues in creating a Discord bot. I want it to be able to respond to slash commands, but to do so I need to verify an endpoint. I am using PHP 7.4, and can't use any external libraries (hosting on a server that does not allow them). I have found documents for PHP, but they do require libraries to work. I tried taking the documents from Node.JS and "converting" them to PHP. Here's my code:

<?php

$public_key = "shh-it's-a-seekrit";
$headers = getallheaders();
$signature = $headers["X-Signature-Ed25519"];
$timestamp = $headers["X-Signature-Timestamp"];
$raw_body = file_get_contents('php://input');

/* To compute the signature, we need the following
 * 1. Message ($timestamp + $body)
 * 2. $signature
 * 3. $public_key
 * The algorythm is SHA-512
 */
$message = $timestamp . $raw_body;
$hash_signature = hash_hmac('sha512', $message, $public_key);
if (!hash_equals($signature, $hash_signature)) {
    header("HTTP/1.1 401 Unauthorized", true, 401);
    die("Request is not properly authorized!");
}
$return_array = [
    'type' => 1,
];
echo json_encode($return_array);
?>

When I put the address the file is uploaded to and try to save the changes, Discord says the following:

Validation errors: interactions_endpoint_url: The specified interactions endpoint URL could not be verified.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

This is a method that works for me on PHP 8.1.

Pass in the headers and raw JSON body, and it returns an array with the response code and payload to send back through whatever you are using to handle the response. Note the response must be JSON encoded.

$discord_public is the public key from the Discord app.

public function authorize(array $headers, string $body, string $discord_public): array
{
    $res = [
        'code' => 200,
        'payload' => []
    ];

    if (!isset($headers['x-signature-ed25519']) || !isset($headers['x-signature-timestamp'])) {
        $res['code'] = 401;
        return $res;
    }

    $signature = $headers['x-signature-ed25519'];
    $timestamp = $headers['x-signature-timestamp'];

    if (!trim($signature, '0..9A..Fa..f') == '') {
        $res['code'] = 401;
        return $res;
    }

    $message = $timestamp . $body;
    $binary_signature = sodium_hex2bin($signature);
    $binary_key = sodium_hex2bin($discord_public);

    if (!sodium_crypto_sign_verify_detached($binary_signature, $message, $binary_key)) {
        $res['code'] = 401;
        return $res;
    }

    $payload = json_decode($body, true);
    switch ($payload['type']) {
        case 1:
            $res['payload']['type'] = 1;
            break;

        case 2:
            $res['payload']['type'] = 2;
            break;

        default:
            $res['code'] = 400;
            return $res;
    }

    return $res;
}
over 4 years ago · Santiago Trujillo Relatório

0

For completeness, adding the missing code to @Coder1 answer:

<?php

$payload = file_get_contents('php://input');
$result = endpointVerify($_SERVER, $payload, 'discord app public key');
http_response_code($result['code']);
echo json_encode($result['payload']);

function endpointVerify(array $headers, string $payload, string $publicKey): array
{
    if (
        !isset($headers['HTTP_X_SIGNATURE_ED25519'])
        || !isset($headers['HTTP_X_SIGNATURE_TIMESTAMP'])
    )
        return ['code' => 401, 'payload' => null];

    $signature = $headers['HTTP_X_SIGNATURE_ED25519'];
    $timestamp = $headers['HTTP_X_SIGNATURE_TIMESTAMP'];

    if (!trim($signature, '0..9A..Fa..f') == '')
        return ['code' => 401, 'payload' => null];

    $message = $timestamp . $payload;
    $binarySignature = sodium_hex2bin($signature);
    $binaryKey = sodium_hex2bin($publicKey);

    if (!sodium_crypto_sign_verify_detached($binarySignature, $message, $binaryKey))
        return ['code' => 401, 'payload' => null];

    $payload = json_decode($payload, true);
    switch ($payload['type']) {
        case 1:
            return ['code' => 200, 'payload' => ['type' => 1]];
        case 2:
            return ['code' => 200, 'payload' => ['type' => 2]];
        default:
            return ['code' => 400, 'payload' => null];
    }
}
over 4 years ago · Santiago Trujillo Relatório

0

According to Discord documentation, interactions endpoint must do two things:

  • Your endpoint must be prepared to ACK a PING message
  • Your endpoint must be set up to properly handle signature headers--more on that in Security and Authorization

The first part is very simple:

So, to properly ACK the payload, return a 200 response with a payload of type: 1:

Thus, you need to return JSON object and not an array (maybe that's one of the problems with your code).

Additionally, endpoint must be able to respond to invalid requests as:

We will also do automated, routine security checks against your endpoint, including purposefully sending you invalid signatures. If you fail the validation, we will remove your interactions URL in the future and alert you via email and System DM.

One thing I noticed is that Discord sends their headers lowercased! Another problem is that you use:

$raw_body = file_get_contents('php://input'); that doesn't look right.

Finally, if you know node.JS take a look at my working example: https://github.com/iaforek/discord-interactions

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda