#php #javascript #angularjs #oauth2
Дано: Основной сайт (PHP+HTML) с поднятым OAuth 2 сервером Доверенное приложение на этом же домене на Angular-е (100% javascript) Задача: Авторизация пользователей в приложении через собственный OAuth сервер (точнее нужен токен для доступа к апи) "Запомнить меня" (каждый раз тыкать кнопку и делать кучку редиректов не вариант) Размышления: Сама спецификация предусматривает для таких случаев Implicit Grant, но как реализовать "запомнить" я так и не придумал ибо срок жизни токена ограничен, а получить новый можно только через редиректы => оно неюзабельно. Кроме того, например, вон там рассказывается что оно не безопасно и дана гениальная идея использовать proxy и шифрованные кукисы для скрытия токенов (refresh_token получается недоступен в js, но сохраняется в кукисах и может потом использоваться повторно) - однако, я так и не понял что помешает использовать этот proxy напрямую? (имхо, бессмысленное усложнение, возможно, ошибаюсь?) Следующей после после proxy была идея забить на спецификацию и использовать Authorisation Code Grant с открытым client_secret - благодаря наличию refresh_token-а можно будет получать новые токены и оставаться авторизованным. НО этот вариант по сути мало чем отличается от Implicit Grant с "вечным" токеном + из-за большего количества действий реализация получается немного сложнее. Решение? В итоге после прочтения тонны всяких статей на тему js + oauth и размышлений о том как же оно всё криво изложенных выше остановился на следующем варианте: используя Client Credentials Grant выполняем ajax POST на основной сайт и если пользователь там авторизован ("там" оно определяется по cookies) и ранее уже авторизовал приложение, то сразу возвращаем токен (это и будет "запомнить меня"), если нет, то получаем первый токен через Implicit Grant. Естественно это всё только при https, POST, X-Frame-Options: DENY и всё на одном домене. Вроде бы оно не сильно дыряво получается? В общем то, хотелось бы услышать критику или предложите какой-нибудь другой вариант, себе уже всю голову сломал :(
Ответы
Ответ 1
Вы, ровно как и Алекс Билби сильно преувеличиваете опасность авторизации клиентских приложений в OAuth2. Естественно, в фронтенде публичного веб-приложения не стоит организовывать получение прав через Resource Owner Password Credentials(когда OAuth-серверу для получения токена передаётся id приложения + логин/пароль пользователя). Не стоит использовать и Client Credentials(OAuth-серверу передаётся только id приложения, а авторизация происходит с использованием внешних систем - например через NTLM-хеш, либо через HTTP-basic-авторизацию). Впрочем, оба этих способа очень специфичны, и абсолютное большинство OAuth-серверов их просто-напросто не поддерживают... Для авторизации остаются только Explicit(Authorization Code) и Implicit. Explicit требует наличия веб-сервера. При этом access token клиенту не передаётся - клиентской стороне возвращается "статус" и "код авторизации", тот передаёт серверу приложения, а он используя код авторизации получает от OAuth-сервера токен доступа. Дополнительно(но не всегда обязательно) при получении токена доступа серверу приложения требуется отправить "client secret" - специальный код/пароль, по которому определяется подлинность вашего приложения, и без указания которого нельзя получить токен доступа. Implict не требует наличия веб-сервера, при этом токен доступа возвращается в url. И естественно "client secret" в этом случае не используется - OAuth-серверу отправляется только id приложение, которое собственно по определению не является секретной информацией(любой может просто скопировать его из url авторизации, даже при explicit-авторизации). Злоумышленник потенциально может украсть как токен доступа при Implicit авторизации, так и авторизационные cookies вашего сайта. Основным каналом утечки при этом являются XSS-уязвимости на вашем сайте, либо вредоносное ПО на компьютере пользователя. Что злоумышленник получит в случае кражи токена доступа/cookies? Для практически всё! И не важно, что применялась Explicit-авторизация и вы проксировали запросы - всю необходимую информацию он получит через ваш сайт. Основное преимущество "проксирования" состоит в том, что иногда поставщики OAuth-ресурсов создают чересчур широкие scope, включающие заведомо больший функционал, нежели необходимо вашему приложению(несмотря на спецификацию, требующую минимальность) - в этом случае вы можете отрезать доступ к нежелательным ресурсам на уровне вашего бекенда. Но и минус тоже есть - при Explicit-авторизации, в случае взлома вашего сервера, злоумышленник получит из хранилища токены доступа сразу всех пользователей приложения. В случае же Implict-авторизации, взломав ваш сервер, злоумышленник токены доступа пользователей сразу не получит(ему придется предваритально модифицировать код фронтенда, да выдирать сохраненные на клиентской стороне токены).
Комментариев нет:
Отправить комментарий