Как стать автором
Обновить

Комментарии 17

ЗакрепленныеЗакреплённые комментарии

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

  1. CLI инициирует авторизацию и встаёт в лонгполлинг на внешний сервер приложения с таймаутом с некоторым генеренным на стороне клиента идентификационным токеном

  2. В браузере открывается ОАуф сессия, которая редиректит в конце на внешний сервер приложения, передавая наш идентификационный токен

  3. Внешний сервер отвечает на лонгполл, если находится с нужным id токеном, передавая данные авторизации oauth

В идеале, чтоб ещё исключить man-in-the-middle, пользователь на стороне нашего внешнего сервера на форме должен ввести какой-то код, который ему сгенерит CLI в процессе, тот же идентификационный токен и только после этого наш сервер отвечает на лонгполл. Это стоит делать и в вашей схеме, если вы не хотите, что б злоумышленник попытался прикинуться вами и украсть данные пользователя от имени вашего приложения, точно так же подняв локальный сервер.

Да, стоит не забывать, что если возникает несколько лонгполлов на одном ID токене, то лучше сбросить все.

А не проще для CLI приложений использовать т.н. "application password"? По сути это аналог токена без экспайра, который юзер создаёт на том же сайте, а потом прописывает в конфиг CLI приложения вместо своего настоящего пароля.

Ведь в этом случае CLI может ничего про OAuth не знать и не иметь никаких проблем из-за возможных конфликтов портов, потенциальной уязвимости через перехват кода на этом порту сторонним приложением, сложностей из-за встроенного веб-сервера и необходимости обновлять токен автоматически либо просить юзера снова логиниться через браузер…

Tip: App passwords aren”t recommended and are unnecessary in most cases. To help keep your account secure, use “Sign in with Google” to connect apps to your Google Account.

Гугл советует пользоваться OAuth, нежели app password. Перехват возможен, т.к. не используется https, но, согласно документации, передаваемый код имеет короткий срок жизни.

Советует - там, где это возможно и работает. А для остальных ситуаций поддерживает application password. Как по мне - CLI это как раз та ситуация, когда использование OAuth не совсем уместно. В частности, многие CLI утилиты должны быть работоспособны на сервере, где браузера нет. А даже если они используются на десктопе, они зачастую используются из скриптов или других приложений, в рамках работы которых запускать браузер и требовать наличия юзера за компом может быть совершенно неуместно. Добавим к этим недостаткам ещё и сложности с реализацией описанного в статье, и вопрос "нафига?" становится крайне уместным.

Насколько я помню доку по OAuth, в ней нет такого понятия как application password. Т.е. по факту это отдельная фича (не связанная с OAuth), которую разные сервисы могут реализовывать или нет, и делать это любым способом. Соответственно, такие application password могут не поддерживать ограничение прав доступа а-ля OAuth scope. Ну и как сервис реализует видимость для юзера созданных им application passwords и возможность их удалять - тоже зависит от конкретного сервиса. Насколько я понимаю - на этих пунктах недостатки этого подхода заканчиваются. В остальном - подход достаточно общепринятый и используется многими сервисами (напр. на гитхабе и на Digital Ocean эта фича называется Personal Access Tokens).

Иными словами данный совет гугла - это его личное предпочтение. Мотивация его неясна, причин не использовать application password там, где клиентам это удобнее - нет.

Теоретически вообще можно использовать mTLS, когда мы получаем (правильно, через Certificate Request, или неправильно - когда все просто на сервере генерируется), сертификат, подписанный собственным Certificate Authority сервера и сервер прямо на уровне транспорта предьявляемый клиентский сертификат проверяет. Но почему-то этот способ очень непопулярен.

Он непопулярен потому, что управление (выдача, установка в браузеры, обновление, отзыв) этими клиентскими сертификатами - достаточно сложная и неудобная штука. Поэтому mTLS активно используется только на бэке, для аутентификации между микросервисами, где всё управление всеми сертификатами может делать (и автоматизировать) девопс компании.

