Организация безопасного канала между веб-приложением и собственным приложением
Этот вопрос является своего рода дополнением к " Обмен учетными данными между собственным приложением и веб-сайтом ", поскольку мы стремимся делиться секретами в противоположном направлении.
TL; TR: как мы можем безопасно передавать состояние аутентификации / авторизации пользователя из приложения веб-браузера в приложение Native Desktop, чтобы одному и тому же пользователю не приходилось дополнительно проходить аутентификацию в приложении Native?
TS; WM: мы работаем над следующей архитектурой: веб-приложение (с некоторым пользовательским интерфейсом HTML, работающим в веб-браузере по выбору пользователя), приложение Native Desktop (реализующее пользовательский обработчик протокола), веб-API и Сервис OAuth2, как на картинке.
Первоначально пользователь проходит проверку подлинности / авторизацию в приложении веб-браузера для службы OAuth2, используя поток предоставления кода авторизации.
Затем содержимое веб-браузера может выполнять одностороннюю связь с приложением Native, когда пользователь нажимает на наши пользовательские гиперссылки на основе протокола. По сути, это делается для создания безопасного двунаправленного внутреннего коммуникационного канала между ними, осуществляемого через Web API.
Мы считаем, что перед тем, как реагировать на любые запросы, полученные через пользовательскую ссылку на протокол из приложения веб-браузера, приложение Native должно сначала подтвердить подлинность пользователя (который должен быть тем же человеком, который использует этот конкретный сеанс рабочего стола). Мы считаем, что родное приложение должно также использовать поток кода авторизации (с PKCE) для получения токена доступа для веб-API. Тогда он сможет безопасно проверять происхождение и целостность данных настраиваемого протокола, используя тот же веб-API.
Однако для пользователя может быть затруднительно дважды проходить проверку подлинности, сначала в веб-браузере, а затем в приложении Native, причем оба приложения работают бок о бок.
Таким образом, возникает вопрос: существует ли способ безопасной передачи маркера доступа OAuth2 (или любого другого носителя авторизации) из приложения веб-браузера в собственное приложение без ущерба для безопасности этой архитектуры на стороне клиента? То есть, чтобы приложение Native могло вызывать веб-API, используя идентификатор из веб-браузера, без предварительной проверки подлинности того же пользователя?
Лично я не вижу, как мы можем безопасно избежать этого дополнительного потока аутентификации. Связь по протоколу пользовательского приложения по умолчанию небезопасна, так как обычно это просто аргумент командной строки, с помощью которого вызывается Native. В отличие от канала TLS, он может быть перехвачен, подделан и т. Д. Мы могли бы зашифровать данные пользовательского протокола. Тем не менее, независимо от того, какие вызовы родному приложению нужно будет сделать для его дешифрования (либо к API клиентской ОС, либо к некоторым незащищенным вызовам веб-API), плохой субъект или вредоносная программа также сможет их воспроизвести.
Я что-то пропустил? Есть ли безопасное решение для платформы? Приложение Native Desktop является приложением Electron и предназначено для кроссплатформенности. Большинство наших пользователей будут запускать это в Windows, используя любой поддерживаемый браузер (включая даже IE11), но об ActiveX или взломе работающего экземпляра веб-браузера не может быть и речи.
5 ответов
Лучшее решение: единый вход (SSO) с использованием пользовательской схемы URL
Когда я проверял ваш вопрос, я вспомнил приложение Zoom, которое я использую в своем офисе. Как это устроено?
Моя учетная запись Gmail связана с учетной записью Zoom (это привязка учетной записи, которая выходит за рамки реализации). Открывая приложение Zoom, я могу выбрать опцию входа в Gmail. Это откроет мой браузер и переместит меня в Gmail. Если я вошел в Gmail, меня перенаправили обратно на страницу с просьбой запустить приложение Zoom. Как происходит запуск этого приложения? Приложение регистрирует пользовательскую схему URL-адресов, когда приложение устанавливается, и конечный редирект в браузере предназначается для этого URL-адреса. И этот URL передает временный секрет, который приложение Zoom использует для получения токенов OAuth. И получение токена осуществляется независимо от браузера, прямой вызов с SSL на конечную точку токена сервера OAuth.
Ну, это поток кода авторизации для нативных приложений. И вот как мобильные приложения используют OAuth. Ваша основная проблема, не позволяющая пользователю повторно войти в систему, решена. Это SSO в действии.
Существует спецификация, которая определяет лучшие практики вокруг этого механизма. Я приветствую вас, чтобы пройти RFC8252 - OAuth 2.0 для нативных приложений.
Вызов
Для каждого дистрибутива приложения необходимо реализовать собственный код для конкретной ОС. Windows, Mac и Linux имеют различную поддержку реализации пользовательской схемы URL.
Совет
PKCE является обязательным (в словах IETF СЛЕДУЕТ) для всех типов предоставления OAuth. Есть этот постоянный проект, который говорит об этом. Так что включите PKCE для вашей реализации тоже.
С PKCE ответ перенаправления / обратного вызова защищен от кражи. Даже какое-то другое приложение перехватывает обратный вызов, запрос токена не может быть воссоздан, так как есть PKCE code_verifer.
Кроме того, не используйте пользовательское решение, такое как передача секрета через другой канал. Это усложнит процесс обслуживания. Поскольку этот поток уже существует в OAuth, вы можете воспользоваться библиотеками и руководствами.
-------------------------------------------------- ---
Обновление: защита запроса токена
В то время как пользовательская схема URL решает проблему запуска собственного приложения, защита запроса токена может быть сложной задачей. Есть несколько вариантов для рассмотрения.
- Привязка собственного запуска приложения с секретным общим доступом из браузера
Когда клиент на основе браузера запускает собственный клиент, он может вызывать пользовательский API для генерации секрета. Этот секрет действует как одноразовый пароль (OTP). Пользователь должен ввести это значение в собственное приложение, прежде чем оно получит токены. Это настройка поверх потока кода авторизации.
- Динамическая регистрация клиента и Динамическая проверка подлинности клиента
Встраивание секретов в общедоступные клиенты не рекомендуется в спецификации OAuth. Но, как указывает владелец вопроса, некоторые вредоносные приложения могут зарегистрироваться, чтобы получить пользовательский URL-ответ и получить токены. В этом случае PKCE может обеспечить дополнительный уровень безопасности.
Но все же в крайнем случае, если вредоносное приложение регистрирует URL-адрес и использует PKCE в качестве исходного приложения, то могут быть потенциальные угрозы.
Один из вариантов - разрешить динамическую регистрацию клиента при первом запуске приложения. Здесь установщик / дистрибутив может содержать секрет, который используется вместе с DCR.
Кроме того, можно использовать динамическую проверку подлинности клиента через выделенный сервис. Здесь запрос токена приложения содержит временный токен, выпущенный пользовательской службой. Таможенный сервис получить вызов из родного приложения. Это может быть сделано с помощью TotP или криптографической привязки на основе встроенного секрета. Также можно использовать OTP (как упомянуто в первом примечании), выданный через браузер, который должен быть скопирован, вставлен вручную конечным пользователем. После проверки эта служба выдает токен, соответствующий секрету. В запросе токена нативный клиент отправляет этот токен вместе со значениями обратного вызова. Таким образом мы уменьшаем векторы угроз, хотя мы увеличиваем реализацию.
Резюме
- Используйте собственную схему URL для запуска собственного приложения
- Приложение-браузер генерирует временный секрет, предоставленный пользовательскому сервису
- При запуске собственного приложения пользователь должен скопировать секрет в пользовательский интерфейс собственного приложения.
- Нативное приложение обменивается этим секретом с пользовательским сервисом для получения токена
- Этот второй токен в сочетании с кодом авторизации обратного вызова (выданным по специальной схеме URL) используется для аутентификации в конечной точке токена
- Выше можно рассматривать как динамическую проверку подлинности клиента
- Значение, предоставляемое пользователю, может быть хешированным секретом, следовательно, исходное значение никогда не раскрывается конечному пользователю или другому клиенту.
- DCR также возможен, но в мире OAuth встроенные секреты не приветствуются.
Как вы упомянули, использование специального обработчика протокола не является безопасным способом передачи секретов, поскольку другое приложение может обрабатывать ваш протокол и перехватывать этот секрет.
Если вы налагаете строгое ограничение на то, что канал связи между нативным приложением и веб-приложением инициируется из веб-приложения и что нативное приложение ранее не устанавливало безопасный канал (например, общий секрет, который мог бы зашифровать другие секреты), тогда невозможно безопасно передать секрет нативному приложению.
Представьте, если бы это было возможно, то PKCE был бы избыточен в потоке кода OAuth 2.0, поскольку сервер мог бы безопасно передать токен доступа в ответ на запрос авторизации, вместо того чтобы требовать code_verifier
предоставляется при получении токена доступа.
Вы думали об использовании LDAP
или же Active Directory
?
Также OAuth2 может быть объединен, вот связанный вопрос:
- Сервис Oauth для аутентификации LDAP
- Oauth 2 токен для учетных записей Active Directory
SSO
тогда должно быть проще, кроме того, права доступа могут управляться централизованно.
Что касается общих соображений безопасности, вы можете работать с двумя серверами и перенаправить с одного веб-приложения на другой после успешной проверки доступа. Этот 2-й сервер может быть защищен настолько, что с 1-го сервера требуется перенаправление, и проверка доступа может быть снова сделана независимой, но без необходимости входа в систему в другой раз, может быть важно упомянуть здесь предлагаемое использование Oracle Access Manager
в одном связанном ответе за perimeter authentication
,
Этот сценарий с двумя серверами можно также скрыть, используя прокси-сервер во внешнем интерфейсе и сделав перенаправления скрытыми, так что передача данных между серверами будет проще и безопаснее. Важным моментом в моем предложении является то, что доступ ко 2-му серверу просто не предоставляется, если что-то не так и данные все еще защищены.
Я прочитал здесь некоторые комментарии, касающиеся 2FA и некоторых других идей, таких как токены, конечно, эти вещи повышают безопасность, и было бы хорошо их реализовать.
Если вам нравится общая идея, я готов потратить еще некоторое время на детали. Некоторые вопросы могут быть полезны для меня;-)
РЕДАКТИРОВАТЬ:
Технически дизайн в деталях может зависеть от используемого external authentication provider
лайк Oracle Access Manager
или что-то другое. Так что, если решение в целом кажется вам разумным, было бы полезно разработать некоторые параметры для выбора external authentication provider
цена, open-source, особенности и т. д.
Тем не менее, общая процедура заключается в том, что провайдер выдает токен, и этот токен служит для аутентификации. Токен предназначен для уникального одноразового использования, вторая ссылка, которую я разместил выше, содержит несколько ответов, которые очень хорошо объясняют использование токена, связанное с безопасностью и OAuth.
EDIT2
Разница между собственным OAuth2 / OIDC-сервером и LDAP/AD-сервером заключается в том, что вам нужно все программировать самостоятельно, и вы не можете использовать готовые решения. Тем не менее, вы независимы, и если все хорошо запрограммировано, возможно, даже немного более безопасно, поскольку ваше решение не является общедоступным и, следовательно, труднее взломать - потенциальные уязвимости просто не могут быть известны другим. Кроме того, вы более независимы, вам никогда не придется ждать обновлений и вы можете изменить все, что вы хотите в любое время. Учитывая, что задействовано несколько программных серверов и, возможно, даже аппаратных серверов, собственное решение может быть ограничено в масштабах, но об этом нельзя знать извне и зависит от вашей компании / команды. Ваша кодовая база, вероятно, тоньше, чем полноценные решения, поскольку вам нужно только рассмотреть собственное решение и требования.
Слабым местом вашего решения может быть то, что вам нужно программировать интерфейсы для нескольких существующих вещей, готовых для бизнес-фреймворков. Также может быть сложно рассмотреть каждую точку в небольшой команде, у крупных компаний может быть больше обзора и возможностей для решения каждой потенциальной проблемы.
Вы можете попробовать запустить синхронизацию другим способом:
- После проверки подлинности пользователя в веб-приложении запустите собственное приложение из веб-приложения по специальной схеме URL-адресов.
- Если собственное приложение не аутентифицировано, безопасно подключитесь к бэкэнду по HTTPS, создайте запись для собственного приложения, получите одноразовый токен, связанный с этой записью, а затем запустите веб-приложение в браузере пользователя с токеном в качестве параметра URL-адреса.,
- Поскольку пользователь проходит проверку подлинности в браузере, когда сервер видит токен, он может связать запись собственного приложения с учетной записью пользователя.
- Проведите собственный опрос приложений (или используйте другой канал в реальном времени, например push-уведомления или TCP-соединение) на сервере, чтобы узнать, был ли токен привязан к учетной записи пользователя: как только это произойдет, вы можете передать постоянный токен аутентификации, который может использовать нативное приложение. хранить.
Просто получил следующую идею. Это просто, и хотя оно не позволяет полностью автоматизировать настройку безопасного канала между приложением Web Browser и приложением Native, оно может значительно улучшить взаимодействие с пользователем.
Мы можем использовать алгоритм одноразового пароля на основе времени (TOTP). В некотором смысле это похоже на то, как мы соединяем Bluetooth-клавиатуру с компьютером или телефоном.
Приложение веб-браузера (в котором пользователь уже прошел аутентификацию) может отображать для пользователя временный код, и собственное приложение должно попросить пользователя ввести этот код в качестве подтверждения. Затем он будет использовать код для аутентификации на основе веб-API. Этого должно быть достаточно, чтобы установить внутренний канал между ними. Время жизни канала должно быть ограничено продолжительностью сеанса в приложении веб-браузера. Такой подход может даже устранить необходимость в связи с пользовательским протоколом.
Все еще открыт для других идей.