Skip to content

Instantly share code, notes, and snippets.

@martindrapeau
Created November 23, 2020 17:00
Show Gist options
  • Save martindrapeau/9ce72154a1ebe780ef79d37d306c1b80 to your computer and use it in GitHub Desktop.
Save martindrapeau/9ce72154a1ebe780ef79d37d306c1b80 to your computer and use it in GitHub Desktop.
Laravel Middleware to verify POST and GET requests from Canva
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
/**
* Class VerifyCanvaRequest.
*/
class VerifyCanvaRequest
{
protected $key;
public function __construct()
{
$secret = env('CANVA_SECRET');
$this->key = base64_decode(strtr($secret, '-_', '+/'));
}
public function handle(Request $request, Closure $next)
{
if ($request->isMethod('post')) $this->verifyPostRequest($request);
if ($request->isMethod('get')) {
if (app()->environment('local') && $request->exists('bypass')) {
// Debug in dev simply pass bypass in query string
return $next($request);
}
$this->verifyGetRequest($request);
}
return $next($request);
}
public function getCanvaPath(Request $request)
{
// Change these to match your endpoints
$paths = [
'api/canva/configuration' => '/configuration',
'api/canva/publish/resources/find' => '/publish/resources/find',
'api/canva/publish/resources/get' => '/publish/resources/get',
'api/canva/publish/resources/upload' => '/publish/resources/upload',
];
$path = $request->path();
foreach ($paths as $pattern => $canva) {
if (strpos($path, $pattern) !== false) return $canva;
}
abort(404);
}
public function verifyPostRequest(Request $request)
{
$version = 'v1';
$timestamp = $request->header('X-Canva-Timestamp');
$path = $this->getCanvaPath($request);
$body = $request->getContent();
$message = "{$version}:{$timestamp}:{$path}:{$body}";
$signatures = $request->header('X-Canva-Signatures');
$signature = hash_hmac('sha256', $message, $this->key, false);
if (strpos($signatures, $signature) === false) abort(401);
if (abs(now()->timestamp - $timestamp) > 300) abort(401);
}
public function verifyGetRequest(Request $request)
{
$version = 'v1';
$timestamp = $request['time'];
$user = $request['user'];
$brand = $request['brand'];
$extensions = $request['extensions'];
$state = $request['state'];
$message = "{$version}:{$timestamp}:{$user}:{$brand}:{$extensions}:{$state}";
$signatures = $request['signatures'];
$signature = hash_hmac('sha256', $message, $this->key, false);
if (strpos($signatures, $signature) === false) abort(401);
if (abs(now()->timestamp - $timestamp) > 300) abort(401);
}
}
@alextreppass
Copy link

Thanks for this Martin!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment