All streams
Search
Write a publication
Pull to refresh
29
36
Максим @franticticktick

Java разработчик

Send message

Спасибо за фидбэк, хорошее замечание. Доступно рассказать про Client-Initiated Backchannel Authentication Flow трудно, но я подумаю как это можно сделать.

По своему опыту скажу вам так - задача перевода банка легаси авторизации на полноценный Oauth 2.0 - это если не героическая задача, то как минимум очень трудная. Нужно идеально знать все технологии безопасности - keycloak, spring authorization server, spring security и т.д. При это обязательно нужна обратная совместимость с легаси авторизацией, чтобы разрабы в панике не правили баги на коленке. Представьте, что будет если 50 млн пользователей разом разлогинит - банк, наверное, не обнищает, но получит самый масштабный коллапс в своей истории.

В общем то она известна, есть на сайте ЦБ, я могу собрать ее и приложить к статье - потери банков в 2018 году 1млрд, начиная с 2019 и далее (как раз когда начали просить код из смс) - 9.7 млрд, 13.5 и т.д. Есть данные от лаборатории касперского - там это связывают с подделками номеров (сейчас уже не очень актуально, т.к. во всех банках есть проверка imsi) и запросом кода из смс. Чуть позже найду и приложу.

Спасибо за фидбэк. Я упоминал в статье про Client-Initiated Backchannel Authentication Flow или CIBA. Это расширение Ouath 2.0 специально для таких случаев. Он довольно сложен в описании, и я решил вынести это за скобки. В keycloak он есть, но проблема в том, что во многих банках используются свои самописные серверы авторизации и такого флоу там просто нет. Да и мало кто про него знает.

Подтверждение операции по смс не так кошмарно, как просить код из смс при общении с клиентом. Это навязывает клиенту плохой шаблон поведения. Неудивительно, что после того, как банки стали так делать количество атак мошенников увеличилось в разы.

Вы правы. Я как человек много лет проработавший в двух крупных банках знаю это не понаслышке. ЦБ знает про Oauth 2.0 и OpenID Connect. В свое время я задал вопрос сотруднику ЦБ, который проводил у нас аудит, если ЦБ настаивает на использовании Ouath 2.0, почему большинство банков игнорируют это требованию. И он ответил, что невозможно сделать это требование жестким, т.к. за давностью лет многие банки технически не могут перейти на Ouath 2.0.

Ок, я уберу свой тг канал. Цель статьи не в этом - цель показать проблему из-за которой случаются массовые случаи фрода до сих пор в 2025 году. К тому же есть ссылки на oauth 2.0 ciba, чтобы понимать как это должно быть на самом деле.

Хорошо, какова будет причина бана? Статья посвящена конкретной проблеме и довольно серьезной, можете аргументировать?

Спасибо за статью, но поправьте, пожалуйста, опечатки типа "В spring security для этого есть эндпоит /logaut "

Спасибо, исправил.

Вопрос, почему BFF на GW, а не в отдельном сервисе? Ведь шлюз для маршрутизации, a BFF, для авторизации.

TokenRelay реализован на шлюзе в виде фильтра. Если использовать еще один bff, то придется уже на нем реализовывать TokenRelay или нечто подобное. К тому же архитектура, в которой bff это и есть шлюз, явно проще.

В application.yaml у вас указан client-secret. Что это за пароль, учитывая, что во время аутентификации вы вводите логин/пароль?

Это секрет oauth 2.0 клиента. Клиенты бывают двух видов - публичные и приватные. У приватных есть секрет, и они считаются более безопасными.

Я бы обратил внимание на пару моментов. Во-первых это не spring boot filter как таковой, а фильтр Java EE. К spring, а тем более к spring boot он никакого отношения не имеет, это часть контейнера сервлетов.

Для создания своего фильтра нужно реализовать интерфейс `javax.servlet.Filter` и переопределить метод `doFilter`.

Уже давно jakarta.servlet.Filter.

А почему бы не обращаться с фронта в кейклок для получения токена, а бэк только валидирует этот токен?