Тут про CLI приложение речь идет. Скачать файлик сертификата и отдать его приложению - в общем, не сильно сложнее, чем application password сконфигурировать.

А так - смотри Passkeys. Оно именно это (выдача, установка в бразеры итд) и есть. Только почему-то новые интерфейсы написали вместо использования/додельки существующих.

Passkeys/WebAuthn вообще и не про сертификаты и не про CLI. Это про то, чтобы юзер пароли не запоминал. Совсем другая задача и другое решение. Как это может помочь организовать доступ CLI к API сайта более простым способом чем application passwords - мне лично пока неясно. Как минимум это создаст зависимость CLI от внешнего аутентификатора (хардварного или программного), а они пока не особо популярны и распространены.

Passkeys/WebAuthn вообще и не про сертификаты

Я про то, что устроено оно довольно похоже - ассиметричная криптография, приватная часть хранится локально и служит для входа на сервер. Того же самого(нигде не видел объяснений, чего именно мешало) можно было добиться, доработав интерфейсы работы с сертификатами TLS в браузерах. То самое удобство установки в браузерах итд.

CLI тут действительно, не причем. Для CLI более-менее достаточно пункта "скачать сертификат доступа к сервису" где-нибудь в меню сервиса.

И, кстати, а как будет выглядеть вход CLI приложения в сервис, в который в браузере - чисто по Passkeys заходят? Да еще с соседнего смартфона. Этот вариант - довольно усердно рекламируют.

Добавил https, теперь без перехвата)

Ну, так лучше, конечно, но перехват ещё можно организовать тупо прибив этот CLI после запуска браузера и подняв на том же порту свой веб-сервер.

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

  1. CLI инициирует авторизацию и встаёт в лонгполлинг на внешний сервер приложения с таймаутом с некоторым генеренным на стороне клиента идентификационным токеном

  2. В браузере открывается ОАуф сессия, которая редиректит в конце на внешний сервер приложения, передавая наш идентификационный токен

  3. Внешний сервер отвечает на лонгполл, если находится с нужным id токеном, передавая данные авторизации oauth

В идеале, чтоб ещё исключить man-in-the-middle, пользователь на стороне нашего внешнего сервера на форме должен ввести какой-то код, который ему сгенерит CLI в процессе, тот же идентификационный токен и только после этого наш сервер отвечает на лонгполл. Это стоит делать и в вашей схеме, если вы не хотите, что б злоумышленник попытался прикинуться вами и украсть данные пользователя от имени вашего приложения, точно так же подняв локальный сервер.

Да, стоит не забывать, что если возникает несколько лонгполлов на одном ID токене, то лучше сбросить все.

Немного подумав дополню сам себя:

  • Лонгполлинг не обязательно использовать, можно обойтись запрос-ответами.

  • Девайс код не поможет, если сервер поднимать на локолхосте

  • Весь этот усложненный путь стоит использовать ТОЛЬКО, если OAuth-провайдер не реализовал уже за вас расширение device-code, тогда нужно использовать его (ссылки в других ветках комментариев).

точно. такой в AWS CLI используется для аутентификации через SSO.

Столкнулся с некоторой проблемой

Пользователь перенаправляется на страницу с предложением ввести логин, пароль на сайте HH:

def get_oauth_link(client_id: str) -> str:
    url = "https://hh.ru/oauth/authorize?"
    params = {"client_id": client_id,
              "redirect_uri": HH_REDIRECT_URI,
              "response_type": "code"}
    click.echo(url + urllib.parse.urlencode(params))
    return url + urllib.parse.urlencode(params)

Если пользователь авторизоваться, то перенаправление идёт не на форму с логином и паролем, а на страницу с кнопкой "Продолжить". Можно ли как-то миновать эту страницу и перепрыгнуть сразу на редирект в этом случае?

Это от реализации HH зависит. Насколько я понял — нельзя.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории