↩️ «выйди и снова зайди, только правильно». всё ли вы знаете об oauth 2.0?

Authorization code grand

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

Client credentials

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

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

Implicit grant

Теперь у нас сайт без бэкенда – SPA.

Oauth-авторизация с помощью api яндекс id

API Яндекс ID также использует открытый протокол авторизации OAuth 2.0. Для доступа к данным пользователей разработчику необходимо зарегистрировать своё приложение на сервисе Яндекс.OAuth, реализовать получение и обработку OAuth-токенов, а затем предоставить пользователям интерфейс входа через Яндекс.

При использовании OAuth-протокола пользователь не вводит свой пароль на другом сайте, поэтому учётная запись надёжно защищена и не может быть скомпрометирована. Таким образом пользователи Яндекса могут зарегистрироваться и войти в свой аккаунт на стороннем сайте, не заводя новую учётную запись.

Open api для авторизации пользователей вконтакте

Open API — это система, которая предоставляет пользователям ВКонтакте возможность авторизовываться на вашем сайте. Перед началом работы с Open API необходимо создать новое приложение с типом «Веб-сайт» или «Standalone» и следовать дальнейшим указаниям помощника.

Это приложение позволяет использовать на сайте все текущие методы ВКонтакте API и упрощает регистрацию новых пользователей, если у них уже есть учётная запись ВКонтакте. SDK (Software Development Kit) содержит готовые реализации основных функций API, библиотеки для популярных платформ используют авторизацию OAuth 2.0 для взаимодействия с API.

Вход через сбер id

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

Похожее:  Как зарегистрироваться в Твиче: регистрация на русском в twitch.tv

Протокол взаимодействия между клиентом и партнёром разработан на основе стандарта OpenID Connect. Таким образом пользователи получают возможность войти на сайт партнёра банка по кнопке Сбер ID, а партнёры — настроить простую и быструю аутентификацию.

Для чего это нужно

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

Параллельно с этим в интернете есть сервисы, которыми пользуются все: Яндекс, Гугл, фейсбук или Вконтакте. Почему бы не брать данные о пользователе с этих сервисов?

Для этого и придумали OAuth.

Заглянем под капот oauth

Выше мы обсудили абстрактный
дизайн OAuth. Внутри этой системы существуют также области и токены, разрешения и потоки. Разберемся детальнее.

Использование oauth 2.0 для доступа к api google

Google API используют протокол OAuth 2.0 для аутентификации и авторизации. Google поддерживает работу с веб-серверами и клиентскими приложениями. Реализация сценария аутентификации соответствует спецификации OpenID Connect и прошла сертификацию в OpenID Foundation.

Для начала работы необходимо получить учетные данные клиента OAuth 2.0 в консоли Google API. Затем ваш сайт или приложение запрашивает токен доступа с сервера авторизации Google, извлекает токен из ответа и отправляет его в API Google, к которому вы хотите получить доступ. Разработчикам доступна для экспериментов тестовая площадка OAuth 2.0 Playground.

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

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

Можно ли этому доверять?

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

⚠️ Во всех важных сервисах включайте двухфакторную авторизацию: чтобы не только вводить пароль, но и получать СМС.

Области и токены oauth

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

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

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

Условно можно выделить
четыре типа областей:

  • доступ для чтения;
  • доступ на запись;
  • доступ для чтения и записи;
  • без доступа.

Определение области действия – мощный инструмент для определения того, какой
уровень допуска к пользовательским данным разрешен третьим лицам. Чтобы понять,
как это можно использовать, прочитайте документацию Slack и Google,
которые демонстрируют различные вариации параметров настройки.

Пример: github sso

Изучим описанные
концепции на примере. Teleport – опенсорсный
инструмент удаленного доступа, позволяющий юзерам входить в систему через
Github single sign-on (SSO) с использованием OAuth. Действующиелица:

Рис. 4. Поток разрешения авторизации
Рис. 4. Поток разрешения авторизации

Рассмотрим поток шаг за шагом.

Шаг 1. Пользователь Teleport получает доступ к приложению Teleport.

Шаг 2. Приложение предлагает пользователю Teleport войти с помощью Github SSO.

Разрешения и потоки oauth

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

  • приехать к кинотеатру;
  • войти в него;
  • пройти к кассе;
  • найти сеанс;
  • пообщаться с сотрудником кассы;
  • оплатить;
  • получить билет.

Покупка
онлайн:

  • перейти на сайт театра;
  • найти сеанс;
  • добавить билет в заказ;
  • оплатить;
  • получить билет на e-mail.

Разрешения (grants) диктуют клиенту порядок операций по получению access-токена. Этот уникальный порядок называется потоком.

