ПРИМЕЧАНИЕ. У меня было 4 награды на этот вопрос, но ни один из приведенных ниже ответов не является ответом, необходимым для этого вопроса. Все необходимое находится в обновлении 3 ниже, просто ищу код Laravel для реализации.
ОБНОВЛЕНИЕ 3: Эта блок-схема представляет собой точно поток, который я пытаюсь выполнить, все, что ниже, является исходным вопросом с некоторыми более старыми обновлениями. Эта блок-схема суммирует все необходимое.
Зеленые части на блок-схеме ниже - это те части, которые я умею делать. Красные части вместе с их боковыми примечаниями - это то, что я ищу помощи при использовании кода Laravel.
Я провел много исследований, но информация всегда заканчивалась короткой и неполной, когда дело дошло до использования Laravel с JWT httponly cookie для самопотребляющего API (большинство онлайн-руководств показывают, что JWT хранится только в локальном хранилище, что не очень безопасно ). Похоже, что httponly cookie, содержащий JWT by Passport, должен использоваться для идентификации пользователя на стороне Javascript при отправке с каждым запросом на сервер, чтобы подтвердить, что пользователь является тем, кем они себя называют.
Есть также некоторые дополнительные вещи, которые необходимы, чтобы иметь полное представление о том, как выполнить эту настройку, которые я не встречал в одном руководстве, которое охватывает это:
Я надеюсь, что ответ на этот вопрос послужит простым руководством для будущих читателей и тех, кто в данный момент пытается найти ответ, охватывающий вышеупомянутые пункты о самопотребляющем API.
ОБНОВЛЕНИЕ 1:
CreateFreshApiToken раньше, но это не сработало, когда дело дошло до отзыва токенов пользователя (для пунктов 3 и 4 выше). Это основано на этот комментарий разработчиком ядра laravel, когда речь идет о промежуточном программном обеспечении CreateFreshApiToken:JWT tokens created by this middleware aren't stored anywhere. They can't be revoked or "not exist". They simply provide a way for your api calls to be authed through the laravel_token cookie. It isn't related to access tokens. Also: you normally wouldn't use tokens issued by clients on the same app which issues them. You'd use them in a first or third party app. Either use the middleware or the client issued tokens but not both at the same time.
Таким образом, кажется, что он может обслуживать пункты 3 и 4 для отзыва токенов, это невозможно сделать при использовании промежуточного программного обеспечения CreateFreshApiToken.
Authorization: Bearer <token> не подходит для работы с безопасным файлом cookie httpOnly. Я думаю, что запрос / ответ должен включать безопасный файл cookie httpOnly в качестве заголовка запроса / ответа, например, на основе документов laravel:When using this method of authentication, the default Laravel JavaScript scaffolding instructs Axios to always send the X-CSRF-TOKEN and X-Requested-With headers.
headerswindow.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': (csrf_token goes here)
};
Это также причина, по которой я ищу решение, охватывающее все вышеперечисленные вопросы. Извините, я использую Laravel 5.6, а не 5.5.
ОБНОВЛЕНИЕ 2:
Кажется, комбинация Предоставление пароля / Предоставление токена обновления - лучший вариант. Ищете простое руководство по реализации с использованием комбо Предоставление пароля / Предоставление токена обновления.
Password Grant: This grant is suitable when dealing with the client that we trust, like a mobile app for our own website. In this case, the client sends the user's login credentials to the authorization server and the server directly issues the access token.
Refresh Token Grant: When the server issues an access token, it also sets an expiry for the access token. Refresh token grant is used when we want to refresh the access token once it is expired. In this case, authorization server will send a refresh token while issuing the access token, which can be used to request a new access token.
Я ищу простой в реализации, прямой, целостный ответ с использованием комбинации Предоставление пароля / Предоставление токена обновления, которая охватывает все части вышеперечисленных исходных 5 пунктов с httpOnly secure cookie, создание / отзыв / обновление токенов, создание файлов cookie для входа, отзыв файлов cookie для выхода, контроллер методы, CSRF и др.
@KeitelDOG Спасибо за ваш вклад, но этот пакет идет только до Laravel 5.3, также они превратили его в Passport. Как уже говорилось, я ищу целостный подход / решение / руководство по реализации, которое охватывает все вышеперечисленные моменты.
Я знаю, это то, что я перешел на Паспорт. Passport лучше, и последняя версия может даже управлять отзывом токена пользователя в конкретном клиенте по вашему желанию в пункте 3.
Здравствуйте, в нашем приложении SPA Laravel мы регистрируем пользователя, используя веб-аутентификацию по умолчанию (защита сеанса). Мы также создаем csrf_token и помещаем его в мета перед загрузкой приложения SPA. Выполнив оба действия, мы используем промежуточное ПО CreateFreshApiToken, чтобы определить, нужен ли SPA токен Now или нет. Наконец, используйте токен для аутентификации / авторизации из api. Это то, что вы хотите?
@HilmiErdemKEREN Я добавил обновление о том, почему CreateFreshApiToken у меня не работает. Невозможно отозвать эти токены ... Ищете решение, которое охватывает все вышеперечисленные моменты и хорошо и согласованно работает вместе.
@Wonka дорогой, если вы найдете какое-либо решение для своего вопроса, пожалуйста, добавьте свой ответ здесь, чтобы другие могли реализовать ваше требование ..
@Wonka, я до сих пор не понимаю, почему вы хотите использовать решение без сохранения состояния (аутентификация JWT) в протоколе с отслеживанием состояния (файлы cookie и т. д.)
@ N69S Я использовал JWT и хранил его в локальном хранилище. Когда я узнал о том, что хранение токена в локальном хранилище является уязвимостью хранилища, более безопасным подходом оказалось хранение токена в безопасных файлах cookie только по протоколу http. Это не обязательно должен быть JWT, это просто способ идентифицировать пользователя с помощью файла cookie, но также необходима возможность отозвать токен, если он каким-то образом был украден у пользователя, серверу необходимо знать, какой токен (-ы) использовать отозвать в зависимости от конкретного пользователя.
Причина, по которой вы должны сохранить токен обновления как файл cookie HttpOnly, заключается в предотвращении атак межсайтового скриптинга (XSS).
@Wonka, поэтому мы больше говорим о файлах cookie сеанса, чем о самой системе JWT. в любом случае, поскольку с помощью токена (любого) вы можете идентифицировать пользователя, вам просто нужно отметить пользователя (например, с помощью атрибута), когда он смог пройти аутентификацию. допустим, вы хотите сбросить все сеансы пользователя; просто установите для этого атрибута значение now, и любой токен, выпущенный до этого времени, станет недействительным. для этого вам может потребоваться объявить свой собственный middleware.
@ N69S здесь файлы cookie не сохраняют состояние. Здесь файлы cookie используются только для хранения значения - это клиентская система, и значение отправляется с каждым запросом. На сервере не поддерживается состояние файла cookie (в отличие от файлов cookie сеанса). Аннулирование или отзыв токенов обычно выполняется сервером аутентификации, и в этом случае он отслеживает все токены в какой-либо базе данных и помечает токены для признания недействительными. Когда клиент / сервер ресурсов обращается к серверу аутентификации для обновления токена (из-за истечения срока действия токена доступа), сервер аутентификации дает отрицательный ответ. В pwd cred grant type auth server и res serv одинаковы
@AtiqUrRehman Мне нужно решение / ответ, а не репутация. У меня уже было 4 награды по этому вопросу, и люди по всему Интернету ищут решение. Это только на SO, по крайней мере, 40 человек проявили интерес, а 10 добавили вопрос в избранное.
Я реализовал решение, о котором вы просили, но вы упустили несколько важных моментов. Однако я отметил этот вопрос, потому что в нем очень много подвопросов. Существует множество подробных инструкций, как это реализовать, например: docs.microsoft.com/en-us/azure/active-directory/develop или aaronparecki.com/oauth-2-simplified.
@GillsoftAB Спасибо, я просмотрел их и подтвердил то, что уже знал. Просто ищу конкретную реализацию кода Laravel, которая охватывает предоставление пароля + интеграцию CSRF для SPA.
Замечу об этом подходе. Заголовки можно легко подделать, и на самом деле можно «позаимствовать» файлы cookie из другого домена. Это верно, даже если используются политика безопасности контента (CSP), XSS и многие другие методы безопасности. Вы предполагаете, что браузер БУДЕТ следовать спецификациям, но я могу сообщить вам, что это просто неверно. Никто не собирается просто передавать вам решение, здесь, в StckOverflow, вы получаете некоторые детали, и кто-то указывает вам правильное направление. Вот почему я дал вам несколько ссылок :) Удачи!
Если ваши клиенты доверяют вам, возможно, вы сохраните токен обновления на стороне сервера (в базе данных и т. д., Где вы можете автоматически обновлять токен обновления перед аннулированием), например никогда не разглашать токен обновления клиенту, первый вход в систему исключен, поскольку первый токен обновления и токен доступа поступают из браузера клиента. Затем вы можете позволить клиентам входить в систему на вашем сервере / api, и вы запрашиваете db, используя хэш их пароля, и отправляете правильный токен доступа, который не является одинаково чувствительным. Это один подход, я использовал много разных подходов.
Вам может показаться это интересным: github.com/neoighodaro-articles/csrf-attacks-laravel
Кто-нибудь когда-нибудь это решал? Много примеров Laravel API + SPA, разделенных, показывает только хранение в localStorage.
Нет ... Не получил ответа на все вопросы ..
На мой взгляд, этот вид аргументов следует рассматривать в официальном документе ... если паспорт стремится быть безопасным способом обработки аутентификации, этот тип сценария должен быть четко объяснен. После нескольких дней исследований я понял, что почти никто не справляется с этим должным образом.






