Created
November 23, 2020 17:00
-
-
Save martindrapeau/9ce72154a1ebe780ef79d37d306c1b80 to your computer and use it in GitHub Desktop.
Laravel Middleware to verify POST and GET requests from Canva
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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); | |
} | |
} |
Thanks for this Martin!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Laravel Middleware to verify that an HTTP request originated from Canva. Necessary if you build an App on the Canva Apps Marketplace.
If a verification fails for a POST or GET request, the middleware will abort the request and return a 401 not authorized response. Translated from the original JavaScript code on their website. Read the docs to understand the logic.
To use
Kernel.php
, register the middleware. For example:Testing the login page in your local/dev environment
If you require an authentication step and want to test it locally, you can set
&bypass
in the query string. The middleware will bypass verification. Look at the code for details.