auth_redirect() – Проверяет авторизован ли пользователь, перед тем как допустить его на любую страницу сайта.

Что такое grant?

Grant — это данные, которые представляют из себя успешную авторизацию клиента владельцем ресурса, используемые клиентом для получения access token.

Например, когда мы где-либо аутентифицируемся с помощью Google, перед глазами всплывает уведомление. В нём говорится, что такой-то сервис хочет получить доступ к данным о вас или к вашим ресурсам (выводятся запрашиваемые scope-token). Это уведомление называется «Consent Screen».

В момент, когда нажимаем «ОК», в базу данных попадает тот самый grant: записываются данные о том, что такой-то пользователь дал такие-то доступы такому-то сервису. Клиент получает какой-то идентификатор успешной аутентификации, например строку, которая ассоциируется с данными в базе данных.

Существует 4 1 способа получения grant — grant type:

Редирект на изначально запрашиваемую страницу после авторизации на базе php – weril

Redirect делается обычно на основе запрашиваемого URL из переменной $_SERVER[‘REQUEST_URI’], далее назовем это query URL.

Первоначально редиректим на страницу авторизации с указанием запрашиваемого url из query URL в переменной location.

header("Location:login.php?location=" . $_SERVER['REQUEST_URI'] );

Уже на странице авторизации после успешной авторизации делаем тоже самое – забираем query URL. Далее выщепляем из него только нужное через регулярные выражения или explode на основе строки “location=” и редиректим. В случае если в запросе нет строки “location=” – редиректим на index.php.

$req_url = ($_SERVER['REQUEST_URI']);$splitted_array = explode('location=', $req_url);if(!empty($splitted_array[1])){  $url= $splitted_array[1];  header("Location:$url");}else{  header("Location:index.php");}

Что такое оauth2.0?

Разработку нового Auth мы решили начать с изучения доступных протоколов и технологий. Самый распространённый стандарт авторизации — фреймворк авторизации OAuth2.0. 

Стандарт был принят в 2022 году, и за 8 лет протокол меняли и дополняли. RFC стало настолько много, что авторы оригинального протокола решили написать OAuth 2.1, который объединит все текущие изменения по OAuth 2.0 в одном документе. Пока он на стадии черновика.

Актуальная версия OAuth описанна в RFC 6749. Именно его мы и разберем. 

OAuth 2.0 — это фреймворк авторизации.

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

Особенности:

Разберёмся подробнее в особенностях.

Authorization code

Самый распространённый flow на данный момент. В основном используется для confidential клиентов, но с появлением дополнительной проверки с помощью PKCE, может применяться и для public-клиентов. 

Authorization code grand

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

Client credentials

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

  1. API 1 идет в авторизационный сервер передает туда client_id и client_secret.

Redirect авторизованного пользователя, когда тот снова хочет попасть на страницу авторизации

Есть простенький сайтик, на котором есть страница приветствия (/welcome) с двумя ссылками на авторизацию(/login) и регистрацию(/sign). Если пользователь не авторизован, на другие страницы его не пускает – перенаправляет на страницу авторизации.

        http
            .authorizeRequests()
            .antMatchers(HttpMethod.GET, "/css/**", "/js/**").permitAll()
            .antMatchers("/", "/welcome", "/login", "/sign").permitAll()
            .antMatchers("/main").authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/main")
            .permitAll()
            .and()
            .logout()
            .logoutSuccessUrl("/welcome")
            .permitAll();

Вот моя конфигурация.
А теперь, собственно, о проблеме. Когда пользователь авторизован, то ему все равно остаются доступны страницы приветствия, авторизации и регистрации. Например, пользователь вошел на сайт под своим логином и паролем, потом перешел через строку браузера на страницу авторизации и еще раз вошел. Я бы хотел оградиться от такого редиректом с эти трех начальных страниц на /main, но только, если пользователь авторизован. Подскажите, есть ли способ редиректить через конфигурацию или есть другой способ лучше и проще?

Resource owner password credentials flow

По текущим рекомендациям безопасности описанных в

, данный flow не рекомендуется использовать вовсе из-за явных проблем с безопасностью.

Абстрактный oauth 2.0. flow c применением access token

Мы рассмотрели роли, рассмотрели виды токенов, а также как выглядят scope. Посмотрим на flow предоставления доступа к сервису.

Ниже представлена абстрактная схема (или flow) взаимодействия между участниками. Все шаги на данной схеме выполняются строго сверху вниз. Разберём детальнее.

Клиент получает одобрение от resource owner, на основе которого ему выдаётся доступ к ресурсу. Всё просто. А будет ли так же просто, если мы добавим в эту схему работу с refresh token?

Абстрактный oauth 2.0. flow c применением refresh token

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

Схема подробнее:

Авторизация под разными рабочими аккаунтами

Для получения списка рабочих аккаунтов менеджера и для работы под разными рабочими аккаунтами менеджера необходимо прочитать документацию по рабочим аккаунтам менеджера

Возвращает

null.

Задача auth

Проблема авторизации в десятках сервисов встречалась ещё несколько лет назад — в начале «

». Эту проблему решили новым сервисом, который назвали – Auth. Он помог реализовать бесшовную аутентификацию в различных сервисах и перенести данные о пользователях в отдельные базы данных. 

У сервиса Auth есть три основные задачи:

Запрос авторизации под другим пользователем

Возможен следующий сценарий:

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

Если есть необходимость, чтобы на шаге 3 сразу происходило перенаправление (redirect) с временным токеном,
необходимо добавить к запросу /oauth/authorize… параметр skip_choose_account=true.
В этом случае автоматически выдаётся доступ пользователю авторизованному на сайте.

Инвалидация access-токена

Для того, чтобы инвалидировать текущий access-токен, необходимо сделать запрос:

Передавая его стандартным способом в заголовке в формате:

Authorization: Bearer ACCESS_TOKEN

Инвалидация работает только на действующем access-токене.

После инвалидации токен нельзя будет запросить с помощью refresh-токена – для работы необходимо будет заново авторизоваться в api.

Таким образом можно инвалидировать только токен пользователя.

Использование

auth_redirect();

История возникновения oauth

Авторизацией через социальные сети никого уже не удивишь. Нажимаешь кнопку соц сети, вжух и ты авторизовался на новом сайте. Сайт получил твоё ФИО, фотку и прочие данные. Но так было не всегда.

Обновление пары access и refresh токенов

access_token также имеет срок жизни (ключ expires_in, в секундах), при его
истечении приложение должно сделать запрос с refresh_token для получения
нового.

Запрос необходимо делать в application/x-www-form-urlencoded.

В теле запроса необходимо передать дополнительные параметры:

Ответ

Ответ будет идентичен ответу на получения токенов в первый раз:

refresh_token можно использовать только один раз и только по истечению
срока действия access_token.

После получения новой пары access и refresh токенов, их необходимо использовать
в дальнейших запросах в api и запросах на продление токена.

Ошибки

  • 400 Bad Request – ошибка в параметрах запроса.

Получение авторизации пользователя

В начале приложению необходимо направить пользователя (открыть страницу) по адресу:

Обязательные параметры:

  • response_type=code — указание на способ получения авторизации, используя authorization code
  • client_id — идентификатор, полученный при создании приложения

Необязательные параметры:

Права доступа

Права доступа выдаются клиенту в виде scope. Scope – это параметр, который состоит из разделённых пробелами строк — scope-token.

Каждый из scope-token представляет определённые права, выдающиеся клиенту. Например, scope-token doc_read может предоставлять доступ на чтение к какому-то документу на resource server, а employee — доступ к функционалу приложения только для работников фирмы. Итоговый scope может выглядеть так: email doc_read employee.

В OAuth 2.0 мы сами создаём scope-token, настраивая их под свои нужды. Имена scope-token ограничиваются только фантазией и двумя символами таблицы ASCII — ” и .

На этапе регистрации клиента, в настройках сервиса авторизации клиенту выдаётся стандартный scope по умолчанию. Но клиент может запросить у сервера авторизации scope, отличный от стандартного. В зависимости от политик на сервере авторизации и выбора владельца ресурса, итоговый набор scope может выглядеть совсем иначе.

Примеры

Используйте такой код в header.php:

if( is_single() ){
	auth_redirect();
}

Проблемы

Первая версия Auth — часть монолита. Он использует свой собственный протокол общения с сервисами. Такая «схема» была необходима в тот момент, но за несколько лет работы проявились проблемы.

Auth — часть монолита. Следовательно, сервис привязан к релизному циклу, что лишает возможности независимой разработки и деплоя. Кроме того, придется разворачивать весь монолит, если захотелось развернуть Auth, например, при масштабировании сервиса.

