Dva: образец аутентификации oauth2

Созданный на 5 сент. 2016  ·  26Комментарии  ·  Источник: dvajs/dva

Есть ли примеры OAuth2 от dva, как организовать модальные окна и как проверить разрешения?

Самый полезный комментарий

Что касается ответа @ u0x01 , я сказал много запутанной и бесполезной информации.

Фактически, это можно резюмировать следующим образом:

  1. Выбрасывание access_token непосредственно во внешний интерфейс вместо сеанса связано с тем, что он должен совместно использовать интерфейс с клиентским режимом. Этот вид интерфейса часто не поддерживает проверку сеанса или неудобно управлять сеансом в распределенной системе.

  2. Защищенность от XSS и CSRF атак необходимо анализировать отдельно.

    2.1 Для предотвращения CSRF интерфейс помещает access_token в HTTP-заголовок для отправки, а серверная часть поддерживает только проверку заголовка.В то же время этого достаточно, чтобы хорошо спроектировать интерфейс. Поскольку сторонний веб-сайт не может отправлять дополнительные HTTP-заголовки только через форму, а JS стороннего веб-сайта не может отправлять данные на свой собственный веб-сайт (если CORS настроен правильно)

    2.2 Для предотвращения XSS внешний интерфейс, хранящий access_token, действительно небезопасен и может быть прочитан JS по желанию и отправлен между доменами; а файлы cookie с установленным HttpOnly являются ресурсами учетных данных. Современные браузеры имеют очень ограниченные междоменные ограничения на Credentials.Строго нет возможности его получить. Но, в конечном счете, не должно ли предотвращение XSS означать предотвращение внедрения сценария + избегание цитирования ненадежных внешних сценариев?Этот HttpOnly можно назвать только лекарством

  3. Самая безопасная мера - действовать как входной прокси на серверной части и установить CORS Access-Control-Allow-Origin чтобы разрешить только внешние доменные имена. После успешного входа пользователя в систему возвращается сеанс HttpOnly и в поле заголовка добавляется случайный код, например X-CSRF-TOKEN . Этот случайный код существует с токеном access_token, полученным из интерфейса OAuth. . Внешний интерфейс использует Ajax или выборку для отправки данных с Cookie и этим заголовком. После того, как серверная часть проверяет действительность Cookie, ему необходимо проверить правильность заголовка X-CSRF .Это может в основном предотвратить кражу разрешений CSRF и обычного XSS.

Короче говоря, внешнее управление access_token нельзя грубо считать небезопасным.

Обновление 1:

Промежуточное ПО или бэкэнд использует jwt для шифрования access_token и в то же время обнаруживает внедрение форм и CSP для предотвращения XSS.

Все 26 Комментарий

Разве проверка oauth2 не выполняется путем перенаправления URL-адресов? Это нормально, если вы входите в систему, оценивая файл cookie.

Некоторые из OAuht2 выполняются через access_token, а не через url, чистый формат RESTFul.

Было бы лучше, если бы был пример интеграции dva и Spring Boot Oauth2: D

@soulmachine Я использую это, и я когда у меня будет время.

@WhatAKitty передает access_token, где хранится access_token? Хранение в local / SeeionStorage будет иметь риски безопасности XSS.

@ u0x01 хранится в localstorage. На самом деле, здесь нет большого риска. Access_token имеет ограничение по времени. Вы не можете снова войти в систему после тайм-аута, и нет разрешения refresh_token. Более того, другого пути нет - запрашивается другая связанная информация, и все они хранятся в localstorage.

@WhatAKitty Сейчас хакеры используют или пишут автоматизированные инструменты для атак. Двухчасового срока действия access_token достаточно для многих вещей. Как вы пришли к выводу, что «здесь не так уж много риска»?
Во-вторых, refresh_token не помещается в localstorage, куда вы его кладете?
Access_token больше подходит для APP. Чистая сторона JS не должна использовать схему access_token. По-прежнему существует риск межсайтовых атак.
Наиболее безопасным решением сейчас является добавление http-only в set-cookie.
При проверке входа в систему, принесите cookie на сервер, чтобы получить статус просмотра. Если он не удастся, он перейдет непосредственно на страницу входа.
Безопасность - это еще и продуктивность, которая важнее, чем Тайшань, поэтому здесь нельзя лениться.