Более подробную информацию вы можете увидеть здесь
http://esbenp.github.io/2017/03/19/modern-rest-api-laravel-part-4/
Спасибо, Алекс, но я уже наткнулся на этот урок. Проблема, с которой я столкнулся, заключается в том, что он говорит: «6. Клиент сохраняет токен доступа в хранилище, например, приложение браузера сохраняет его в localStorage», и я просто пытаюсь автоматически отправить файл cookie обратно, вроде laravel_token работает, но laravel_token не позволяет нам уничтожить в нем jwt. Так что просто пытаюсь заставить его работать только с http cookie, иначе, если кто-то может получить доступ к вашему локальному хранилищу, он может захватить ваш токен доступа, что сделает cookie бесполезным. Также в статье не затрагивается интеграция CSRF.
Да, я понимаю, что вам нужно что-то подобное, это без Laravel Passport, но вы можете увидеть пример, как предотвратить кибератаки
Я надеюсь, что есть более простой способ выполнить 5 пунктов в моем исходном вопросе, используя Laravel 5.5 с Passport, без локального хранилища для вызовов api, просто интеграцию cookie + CSRF. Я думаю, что должен быть лучший / более простой способ достичь этих 5 баллов с помощью Passport и Laravel 5.5. Я оставлю вопрос открытым, надеюсь, мы получим ответ по всем вышеперечисленным вопросам. Я знаю, что многие люди ищут то же самое, но все кажется устаревшим или неполным на 100%, и нет ни одного вопроса источника / руководства / laracast / SO, показывающего, как это сделать правильно / полностью на 100% с L5.5 / Passport .
Я думаю, что это хорошая идея, и вы правы, если хотите, чтобы другие получили полную информацию, которая вам нужна. Я с радостью вам в этом помогу. Спасибо
Я также реализовал в своем проекте паспорт Laravel, и я думаю, что я рассмотрел большинство моментов, о которых вы упомянули в своем вопросе.
Authorization: Bearer <token>).Дайте мне знать, если вам понятны вышеуказанные моменты.
Я добавил обновление, вторая точка в обновлении, как я полагаю, должна отправлять / получать безопасный файл cookie httpOnly с заголовком запроса / ответа, в отличие от Authorization: Bearer <token>. Я также ищу решение, которое охватывает все вышеперечисленные моменты и хорошо и согласованно работает вместе.
В вашем случае вы добавили CreateFreshApiToken, который работает с токеном личного доступа. Вы не можете обновить или отозвать токен личного доступа, он является долгоживущим токеном, но вы можете настроить его срок действия.
В моем третьем варианте использования (украденное устройство) выйдите из учетной записи пользователя с других авторизованных устройств, где они активны / были активны, измените пароль и т. д. Это все случаи, когда сервер приложений должен иметь возможность немедленно отозвать доступ к текущего пользователя, вошедшего в систему, и делают их токены бесполезными. Этот вопрос и планирование решения с этим сценарием меня очень сбивают с толку.
Если пользователь вышел из системы или изменил свой пароль, у вас есть возможность удалить сохраненный токен или установить флаг отозванного как истинный. Если вам нужен полный контроль над своими токенами, я бы посоветовал вам использовать метод предоставления пароля.
Да, я согласен с тем, что метод предоставления пароля должен быть подходящим, но я ищу ответ, который реализует его при рассмотрении использования / реализации 5 баллов исходного вопроса, чтобы нарисовать полное полезное руководство, как вся система будет работать с сервера клиенту обратно на сервер.
Не могли бы вы поделиться кодом по вышеупомянутым пунктам? Можете ли вы интегрировать httpOnly secure cookie для доступа / обновления токена и csrf? Мы пытаемся избежать использования Authorization: Bearer <token> с локальным хранилищем, и вместо этого для запроса / ответа используйте безопасный файл cookie httpOnly с отзывным токеном / csrf.
Спасибо, что вернулись, но я уже много раз читал документы. Я до сих пор не понимаю, как реализовать все части, чтобы все работало вместе, поэтому я задал этот вопрос :) Я и многие другие ищут реализуемое решение, но мне еще предстоит найти одно, охватывающее все аспекты и готов реализовать как гайд.
можете ли вы упомянуть свою версию Laravel и какую базу данных вы используете
Laravel 5.6 / MySQL
Паспорт Laravel JWT
Чтобы использовать эту функцию, вам необходимо отключить сериализацию файлов cookie. В Laravel 5.5 есть проблема с сериализацией / десериализацией значений файлов cookie. Подробнее об этом можно прочитать здесь (https://laravel.com/docs/5.5/upgrade)
Убедись в том, что
у вас есть <meta name = "csrf-token" content = "{{ csrf_token() }}"> в головке шаблона вашего лезвия
axios настроен на использование csrf_token при каждом запросе.
У вас должно быть что-то подобное в resources/assets/js/bootstrap.js
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name = "csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
Важные части:
Laravel\Passport\HasApiTokens к вашей модели Userdriver средства защиты аутентификации api значение passport в вашем config/auth.php.\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, в группу промежуточного ПО web в app/Http/Kernel.phpОбратите внимание, что вы, вероятно, можете пропустить миграцию и создание клиентов.
/login, передав свои учетные данные. Вы можете отправить запрос AJAX или отправить обычную форму.Если запрос входа - AJAX (с использованием axios), данными ответа будет HTML, но вас интересует код состояния.
axios.get(
'/login,
{
email: '[email protected]',
password: 'secret',
},
{
headers: {
'Accept': 'application/json', // set this header to get json validation errors.
},
},
).then(response => {
if (response.status === 200) {
// the cookie was set in browser
// the response.data will be HTML string but I don't think you are interested in that
}
// do something in this case
}).catch(error => {
if (error.response.status === 422) {
// error.response.data is an object containing validation errors
}
// do something in this case
});
При входе в систему сервер находит пользователя по предоставленным учетным данным, генерирует токен на основе информации о пользователе (идентификатор, адрес электронной почты ...) (этот токен нигде не сохраняется) затем сервер возвращает ответ с зашифрованным файлом cookie, который содержит сгенерированный токен.
Предполагая, что у вас есть защищенный маршрут
Route::get('protected', 'SomeController@protected')->middleware('auth:api');
Вы можете сделать вызов ajax, используя axios как обычно. Файлы cookie устанавливаются автоматически.
axios.get('/api/protected')
.then(response => {
// do something with the response
}).catch(error => {
// do something with this case of error
});
Когда сервер получает вызов, он расшифровывает запрос laravel_cookie и получает информацию о пользователе (например, идентификатор, адрес электронной почты ...)
Затем с помощью этой информации о пользователе выполняется поиск в базе данных, чтобы проверить, существует ли пользователь.
Если пользователь найден, то ему разрешен доступ к запрошенному ресурсу.
В противном случае возвращается 401.
Аннулирование токена JWT. Когда вы упоминаете комментарий, вам не о чем беспокоиться, поскольку этот токен нигде не сохраняется на сервере.
Что касается пункта 3, в Laravel 5.6 Auth появился новый метод logoutOtherDevices. Вы можете узнать больше здесь (https://laracasts.com/series/whats-new-in-laravel-5-6/episodes/7)
так как документация очень легкая.
Если вы не можете обновить свою версию Laravel, вы можете проверить, как это сделано в версии 5.6, и создать свою собственную реализацию для версии 5.5.
Пункт 4 из вашего вопроса. Взгляните на контроллеры, найденные в app/Http/Controllers/Auth.
Что касается access_tokens и refresh_tokens, это совершенно другой и более сложный подход. В Интернете можно найти множество руководств, в которых объясняется, как это сделать.
Я надеюсь, что это помогает.
PS. Счастливого Нового года!! :)
Спасибо за ваш ответ; очень важно также рассмотреть пункты 3 и 4 в моем вопросе. Если устройство потеряно или украдено, нам нужно иметь возможность отозвать доступ, например, через изменение пароля, что затем отменит все токены, связанные с устройством (-ами) пользователя. Проблема с CreateFreshApiToken заключается в том, что мы не можем отозвать токены этого пользователя, поэтому утерянное / украденное устройство всегда будет активным без возможности отзыва. Если вы также подумаете о «выходе из системы со всех устройств», необходима такая же функциональность, при которой активный токен (-ы) будет отозван для данного пользователя. Как мы это делаем?
Спасибо за обновление, я стремлюсь к максимальной безопасности с помощью проверки подлинности по паспорту. Кажется, что предоставление пароля с помощью комбинации access_token и refresh_token является рекомендуемым способом. Таким образом, даже администратор приложения может отозвать токены пользователей, чтобы мгновенно сделать их следующий токен запроса бесполезным и вызвать выход из приложения. Беспокойство с вашим подходом заключается в том, что если кто-то схватит токен CreateFreshApiToken другого пользователя, теперь они могут быть им навсегда, верно? Я думаю, что администратор не может отозвать этот токен, поэтому они могут иметь бесконечный доступ. Есть ли способ справиться с этим сценарием?
С Новым годом :) Есть идеи по поводу моего последнего комментария?
Привет @Wonka! Извините за медленный ответ. Я не уверен, что понимаю ваши требования. Вам нужен поток, который использует какое-то разрешение oauth (например, предоставление пароля) вместо JWT? В этом случае, как вы будете хранить идентификатор клиента и секрет клиента в браузере, если у вас больше клиентов?
Допустим, вы аутентифицируете пользователя, и сервер установит refresh_token в файл cookie httpOnly. Как получить к нему доступ, чтобы получить новый access_token? Файлы cookie httpOnly не могут быть прочитаны с помощью JS.
Это в основном одна из основных проблем, но я думаю, что когда сервер после входа в систему отправляет файл cookie httpOnly с токеном доступа в качестве заголовка ответа, он будет передан обратно на сервер с каждым запросом api в качестве заголовка запроса. Серверу необходимо как-то проверить токен, и если срок действия токена истекает / d, он должен каким-то образом выдать / повторно выпустить токен обновления в заголовке ответа без повторного входа в систему. Может через промежуточное ПО, не уверен. Но сервер приложений также должен иметь возможность отзывать токены, скажем, для захваченного токена доступа / обновления учетной записи, чтобы выгнать пользователя, поэтому ему придется снова входить в систему с помощью имени пользователя / пароля.
Допустим, вы достигли своего потока. JS отправляет почтовый запрос в некоторую конечную точку входа, и сервер устанавливает access_token в cookie. ваш клиент будет использовать это для каждого запроса. Когда срок действия access_token истечет, сервер автоматически обновит этот токен. У меня вопрос, насколько это безопасно? Если я получу ваш файл cookie, я всегда могу использовать этот токен, потому что сервер автоматически обновит его. Понимаете мою точку зрения? И где меня путает ваш поток?
Я определенно не эксперт по безопасности, но я думаю, что если у access_token и refresh_token короткий срок действия, ~ 10 минут, может быть, это сделает «украденный» cookie бесполезным? Это мое предположение ... Я надеялся, что кто-то с большим опытом, реализовавший это, предоставит решение, касающееся этого и других вопросов. Ваш подход проще всего реализовать, и я пробовал его раньше, но невозможность отозвать токен (-ы) пользователя не позволяет серверу приложений отозвать доступ для плохого пользователя. Я застрял на этом 3 недели +, и действительно сложно найти решение, которое охватит все.
@Wonka Я не знаю, как вам помочь, потому что я многого не знаю о вашем приложении, но, возможно, эта статья medium.com/lightrail/… даст вам несколько советов.
Извините за то, что вы нашли решение, но вот сценарий, который я действительно пытаюсь решить, и если он работает с вашим решением, то это действительно правильный ответ. Пользователь входит в систему с телефона, вор крадет телефон, поэтому пользователь входит в систему с компьютера и меняет пароль, чтобы вор не мог получить доступ к своей учетной записи на телефоне. Будет ли с этим потоком вора отключаться от телефона? Я просто хочу убедиться, что после того, как пользователь изменит свой пароль, он отключит вора от дальнейшего доступа к украденному устройству.
Я использовал Passport и Oauth2 Луки Десаспери для Laravel. Когда дело доходит до мобильного приложения и Javascript, это небезопасно с типом предоставления пароля. Только поток кода авторизации в порядке. Но токены не должны сохраняться более 2–60 минут или более в зависимости от конфиденциальности данных. Токены Facebook - это 2 минуты + 1 время использования. При использовании типа предоставления кода авторизации браузер запрашивает имя пользователя и пароль и запрашивает разрешение на доступ к вашему приложению или вашему собственному веб-сайту (что вы можете разрешить по умолчанию), а затем отправляет только токен со сроком действия, который обновляет каждый период время