Вся коммуникация между владельцем ресурса,
клиентом и сервером авторизации происходит через строки запроса с параметрами. В этих параметрах содержится информация,
необходимая серверу авторизации для понимания того, какому потоку следовать:

  • Код разрешения авторизации (Authorization Code Grant) – наиболее распространенный тип разрешений (Рис. 4). Клиент получает уникальный код, выданный сервером авторизации, который затем обменивается на токен.
  • Код разрешения авторизации с PKCE – этот вариант используется для публичных клиентов, которым нельзя доверять хранение учетных данных. Используя расширение PKCE (Public Key for Code Exchange), клиент и сервер обмениваются хэшем, чтобы убедиться, что связь не скомпрометирована.
  • Учетные данные клиента – иногда клиенты запрашивают доступ для себя, а не для владельца ресурса. Эти экземпляры используют внутренние службы, которым требуется доступ к облачному хранилищу. В этом случае клиент сделает запрос, включающий client_id и client_secret, которые сервер авторизации проверяет для выдачи access-токенов. Этот тип разрешений должен использоваться только с конфиденциальными клиентами.
  • Код устройства – используется для устройств, подключенных к интернету, которые не имеют браузеров или снабжены неудобными виртуальными клавиатурами, например, игровая консоль или Smart TV.

Реализация сервера авторизации oauth с помощью сервера авторизации spring

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

Сервер авторизации в OAuth предназначен для выдачи маркера доступа, который позволяет клиентскому приложению использовать этот маркер доступа для запроса ресурса, который ему нужно получить. Сервер ресурсов будет подтверждать этот маркер доступа с помощью сервера авторизации каждый раз, когда клиентское приложение запрашивает ресурс, чтобы определить, следует ли разрешить клиентскому приложению доступ к этому ресурсу. Вы можете использовать множество различных открытых источников, таких как Keycloak, Spring Security OAuth (устаревший), или же новый проект Spring под названием Spring Authorization Server для реализации этого сервера авторизации. В этом руководстве я покажу вам, как использовать сервер авторизации Spring (Spring Authorization Server) для реализации сервера авторизации OAuth (OAuth Authorization Server)!

Сначала я создам новый проект Spring Boot с Web Starter, Security Starter:

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

и сервер авторизации Spring:

<dependency>
    <groupId>org.springframework.security.experimental</groupId>
    <artifactId>spring-security-oauth2-authorization-server</artifactId>
    <version>0.1.2</version>
</dependency>

для примера.

Результат:

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

Конфигурация сервера авторизации

Сначала я создам новый класс AuthorizationServerConfiguration для настройки сервера авторизации.

По умолчанию сервер авторизации Spring  поддерживает класс OAuth2AuthorizationServerConfiguration с конфигурациями по умолчанию для сервера авторизации. Если взглянуть на код этого класса, то можно увидеть, что он определяет метод applyDefaultSecurity(), который инициализирует объект OAuth2AuthorizationServerConfigurer с целью применения конфигураций по умолчанию, которые определяет этот класс OAuth2AuthorizationServerConfigurer:

public static void applyDefaultSecurity(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
            new OAuth2AuthorizationServerConfigurer<>();
    RequestMatcher endpointsMatcher = authorizationServerConfigurer
            .getEndpointsMatcher();

    http
        .requestMatcher(endpointsMatcher)
        .authorizeRequests(authorizeRequests ->
            authorizeRequests.anyRequest().authenticated()
        )
        .csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
        .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
        .apply(authorizationServerConfigurer);
}

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

Класс OAuth2AuthorizationServerConfiguration также определяет бин (bean) для класса SecurityFilterChain, который вызывает метод applyDefaultSecurity() для регистрации этих конфигураций по умолчанию в Spring Security сервера авторизации.

Вы можете импортировать этот класс OAuth2AuthorizationServerConfiguration с помощью аннотации Spring @Import, чтобы использовать эти конфигурации по умолчанию:

package com.huongdanjava.springauthorizationserver;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;

@Configuration
@Import(OAuth2AuthorizationServerConfiguration.class)
public class AuthorizationServerConfiguration {

}

или если вы хотите добавить что-то из пользовательского кода, то давайте объявим бин для класса SecurityFilterChain и вызовем метод applyDefaultSecurity() следующим образом:

package com.huongdanjava.springauthorizationserver;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class AuthorizationServerConfiguration {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

        return http.formLogin(Customizer.withDefaults()).build();
    }

}

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

При использовании сервера авторизации нам важно определить веб-ключ JSON для проверки информации в маркере доступа, который пользователь запросил у сервера ресурсов, выданном сервером авторизации. Для завершения настройки этого сервера авторизации требуется бин JwtDecoder с объектом класса JWKSource. Мы можем определить бины для этих объектов следующим образом:

