slack/src/Http/Middleware/CheckSignature.php
2022-08-23 17:48:09 +10:00

71 lines
2.0 KiB
PHP

<?php
namespace Slack\Http\Middleware;
use Carbon\Carbon;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Slack\Base;
class CheckSignature
{
private const LOGKEY = 'MCS';
/**
* Validate a slack request
* by the slack signing secret (not the token)
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request,Closure $next)
{
// Make sure we are not an installation call
if (! in_array($request->path(),config('slack.bypass_routes'))) {
// get the remote sign
$remote_signature = $request->header('X-Slack-Signature');
Log::info(sprintf('%s:Incoming request - check slack SIGNATURE [%s]',static::LOGKEY,$remote_signature),['m'=>__METHOD__]);
// Load the secret, you also can load it from env(YOUR_OWN_SLACK_SECRET)
$secret = config('slack.signing_secret');
$body = $request->getContent();
// Compare timestamp with the local time, according to the slack official documents
// the gap should under 5 minutes
// @codeCoverageIgnoreStart
if (! $timestamp = $request->header('X-Slack-Request-Timestamp')) {
Log::alert(sprintf('%s:No slack timestamp - aborting...',static::LOGKEY),['m'=>__METHOD__]);
return response('',444);
}
if (($x=Carbon::now()->diffInMinutes(Carbon::createFromTimestamp($timestamp))) > 5) {
Log::alert(sprintf('%s:Invalid slack timestamp [%d]',static::LOGKEY,$x),['m'=>__METHOD__]);
return response('',444);
}
// @codeCoverageIgnoreEnd
// generate the string base
$sig_basestring = sprintf('%s:%s:%s',Base::signature_version,$timestamp,$body);
// generate the local sign
$hash = hash_hmac('sha256',$sig_basestring,$secret);
$local_signature = sprintf('%s=%s',Base::signature_version,$hash);
// check two signs, if not match, throw an error
if ($remote_signature !== $local_signature) {
Log::alert(sprintf('%s:Invalid slack signature [%s]',static::LOGKEY,$remote_signature),['m'=>__METHOD__]);
return response('',444);
}
}
return $next($request);
}
}