Потому что в таком случае фронт должен быть публичным клиентом и токены будут храниться локально в браузере. А это открывает некоторые векторы атак. Плюс реализация флоу авторизации на бэке гораздо более простая и надежная, чем на фронте.

И еще не понятен мне момент: только шлюз проверяет токен? А как запретить тогда запросы к микросервисам отовсюду, кроме шлюза?

Бэк настроен как ресурс-сервер, т.е. валидация токена и проверка ролей происходит на бэке. Задача шлюза - обеспечить процесс авторизации по флоу, т.е. получения токена, и удержание его в сессии. Валидацию токена шлюз, естественно, выполняет, но проверку ролей. То есть шлюз может выдать 401, не дав заведомо невалидному токену дойти до бэка, а бэк может выдать 403, если у токена недостаточно прав для доступа к ресурсу.

Для ограничения доступа к шлюзу с других клиентов вам нужно сделать свой клиентский скоуп и контролировать его на стороне шлюза. Я не написал про это в этой статье, но про это можно почитать тут.

Как простой пример проектирования rest api статья вполне неплохая, но в реальных продакшн-условиях гораздо проще и эффективнее использовать Spring Data Rest - все, что реализовано в этой статье, там будет умещаться в реализации репозитория, т.е. без кода вообще.

Честно говоря не пойму почему возврат сущностей из БД в rest выдаче для CRUD сервисов - это антипаттерн. CRUD он на то и CRUD - просто набор данных без какой либо логики. Это то, что называется anemic domain model, и я не понимаю какой профит в перегоне одних структур данных в точно такие же, но с DTO в названии.

Не волнуйтесь, по безопасности такой вариант на данный момент - лучшее, что можно сделать:

  • На шлюзе есть csrf токены от межсайтового скриптинга.

  • Аксес и рефреш токены не хранятся на стороне клиента.

  • Запрос не доходит до бэка если есть проблемы с авторизацией, а остается на шлюзе.

В целом, такая архитектура это наиболее безопасный и оптимальный вариант.

Статья вызывает очень много вопросов. Во-первых: а вы уверены, что это именно Oauth 2.0, а не его вольная интерпретация?

  • протокол авторизации oauth 2 (частично)

То, что описано у вас в статье больше похоже на попытку реализации своего Resource Owner Password Credentials, небезопасного и нерекомендуемого к использованию, а Oauth 2.1 так и вовсе запрещённого. Настоящий Oauth 2.0 для веб приложений - это authorization code со всей цепочкой редиректов. Ваша реализация не имеет ничего общего с этим флоу.

Второе: для чего понадобилось делать свой AuthService - без нормальной поддержки Oauth 2.0, безопасных веб-сессий, OIDC и т.д.? Почему нельзя было взять тот же keycloak или Spring Authorization Server? Это мощные проверенные временем технологии с большим комьюнити, надежно зарекомендовавшие себя в продакшн-условиях. Ваш AuthService  не удовлетворяет даже 5% от тех требований, которые предъявляются к реальным серверам авторизации.

1. Сприг-секьюрити слишком подвержен изменениям. Постоянно выходят новые версии, старые методы становятся неподдерживаемыми, возникают новые классы и так далее. С моей точки зрения это говорит о том, что данный проект ещё несколько сыроват.2. Использование сприг-секьюрити накладывает дополнительные архитектурные ограничения. Иногда эти ограничения идут в разрез с планируемой архитектурой.3. Наконец что если я хочу написать действительно "микро"-сервис, то есть вообще без использования спринга?

По пунктам:

  1. В spring-security депрекейтед апи может присутствовать годами. Есть компоненты еще с первых релизов. Удаляются такие компоненты крайне редко, чтобы лишний раз не нарушать обратную совместимость. То, что появляются новые классы - неудивительно, фрэймворк развивается, появляются новые фичи - тот же webauth или one time token login. Вы считаете, что развитие технологии это минус? Это я вам говорю как один из разработчиков spring-security.

  2. Например, какие? То, что нужно настроить SecurityFilterChain не заставит ваш сервис работать кардинально иначе. Если только вы не используете свою велосипедную авторизацию вместо oauth 2.0. Но как показала практика, даже в таких случаях spring security прекрасно работает.

  3. Никто не запрещает. правда возникает вопрос - какова цена такой разработки.