Dodo IS зависит от Auth. В старой реализации внешние сервисы обращаются к Auth при каждом действии пользователя, чтобы валидировать данные о нём. Настолько сильная привязка может привести к остановке работы всей Dodo IS, если Auth «приляжет» по какой-то причине.

Auth зависит от Redis. Притом достаточно сильно — неисправность работы Redis’а приведёт к падению Auth’а. Мы используем Azure Redis, для которого заявленный SLA 99,9%. Это значит, что сервис может быть недоступен до 44 минут в месяц. Такие простои не позволительны.

Текущая реализация Auth использует свой протокол аутентификации, не опираясь на стандарты. В большинстве своих сервисов мы используем C# (если говорим о backend) и у нас нет проблем с поддержкой библиотеки для нашего протокола. Но если вдруг появятся сервисы на Python, Go или Rust, разработка и поддержка библиотек под эти языки потребует дополнительных затрат времени и принесет дополнительные сложности.

Текущий Auth использует схему Roles Based Access Control, которая базируется на ролях. Обычно с ролью выдаётся полный доступ к определённому сервису, вместо привязки к конкретному функционалу. Например, в пиццериях есть заместители управляющего, которые могут вести определенные проекты: составлять графики или учитывать сырьё.

Проблемы подтолкнули к тому, чтобы спроектировать и написать новую версию Auth. На старте проекта мы потратили 3 недели только на изучение стандартов авторизации и аутентификации OAuth 2.0 и OpenID Connect 1.0. 

Примечание. Утрированно, статья — это пересказ RFC, который приходилось перечитывать несколько раз, чтобы понять, что происходит вокруг. Здесь я постарался уйти от этой сложности и рассказать всё максимально просто, структурировано, кратко и без описания сложных вещей, например, какие символы может содержать в себе ответ сервиса.

Процесс авторизации

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

Если пользователь не разрешает доступ приложению, пользователь будет
перенаправлен на указанный redirect_uri с ?error=access_denied и
state={state}, если таковой был указан при первом запросе.

Если пользователь авторизован, ему будет показана форма для подтверждения работы под текущим пользователем или смены пользователя.

Регистрация клиента


Способ регистрации клиента, например, ручной или service discovery, вы выбираете сами, в зависимости от

фантазии

конкретной реализации. Но при любом способе при регистрации, кроме ID клиента, должны быть обязательно указаны 2 параметра: redirection URI и client type.

Redirection URI — адрес, на который отправится владелец ресурса после успешной авторизации. Кроме авторизации, адрес используется для подтверждения, что сервис, который обратился за авторизацией, тот, за кого себя выдаёт.

Client type — тип клиента, от которого зависит способ взаимодействия с ним. Тип клиента определяется его возможностью безопасно хранить свои учётные данные для авторизации — токен. Поэтому существует всего 2 типа клиентов:

Способы получения access token

Всего есть 4 способа:

Токены

Токен в OAuth 2.0 — это строка, непрозрачная для клиента. Обычно строка выглядит как случайно сгенерированная — её формат не имеет значения для клиента. Токен — это ключ доступа к чему-либо, например, к защищённому ресурсу (access token) или к новому токену (refresh Token).

У каждого токена своё время жизни. Но у refresh token оно должно быть больше, т.к. он используется для получения access token. Например, если срок жизни access token около часа, то refresh token можно оставить жить на целую неделю. 

Refresh token опционален и доступен только для confedential клиентов. Пользуясь опциональностью токена, в некоторых реализациях время жизни access token сделано очень большим, а refresh token вообще не используется, чтобы не заморачиваться с обновлением.

За access token закреплён определённый набор прав доступа, который выдаётся клиенту во время авторизации. Давайте разберёмся, как выглядят права доступа в OAuth 2.0.

Успешное получение временного authorization_code

В случае разрешения прав, в редиректе будет указан
временный authorization_code:

Вместо вывода

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

Если хотите погрузиться в тематику детальнее, то рекомендую в RFC 6749 (для OAuth 2.0) и RFC 8628 (для Device Flow). Кроме того, следить за актуальными версиями RFC можно на ресурсе, посвящённому OAuth.

Если статья была полезна и захотите подробностей — пишите в комментариях, и в следующих статьях расскажу о PKCE, о протоколе аутентификации OpenID Connect 1.0, о нашей реализации сервера аутентификации и многом другом.

Полезные ссылки:

Похожее:  Получить налоговое уведомление можно в «Личном кабинете налогоплательщика» | ФНС России | 10 Республика Карелия

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *