А в чём проблема? Хранить таблицу соответствий логинов и рандомных достаточно длинных идентификаторов. При входе через этот идентификатор создавать сессию пользователя, как если бы пользователь зашёл под своим логином и паролем. Примерно так на сайтах и устроен механизм "запомнить меня". На сайте сделать эндпоинт, который на вход принимает идентификатор по GET, проверяет идентификатор по базе и залогинивает пользователя, если идентификатор соответствует какому-нибудь логину, или выдаёт красивое сообщение об ошибке, что QR-код уже истёк. А библиотек, которые ссылки в QR-код заворачивают, готовых масса, как на стороне бэкенда это можно делать, так и на стороне фронтенда.