Со шлюзом тоже странная ситуация: есть TokenRelay для oauth клиентов и это, то как нужно строить систему авторизации для веб-приложений. У вас же опять что-то сильно странное и неочевидное.

В общем, извините за критику, но в данном случае "Платон мне друг но истина дороже". Ваше решение мне видится крайне сомнительным.

Для простоты можно принять, что редис хранит два токена - аксес и рефреш.

Все верно. В следующий раз для доступа к авторизованной сессии фронт будет использовать куку. Правильнее сказать браузер будет использовать куку.

Если у нас на гетевей ломится фронт, к примеру реактовский, то как он определит, что сессии нет и надо показать страницу логина?

Это поймет сам шлюз и фронт получит редирект на страницу авторизации сервера авторизации. Даже если сессия до этого была и были просто почищены куки. При этом старая сессия будет висеть пока не отвалится сама.

  1. Есть ли какое нибудь кэширование или каждый запрос на гетевей по http вызывает обращение в редис за сессией?

В общем-то, сам редис частично выполняет функцию кэша, в памяти авторизационные данные не кэшируются. Это могло бы быть актуально для небольшого числа сессий, но представьте если у вас, например, 2 млн живых пользователей, и вам нужно держать в памяти 2 млн активных сессий, т.е. объектов OAuth2AuthorizedClient. Лучше так не делать.

Спасибо, я понял о чем вы.

Этот протокол реализуется всеми браузерами современными на android

Нет, не всеми. Только браузерами на основе chromium. Кроме того для того, чтобы полноценно работал AppAuth (т.е. флоу авторизации oauth 2.0) в браузере необходима поддержка app-links. В свое время был вопрос на stackoverflow почему AppAuth не работает в Opera, Dophin, Firefox и т.д. Ответ дал сам лид AppAuth. То, о чем говорите вы, в теории реально - необходим зловредный браузер на основе chromium, который поддерживает custom tabs и app-links, этот браузер должен попасть в ось пользователя, а тот уже должен начать авторизовываться в нем. Насколько это реально? Дума, что реально. Является ли это критической уязвимостью, из-за которой нужно отказываться от oauth 2.0? Думаю нет. Известно, что 65% рынка это chrome (включая ios), что делает авторизацию в таких девайсах относительно безопасной. В любом случае - фишинг через откровенно мошеннические приложения, где пользователь вводит свои креды в никуда, (таких приложений в том же app store полно: сбер, т-банк, висят они там долго, не удаляются), в последнее время стал массовой проблемой, один telegram чего стоит.

Вы уверены, что это будет работать в AppAuth именно так? В документации написано:

The library follows the best practices set out in RFC 8252 - OAuth 2.0 for Native Apps, including using Custom Tabs for authorization requests. For this reason, WebView is explicitly not supported due to usability and security reasons.

Т.е. будет использованы custom tabs и это не то, о чем говорите вы. Или я ошибаюсь? Можете пояснить?

Минуточку. А почему вы решили, что это аргументы? Вы считаете, что я поставил себе цель доказать кому-то, что стандарты безопасности и построенные на их основе технологии и фрэймворки не являются полной ерундой? И затеял спор на эту тему? Извините, но это не так, со стороны это выглядит как абсурд. Есть набор фактов - есть спецификация, есть описание конкретной реализации в стандарте, есть keycloak, spring authorization server, okkta, auth0, которые реализовывают эти стандарты и рекомендуют использовать их именно так, как реализовано. В конце концов есть фрэймворки, которые поддерживают именно такие подходы. Пруфы можно приводить до бесконечности. И это все факты. Что тут для кого авторитет, а для кого нет, тут пусть каждый сам решает. Моя цель, как разработчика одного из таких фрэймворков, указать на все эти факты. А что с этим делать - решайте сами.

Information

Rating
203-rd
Registered
Activity

Specialization

Backend Developer
Lead
Java
Junit
Java Spring Framework