@ u0x01 refresh_token, js клиенту не отдам. Следовательно, он должен быть повторно сертифицирован по истечении срока его действия. Возможно, я не разъяснял это раньше, потому что наше приложение выглядит следующим образом: access_token - это просто ключ, который позволяет вам получить доступ. Если вы хотите получить доступ к определенным ресурсам, вы должны пройти аутентификацию пользователя. Этот процесс защищен SSL, поэтому Вы не появитесь. Сказал о различных рисках.
Что касается самого безопасного решения, которое вы сказали, я также рассматривал возможность использования файлов cookie, но одно: я не сделал сервер совместимым с OAUTH2 и ПАРОЛЬОМ ВХОДА в одно и то же время, потому что я не могу вернуть access_token после входа в систему с ПАРОЛЕМ ВХОДА., Могут быть и другие способы, но я не нашла. Во-вторых: из-за того, что проект требует времени, этот вариант может быть выбран только в качестве компромисса. Поэтому этот план кажется немного неправильным, но на самом деле проблем с безопасностью не будет.

@WhatAKitty никогда не слышал о том, что SSL «может защищать веб-сайты от
Если вы можете гарантировать, что система вашего веб-сайта на 100% свободна от уязвимостей XSS / CSRF, вы можете сохранить ее в localStorage и позволить JS напрямую обращаться к учетным данным. (Но я никогда не видел ни одной компании, которая осмелилась бы проголосовать за то, что в ее системе нет лазеек в системе безопасности)

И я не понимаю, что значит доступ к определенным ресурсам, которые должны быть аутентифицированы пользователем. В спецификации OAuth2 получение access_token означает, что пользователь (или поставщик) одобрил эту авторизацию.

Кроме того, вы упомянули:
因为没法在使用 LOGIN PASSWORD 登录后给我返回一个access_token
Это неправильное понимание спецификации OAUth2 и неправильное использование.

Метод LOGIN PASSWORD - это, по сути, процесс, в котором UA напрямую запрашивает аутентификацию у поставщика OAUth2, см. RFC6749 . В это время должен быть получен authorization_code. После того, как UA получит authorization_code, он будет отправлен Клиенту для проверки действительности поставщика OAUth2. Если проверка пройдена, Клиент получит access_token от поставщика OAUth2. В это время Клиент может использовать access_token для доступа к ресурсам. Затем клиент выдает SessionID UA.
(Под клиентом здесь понимается сервер или приложение бизнес-стороны, а не конечный пользователь, конечный пользователь является владельцем ресурса, а UA - браузером)

В общем, SessionID должен использоваться для аутентификации пользователей, даже если SessionID не используется, access_token следует поместить в файл cookie только для http:

1. Don't use local storage for session identifiers. Stick with cookies and use the HTTPOnly and Secure flags.
2. If cookies won't work for some reason, then use session storage which will be cleared when the user closes the browser window.
3. Be cautious with storing sensitive data in local storage. Just like any other client side storage options this data can be viewed and modified by the user. 

Если вы действительно хотите предоставить клиенту access_token, способ компрометации:

// GET /seesion
    access_token := ctx.Session().GetString("access_token")

    if access_token != "" {
        ctx.JSON(200, {"signed": true, "access_token": access_token})
    } else {
        ctx.Redirect("//yoursite.com/login")
    }

Но я по-прежнему рекомендую помещать его только в файл cookie. JS использует метод GET / seeion, чтобы определить, вошли ли вы в систему. Доступ к другим ресурсам осуществляется как обычно. Сервер перейдет на страницу входа сразу после обнаружения истечения срока действия access_token. :

// GET /seesion
    access_token := ctx.Session().GetString("access_token")
    if signed != "" {
        ctx.JSON(200, {"signed": true})
    } else {
        ctx.Redirect("//yoursite.com/login", "you need login first.")
    }

// GET /posts/:postid
    access_token := ctx.Session().GetString("access_token")

    if access_token != "" && isValidAccessToken(access_token) {
        ctx.JSON(200, getPostWithAccessToken(access_token, postid))
    } else {
        ctx.Redirect("//yoursite.com/login", "you need login first.")
    }

Конечно, если вы думаете, что ваша система веб-сайта не имеет ценности для атаки, я ничего не сказал.

Это своего рода «на вид неприемлемо, но на самом деле проблем с безопасностью не будет». Думаю, я не знаю, сколько убытков это принесет вашему работодателю в будущем:
Инвентаризация утечек корпоративной информационной безопасности
Информация об одном миллионе клиентов передавалась в реальном времени (проблема утечки информации в этой компании не была полностью решена до сих пор, она была запрещена рядом крупных компаний электронной коммерции, таких как клуб продуктов)

