К основному контенту

Laravel signed routes

Starting with version 5.6.12, Laravel has acquired useful functionality of “signing” routes. Since I decided to cryptography, I decided to thoroughly deal with this feature and tell you how to use it.
Let's see what the official documentation says:
"Laravel allows you to easily create "signed" URLs to named routes. These URLs have a "signature" hash appended to the query string which allows Laravel to verify that the URL has not been modified since it was created. Signed URLs are especially useful for routes that are publicly accessible yet need a layer of protection against URL manipulation."

So, the article consist of such parts:
  • What for?
  • How to use?
  • How does it work?
Examples of using:
  1. You need to send a letter to the user with a simple question and answer yes / no. For example, if he will go to an event. If the user is not authorized on the site - he have to log in, and probably  - he will not do this and you will remain unanswered;
  2. You need to confirm the user's mailbox. The same task - it is necessary to confirm the data without authorization.
Here we come to the aid of signed routes. The user does not have to log in to follow the link, but the link can reliably identify the information transmitted, namely that it has not been changed.
By the way, in Laravel 5.7, on the basis of the subscribed routes, the built-in functionality for confirming the user's email box appeared.

Let us consider in practice the second case. We need, for example, to confirm a user’s mailbox change by sending him a letter to a new mailbox with a confirming link.
Make sure that you have a middleware "signed" in Http / Kernel.php:

protected $routeMiddleware = [
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
];


Create such a route.

use Illuminate\Http\Request;

Route::get('email/{email}/{user}', function ($email, $user) {
    if (! $request->hasValidSignature()) {
        abort(401);
    }
    // Action
})->name('changeEmail')->middleware('signed');


In this case, just we need information about the new email and user id to enter data about the modified mailbox in the database. There can be any route and parameters. The main thing is to add on it the middleware "signed" and the name.
To access our route we generate a link with the data:

use \Illuminate\Support\Facades\URL; 
$url = URL::temporarySignedRoute('changeEmail', now()->addHour(), [ 
    'email' => 'test@test.com',
    'user' => 1 
]);

This link we will put in the letter with the request for confirmation of the box. In this case, we created a temporary link (1 hour) using temporarySignedRoute.
Laravel generates a link of the form:


Now, using this link, if any data in it changes (user id, or some character from the signature, email) Laravel throws an exception Illuminate\Routing\Exceptions\InvalidSignatureException. This protects the application from brute force and data integrity.

If there is no need to limit the duration of the link, then just use signedRoute.

$url = URL::signedRoute 
('changeEmail', [ 
    'email' => 'test@test.com',
    'user' => 1 
]);

And now the section for the most curious or interested in crypto component question.
Actually, the most visual function of this whole system is \Illuminate\Routing\UrlGenerator::signedRoute.
What is the signature?
This is the HMAC hash (sha256) from the route itself (in our case it is “http: //test.local/email/test@test.com/1” + the expiration parameter of the link “?expires = 1563484975” in UNIX timestamp format).
The encryption key is the application's secret key, we generate while creating an application with the key:generate command and which is registered in .env.
Verification of the signature is taken again from the reference (http: //test.local/email/test@test.com/1?expires = 1563484975) of the HMAC hash and its verification with the signature.

That's all the magic!
I hope I was able to communicate clearly how to use the signed routes and how it works :)

Sources:
  1. Getting Started with Signed Routes in Laravel https://laravel-news.com/signed-routes
  2. URL Generation https://laravel.com/docs/5.8/urls#signed-urls
  3. HMAC https://ru.wikipedia.org/wiki/HMAC

Комментарии

  1. Этот комментарий был удален администратором блога.

    ОтветитьУдалить

Отправить комментарий

Популярные сообщения из этого блога

ВОПРОС К ЧИТАТЕЛЯМ

Уважаемые читатели моего блога и просто проходящие мимо! У меня появилась идея заняться созданием уроков по интересующим вас темам. Предпочтительно на C++, но не ограничиваясь ими, я хочу поделиться своими знаниями не только в виде готового кода но и подробными объяснениями что к чему. Прошу вас, если вы имеете идею и хотели бы разобраться в какой-то теме - отпишитесь в комментариях, что было бы вам интересно. Постараюсь помочь. 

7 глава, Лафоре Р

*1. Напишите функцию reversit(), которая переворачивает строку (массив типа char). Используйте цикл for, который меняет местами первый и последний символы, затем следующие и т. д. до предпоследнего. Строка должна пере- даваться в функцию reversit() как аргумент. Напишите программу для выполнения функции reversit(). Программа долж- на принимать строку от пользователя, вызывать функцию reversit(), а за- тем выводить полученный результат. Используйте метод ввода, который позволяет использовать внутренние пробелы. Протестируйте программу на примере фразы «Аргентина манит негра».

6 глава, Лафоре Р

*1. Создайте класс Int, имитирующий стандартный тип int. Единственное поле этого класса должно иметь тип int. Создайте методы, которые будут устанавливать значение поля, равным нулю, инициализировать его целым значением, выводить значение поля на экран и складывать два значения типа Int. Напишите программу, в которой будут созданы три объекта класса Int, два из которых будут инициализированы. Сложите два инициализирован- ных объекта, присвойте результат третьему, а затем отобразите результат на экране.