@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
    return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}

@Bean
public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {
    RSAKey rsaKey = generateRsa();
    JWKSet jwkSet = new JWKSet(rsaKey);

    return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}

private static RSAKey generateRsa() throws NoSuchAlgorithmException {
    KeyPair keyPair = generateRsaKey();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

    return new RSAKey.Builder(publicKey)
        .privateKey(privateKey)
        .keyID(UUID.randomUUID().toString())
        .build();
}

private static KeyPair generateRsaKey() throws NoSuchAlgorithmException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048);

    return keyPairGenerator.generateKeyPair();
}

Конфигурация Spring Security

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

Мы можем определить SecurityFilterChain следующим образом:

package com.huongdanjava.springauthorizationserver;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
public class SpringSecurityConfiguration {

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests(authorizeRequests ->
                authorizeRequests.anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults());

        return http.build();
    }

}

На этом этапе страница входа будет отображаться, если пользователь не вошел в систему.

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

Сервер авторизации Spring использует класс RegisteredClient для объявления информации клиента, зарегистрированного на сервере авторизации, и реализует интерфейс RegisteredClientRepository для хранения информации всех этих клиентов.

Мы можем объявить информацию о клиенте, используя память или соответствующую базу данных:

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

Для простоты я буду использовать память следующим образом:

@Bean
public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
        .clientId("huongdanjava")
        .clientSecret("{noop}123456")
        .clientAuthenticationMethod(ClientAuthenticationMethod.POST)
        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
        .redirectUri("https://oidcdebugger.com/debug")
        .scope(OidcScopes.OPENID)
        .build();

    return new InMemoryRegisteredClientRepository(registeredClient);
}

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

Что такое идентификатор клиента, объяснять не нужно! По поводу типа гранта авторизации, следует отметить, что сервер авторизации Spring поддерживает все типы грантов OAuth 2.

Секрет клиента зависит от типа клиента, который мы хотим определить, если наш клиент конфиденциальный, см. также Типы клиентов в OAuth 2.0, то секрет клиента обязателен. Здесь вам нужно объявить, как зашифровать клиентский секрет с помощью PasswordEncoder, если вы не хотите шифровать его в целях тестирования, то можно использовать NoOpPasswordEncoder, объявив “{noop}” в начале клиентского секрета, как я сделал выше. Помните, что это применяется только в тестовых целях!

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

В зависимости от типа гранта клиента, который вы определяете, есть и другая необходимая информация, которую нам нужно объявить. Например, в моем случае я определяю клиента с типом разрешения authorization_code, поэтому мне нужно определить redirect_uri. Здесь я буду использовать инструмент https://oidcdebugger.com/ для получения кода авторизации, поэтому я определяю redirect_uri со значением https://oidcdebugger.com/debug, как это можно видеть в примере.

В зависимости от ваших потребностей, давайте определим информацию о клиенте соответствующим образом.

Регистрация пользователя на сервере авторизации

Для регистрации пользователя на сервере авторизации используется память со следующим объявлением:

@Bean
public UserDetailsService users() {
    UserDetails user = User.withDefaultPasswordEncoder()
        .username("admin")
        .password("password")
        .roles("ADMIN")
        .build();

    return new InMemoryUserDetailsManager(user);
}

Итак, на данном этапе мы завершили базовую конфигурацию для Authorization Server.

Чтобы проверить результаты, я воспользуюсь инструментом https://oidcdebugger.com/, как упоминалось выше, со следующим объявлением:

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

Нажмите кнопку Send request (Отправить запрос) на этой странице, после чего вы откроете страницу входа на сервер авторизации, которая будет выглядеть следующим образом:

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

Войдите в систему с информацией, которую мы объявили выше, и увидите следующие результаты:

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

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

↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?

Материал подготовлен в рамках курса «Разработчик на Spring Framework». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

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

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

Терминология oauth

Разберем несколько
общих терминов. Для упрощения под OAuth будем подразумевать OAuth 2.0.

Функционирование протокола oauth

OAuth создан для
предоставления сторонним приложениям ограниченного доступа к защищенным
ресурсам без риска для данных пользователя. Это похоже на то, как работает режим
Valet Mode в Tesla.

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

Заключение

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

***

Если вы увлеклись веб-разработкой, но ищите помощь наставника, мы советуем обратить внимание накурс факультета Веб-разработки GeekBrains, где вы получите готовую базу навыков и необходимую поддержку. Кстати, на курсе большое внимание уделяется безопасности как клиентской, так и серверной части веб-приложения.

https://www.youtube.com/watch?v=CmhQ1iLFhWU

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

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

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