Информационной безопасности предстоит пройти долгий путь.

@ u0x01
Позвольте мне рассказать о том, что я ответил ранее. Это может быть непонятно. В процессе получения access_token требуются не только client_id и client_secret (это может не понадобиться), но также требуются имя пользователя и пароль.

Может защитить сайт от атак XSS / CSRF

Там CSRF был отключен. Что касается XSS, то весь контент, хранящийся в базе данных, будет автоматически передан, а недопустимые поля будут отфильтрованы. Хотя могут быть упущения, полностью устранить их невозможно. Информационная безопасность не является абсолютно безопасной. То же верно и для Microsoft и Apple. Я вам не верю. Система может обеспечить стопроцентную безопасность.

Даже если вы не используете SessionID, вы должны поместить access_token в http only cookie

Только HTTP тоже не совсем безопасен.

Это неправильное понимание спецификации OAUth2 и неправильное использование.

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

Кроме того, мой идеальный метод аутентификации может отличаться от того, что вы сказали, потому что мой собственный сервер предоставляет услуги аутентификации OAuth2. Поэтому я думаю, что для моего клиента браузера это выглядит так: UA запрашивает AS, AS обнаруживает, что он не аутентифицирован, переходит к LOGIN, а затем после входа пользователя в систему он успешно получает разрешение на доступ к серверу (это может быть access_token, или это может быть) Вы можете напрямую открывать разрешения доступа к ресурсам), а затем пользователи могут прямо / косвенно (access_token) запрашивать ресурсы на сервере ресурсов на стороне js.

Другими словами, мой идеальный метод аутентификации - для нашего собственного UA. Я думаю, что если это сторонняя компания, может потребоваться использовать authorize_code, который вы упомянули, для получения страницы авторизации, к которой пользователь может получить доступ.

Вышеупомянутое - мой идеальный метод аутентификации, но, к сожалению, мой уровень ограничен, и я не могу получить желаемый эффект с помощью Spring OAuth2.

Я не знаю, какой ущерб это принесет вашему работодателю в будущем

Прежде всего, хочу отметить, что наш проект очень актуален, а архитектура его догнала совсем недавно.Если это возможно, не смогу ли я стремиться к совершенству? Однако время не позволяет, ваш босс позволяет перетащить проект клиента во время игры в техбезопасность? Реальность зачастую жестока. Ваш начальник может вообще не заботиться о безопасности ваших клиентов. Их больше заботят интересы. Единственное, что я могу сделать, это обеспечить максимальную безопасность.

@ u0x01 На самом деле, для себя я тоже хочу создать архитектуру, которую я спроектировал, без каких-либо проблем с безопасностью, но на самом деле:

  1. Я не могу удовлетворить это требование на моем личном техническом уровне. Я сам не являюсь техническим экспертом.
  2. Отсутствие настоящего технического эксперта, который мог бы направить меня, если кто-то захочет направить меня, я думаю, что буду счастлив

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

@WhatAKitty
Поскольку ваш проект в спешке, а начальнику все равно, просто делайте его сейчас, как вы задумали.

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

См. Соответствующие спецификации OAuth2, OAuth2 имеет концепцию неявного разрешения.

Другими словами, мой идеальный метод аутентификации - для нашего собственного UA. Я думаю, что если это сторонняя компания, может потребоваться использовать authorize_code, который вы упомянули, для получения страницы авторизации, к которой пользователь может получить доступ.

OAuth2, похоже, не имеет концепции третьей стороны.

К тому же, что ты делаешь с отключенной CSRF-защитой ... Разве не рыть себе яму?
Я не говорил, что http only абсолютно безопасен. Основная проблема безопасности, которую решает только http, - это запретить js читать куки. Взаимодействие с SSL может помешать третьим сторонам контролировать файлы cookie (в случае атак без использования посредника).

@WhatAKitty
Раньше я стоял с точки зрения начальника, но на самом деле, иметь некоторые проблемы с безопасностью - это хорошо. С одной стороны, ваш начальник уделит внимание вопросам безопасности, а с другой стороны, вы оставите обед инженеру по информационной безопасности.

Инженеры по информационной безопасности должны благодарить программистов, которые намеренно оставляют ошибки :)

@ u0x01 Кажется, вы хорошо знаете OAuth2? Можно ли создать группу? Я не нашел много информации о приложениях в этой области, и у меня не было слишком много времени на ее сбор. Я могу задать вам несколько вопросов.

@ u0x01 Бэкэнд не имеет состояния, и сеанса нет вообще. Вам нужно использовать токен для повторного подключения, чтобы определить, истек ли он.Могу я спросить, где находится токен?

@longzb без

Используйте токен для redis, чтобы определить, истек ли он

Фактически, access_token используется как сеанс. Рекомендуется узнать об определении и методах работы сеанса.

Где безопасный токен?

Помещение его в файл cookie http_only может помешать JS напрямую получить файл cookie, тем самым уменьшая ценность и вероятность атак XSS / CSRF.

@ u0x01 Хм. Вчера ходил в Байду. Собираюсь выложить куки, лучше перестраховаться.

Эта статья хороша о неявном анализе.
Сегодня я заканчиваю образец SSM + ANTD. Прочитав эту статью, я считаю, что самый безопасный способ - использовать неявный сервер для запроса сервера аутентификации и получения токена, а также неявно запросить неявный сервер для получения ресурсов ресурсный сервер.

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

Но для этого dva необходимо поддерживать рендеринг на стороне сервера.Теперь, когда его поддерживает antd, поддерживает ли уже dva? @sorrycc

Вы не беспокоитесь о правильных вещах

Защита информации, расположенной на клиенте?

Вам не нужно ничего делать, когда информация дошла до вашего клиента (например, вашего браузера), чтобы защитить его. Вы можете сохранить токен доступа в файле cookie, в скрытом поле на своей веб-странице, в локальном кеше html5. или явно видно прямо посередине страницы, и это ничего не меняет (кроме серфинга по плечу ...).

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

Где есть смысл волноваться?

Обычно ваша информация уязвима во время передачи. В случае OAuth2 (неявный поток) токен доступа будет передаваться в двух местах:

с сервера авторизации в ваш браузер
из вашего браузера на сервер ресурсов
Защитить информацию во время ее передачи так же просто, как повсюду использовать TLS. Что вы уже должны делать, поскольку вы используете OAuth2, а это требуется протоколом.

Теперь настоящая проблема

То, как вы собираетесь использовать OAuth2, скорее всего, не соответствует тому, как вы должны его использовать.

Чтобы понять, почему вы, вероятно, будете злоупотреблять OAuth2, вы должны знать о потоках. OAuth2 определяет 4 потока авторизации

Код авторизации (только хороший, но ... продолжайте читать)
Неявный (ложное чувство безопасности)
Учетные данные для пароля владельца ресурса (ужасная идея)
Учетные данные клиента (не применимы к вашему случаю)
Поскольку вы используете клиент javascript, единственный поток, который работает для вас, - это неявный поток, и теперь он запускает проблемы.

Неявные проблемы потока

Их много, но давайте поговорим о самом важном. Токен доступа не привязан к конкретному клиенту! Из раздела спецификации 10.16:

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

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

В неявном потоке (response_type = token) злоумышленник может легко переключить токен в ответе сервера авторизации, заменив реальный токен доступа на ранее выданный злоумышленнику.

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

Любой общедоступный клиент, который предполагает, что только владелец ресурса может предоставить ему действительный токен доступа к ресурсу, уязвим для этого типа атаки.
Эта первая атака на самом деле даже не атака, а скорее просто «изъян» в неявном потоке ...

Следующая атака

Теперь начинаются большие проблемы. Похоже, вы пытаетесь использовать неявный поток OAuth2 в качестве формы делегированной аутентификации конечного пользователя, для которой он не предназначен. Вернуться к разделу спецификации 10.16

Аутентификация владельцев ресурсов для клиентов выходит за рамки данной спецификации. Любая спецификация, которая использует процесс авторизации как форму делегированной аутентификации конечного пользователя для клиента (например, сторонняя служба входа в систему), НЕ ДОЛЖНА использовать неявный поток без дополнительные механизмы безопасности, которые позволят клиенту определять, был ли выпущен маркер доступа для его использования (например, маркер доступа, ограничивающий аудиторию).
На этом игра для вас в основном окончена.

Как провести эту атаку?

Это довольно просто. Допустим, вашей службе REST требуется токен доступа из facebook. Все, что нужно сделать злоумышленнику, - это разместить службу, например stackoverflow, и потребовать токен доступа из facebook. Когда вы передаете токен доступа facebook в stackoverflow, stackoverflow (наш злоумышленник) теперь может выдавать себя за вас с помощью вашей службы REST.

Все потому, что токены доступа не привязаны к конкретному клиенту.

Решение

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

Почему вы не используете сервер, обслуживающий клиента angularjs для вашего пользователя, для обработки потока OAuth2?

Ссылка: http://tools.ietf.org/html/rfc6749

@WhatAKitty Если определенный идентификатор браузера каждого пользователя уникален, пользователь автоматически передает этот идентификатор при отправке запроса, и его нельзя изменить. Серверная часть может привязать токен к этому идентификатору при первой подаче заявки на токен. Если следующий запрос не соответствует идентификатору браузера, хранящемуся в токене, он будет считаться незаконным. .
Итак, я хочу спросить, есть ли такой логотип, когда браузер запрашивает его? ?

@longzb обычно использует JSESSIONID, или его можно настроить. Например, oschina использует свой собственный id

@WhatAKitty @soulmachine @longzb

Когда режимы пароля и клиента OAuth2.0 используются одновременно, прокси-сервер входа может быть добавлен к внутреннему серверу для хранения access_token, и этот прокси также может использоваться как интерфейсный CORS (Spring Boot Oauth2, кажется, перехватывает предполетную проверку CORS)

В режиме внешнего пароля агенту необходимо только отправить имя пользователя и пароль. Агент получает авторизацию и сохраняет access_token. Затем SESSION_ID, сгенерированный агентом, возвращается внешнему интерфейсу, и агент должен управлять истечение срока действия и обновление access_token. Единственное, что доступно во внешнем интерфейсе, - это Remember-Me и т. д. Просто разные в заголовке Set-Cookie: Expires=

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

Что касается ответа @ u0x01 , я сказал много запутанной и бесполезной информации.

Фактически, это можно резюмировать следующим образом:

  1. Выбрасывание access_token непосредственно во внешний интерфейс вместо сеанса связано с тем, что он должен совместно использовать интерфейс с клиентским режимом. Этот вид интерфейса часто не поддерживает проверку сеанса или неудобно управлять сеансом в распределенной системе.

  2. Защищенность от XSS и CSRF атак необходимо анализировать отдельно.

    2.1 Для предотвращения CSRF интерфейс помещает access_token в HTTP-заголовок для отправки, а серверная часть поддерживает только проверку заголовка.В то же время этого достаточно, чтобы хорошо спроектировать интерфейс. Поскольку сторонний веб-сайт не может отправлять дополнительные HTTP-заголовки только через форму, а JS стороннего веб-сайта не может отправлять данные на свой собственный веб-сайт (если CORS настроен правильно)

    2.2 Для предотвращения XSS внешний интерфейс, хранящий access_token, действительно небезопасен и может быть прочитан JS по желанию и отправлен между доменами; а файлы cookie с установленным HttpOnly являются ресурсами учетных данных. Современные браузеры имеют очень ограниченные междоменные ограничения на Credentials.Строго нет возможности его получить. Но, в конечном счете, не должно ли предотвращение XSS означать предотвращение внедрения сценария + избегание цитирования ненадежных внешних сценариев?Этот HttpOnly можно назвать только лекарством

  3. Самая безопасная мера - действовать как входной прокси на серверной части и установить CORS Access-Control-Allow-Origin чтобы разрешить только внешние доменные имена. После успешного входа пользователя в систему возвращается сеанс HttpOnly и в поле заголовка добавляется случайный код, например X-CSRF-TOKEN . Этот случайный код существует с токеном access_token, полученным из интерфейса OAuth. . Внешний интерфейс использует Ajax или выборку для отправки данных с Cookie и этим заголовком. После того, как серверная часть проверяет действительность Cookie, ему необходимо проверить правильность заголовка X-CSRF .Это может в основном предотвратить кражу разрешений CSRF и обычного XSS.

Короче говоря, внешнее управление access_token нельзя грубо считать небезопасным.

Обновление 1:

Промежуточное ПО или бэкэнд использует jwt для шифрования access_token и в то же время обнаруживает внедрение форм и CSP для предотвращения XSS.

@mdluo имеет четкое представление, хвала 👍

@mdluo Извините, я новичок во credentials: "include" его решения, но этот параметр может решать только запросы GET. POST и другие проблемы имеют проблемы. Поскольку вы используете его впервые, писать самому может быть глупо. Окружающая среда:
Внешний интерфейс: порт DVA 8000
Бэкэнд: Spring boot + Spring security, X-CSRF-TOKEN и Cookie

@ yoster0520 Настройте CORS на внешнего интерфейса есть несколько адресов, бэкэнд должен динамически определять и возвращать только Access-Control-Allow-Origin соответствии с белым списком, чтобы он мог приносить файлы cookie.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги