diff --git a/github/README.MD b/github/README.MD index 08233ad..3e59bac 100644 --- a/github/README.MD +++ b/github/README.MD @@ -8,7 +8,7 @@ Для запуска понадобиться обзавестить своим **GitHub OAuth App**. 1. Переходим в [Developer settings](https://github.com/settings/developers) -2. Создём новое OAuth приложение +2. Создаём новое OAuth приложение ![](docs/1.png) 3. Заполняем обязательно следующие поля - **Homepage URL**: `http://127.0.0.1:8080` diff --git a/settings.gradle b/settings.gradle index 4c71bac..bc1372e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,3 +2,4 @@ rootProject.name = 'spring-oauth2-examples' include('discord') include('github') +include('twitch') diff --git a/twitch/README.MD b/twitch/README.MD new file mode 100644 index 0000000..6c8985b --- /dev/null +++ b/twitch/README.MD @@ -0,0 +1,42 @@ +# Spring Boot + OAuth2 Twitch + +Spring Boot +Spring Boot + +## Перед запуском +### Создание Application +Для запуска понадобиться обзавестить своим **Twitch Application**. + +1. Переходим в [Twitch Developers](https://dev.twitch.tv/console) +2. Создаём новое OAuth приложение + ![](docs/1.png) +3. Заполняем поля + ⚠️ **Внимание!** Есть ряд ограничений. + + Для **Name**: + - Не должен содежрать слово "twitch" + + Для **OAuth Redirect URLs**: + - Если запуск **не** локальный, требуется HTTPS протокол + - Если запуск локальный, то вводить не `127.0.0.1`, а `localhost` + + ![](docs/2.png) +4. После переходим в управление приложением + ![](docs/3.png) +5. Сгенерировать новый **Client Secret** + ![](docs/4.png) + ![](docs/5.png) + +### Настройка Spring +Открываем файл `src/main/resources/application.yml` и указываем там **Client ID** и **Client Secret**: + +```yaml +spring: + security: + oauth2: + client: + registration: + twitch: + client-id: 89fwqw0i5b9857n5orpz3sb3dyfhti + client-secret: mlatyu8twmzq69mx0um1hbahfi7p31 +``` diff --git a/twitch/build.gradle b/twitch/build.gradle new file mode 100644 index 0000000..19982c8 --- /dev/null +++ b/twitch/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'org.springframework.boot' version '2.6.6' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'example.oauth2' +version = '1.0-SNAPSHOT' +sourceCompatibility = JavaVersion.VERSION_11 + +repositories { + mavenCentral() +} + +dependencies { + implementation('org.springframework.boot:spring-boot-starter-web') + implementation('org.springframework.boot:spring-boot-starter-freemarker') + + implementation('org.springframework.boot:spring-boot-starter-security') + implementation('org.springframework.security:spring-security-oauth2-client') +} diff --git a/twitch/docs/1.png b/twitch/docs/1.png new file mode 100644 index 0000000..07aba9e Binary files /dev/null and b/twitch/docs/1.png differ diff --git a/twitch/docs/2.png b/twitch/docs/2.png new file mode 100644 index 0000000..672ada3 Binary files /dev/null and b/twitch/docs/2.png differ diff --git a/twitch/docs/3.png b/twitch/docs/3.png new file mode 100644 index 0000000..5e19a70 Binary files /dev/null and b/twitch/docs/3.png differ diff --git a/twitch/docs/4.png b/twitch/docs/4.png new file mode 100644 index 0000000..24fe5a6 Binary files /dev/null and b/twitch/docs/4.png differ diff --git a/twitch/docs/5.png b/twitch/docs/5.png new file mode 100644 index 0000000..3720813 Binary files /dev/null and b/twitch/docs/5.png differ diff --git a/twitch/docs/twitch.svg b/twitch/docs/twitch.svg new file mode 100644 index 0000000..b9e12a7 --- /dev/null +++ b/twitch/docs/twitch.svg @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/twitch/src/main/java/example/oauth2/twitch/ApplicationTwitch.java b/twitch/src/main/java/example/oauth2/twitch/ApplicationTwitch.java new file mode 100644 index 0000000..7df7ace --- /dev/null +++ b/twitch/src/main/java/example/oauth2/twitch/ApplicationTwitch.java @@ -0,0 +1,13 @@ +package example.oauth2.twitch; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ApplicationTwitch { + + public static void main(String[] args) { + SpringApplication.run(ApplicationTwitch.class, args); + } + +} diff --git a/twitch/src/main/java/example/oauth2/twitch/config/MvcConfig.java b/twitch/src/main/java/example/oauth2/twitch/config/MvcConfig.java new file mode 100644 index 0000000..46f9f7a --- /dev/null +++ b/twitch/src/main/java/example/oauth2/twitch/config/MvcConfig.java @@ -0,0 +1,15 @@ +package example.oauth2.twitch.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class MvcConfig implements WebMvcConfigurer { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/").setViewName("index"); + registry.addViewController("/secret").setViewName("secret"); + } +} diff --git a/twitch/src/main/java/example/oauth2/twitch/config/TwitchOAuth2Config.java b/twitch/src/main/java/example/oauth2/twitch/config/TwitchOAuth2Config.java new file mode 100644 index 0000000..977f24a --- /dev/null +++ b/twitch/src/main/java/example/oauth2/twitch/config/TwitchOAuth2Config.java @@ -0,0 +1,59 @@ +package example.oauth2.twitch.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; + +/* +Отдельное спасибо +- https://www.baeldung.com/spring-security-5-oauth2-login +- https://github.com/spring-projects/spring-security/blob/main/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java +- https://discuss.dev.twitch.tv/t/springboot-oauth2-integration-with-twitch/35011 +- https://www.youtube.com/watch?v=n9oO5D-aHCY + */ + +@Configuration +public class TwitchOAuth2Config { + private static final String TWITCH_CLIENT_PROPERTY_KEY = "spring.security.oauth2.client.registration.twitch"; + private static final String DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}"; + + private final Environment env; + + public TwitchOAuth2Config(Environment env) { + this.env = env; + } + + @Bean + public ClientRegistrationRepository twitchClientRegistrationRepository() { + String clientId = env.getProperty(TWITCH_CLIENT_PROPERTY_KEY + ".client-id"); + String clientSecret = env.getProperty(TWITCH_CLIENT_PROPERTY_KEY + ".client-secret"); + + ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("twitch") + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) + .redirectUri(DEFAULT_REDIRECT_URL) + .scope("user:read:email") + .authorizationUri("https://id.twitch.tv/oauth2/authorize") + .tokenUri("https://id.twitch.tv/oauth2/token") + .userInfoUri("https://id.twitch.tv/oauth2/userinfo") + .userNameAttributeName("preferred_username") + .clientName("Twitch") + .clientId(clientId) + .clientSecret(clientSecret) + .build(); + + return new InMemoryClientRegistrationRepository(clientRegistration); + } + + @Bean + public OAuth2AuthorizedClientService twitchAuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository) { + return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository); + } +} diff --git a/twitch/src/main/java/example/oauth2/twitch/config/WebSecurityConfig.java b/twitch/src/main/java/example/oauth2/twitch/config/WebSecurityConfig.java new file mode 100644 index 0000000..58f6d77 --- /dev/null +++ b/twitch/src/main/java/example/oauth2/twitch/config/WebSecurityConfig.java @@ -0,0 +1,37 @@ +package example.oauth2.twitch.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; + +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + private final ClientRegistrationRepository clientRegistrationRepository; + private final OAuth2AuthorizedClientService authorizedClientService; + + public WebSecurityConfig(ClientRegistrationRepository twitchClientRegistrationRepository, + OAuth2AuthorizedClientService twitchAuthorizedClientService) { + this.clientRegistrationRepository = twitchClientRegistrationRepository; + this.authorizedClientService = twitchAuthorizedClientService; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + //@formatter:off + http + .authorizeRequests() + .antMatchers("/").permitAll() //Доступ разрешен всем пользователей + .anyRequest().authenticated() //Все остальные страницы требуют аутентификации + .and() + .oauth2Login() + .clientRegistrationRepository(clientRegistrationRepository) + .authorizedClientService(authorizedClientService) + ; + //@formatter:on + } +} diff --git a/twitch/src/main/resources/application.yml b/twitch/src/main/resources/application.yml new file mode 100644 index 0000000..ed75233 --- /dev/null +++ b/twitch/src/main/resources/application.yml @@ -0,0 +1,17 @@ +server: + address: 127.0.0.1 + port: 8080 + +debug: false + +spring: + freemarker: + template-loader-path: classpath:/templates + suffix: .ftlh + security: + oauth2: + client: + registration: + twitch: + client-id: 89fwqw0i5b9857n5orpz3sb3dyfhti + client-secret: mlatyu8twmzq69mx0um1hbahfi7p31 diff --git a/twitch/src/main/resources/templates/includes/foother.ftlh b/twitch/src/main/resources/templates/includes/foother.ftlh new file mode 100644 index 0000000..308b1d0 --- /dev/null +++ b/twitch/src/main/resources/templates/includes/foother.ftlh @@ -0,0 +1,2 @@ + + diff --git a/twitch/src/main/resources/templates/includes/header.ftlh b/twitch/src/main/resources/templates/includes/header.ftlh new file mode 100644 index 0000000..e537005 --- /dev/null +++ b/twitch/src/main/resources/templates/includes/header.ftlh @@ -0,0 +1,9 @@ + + + + Twitch OAuth2 Example + + + +

Twitch OAuth2 Example

+
diff --git a/twitch/src/main/resources/templates/index.ftlh b/twitch/src/main/resources/templates/index.ftlh new file mode 100644 index 0000000..3cdd036 --- /dev/null +++ b/twitch/src/main/resources/templates/index.ftlh @@ -0,0 +1,7 @@ +<#include "includes/header.ftlh"> +

+ Home public page
+ ---> Secret Page <---
+ [ Login Twitch ] +

+<#include "includes/foother.ftlh"> diff --git a/twitch/src/main/resources/templates/secret.ftlh b/twitch/src/main/resources/templates/secret.ftlh new file mode 100644 index 0000000..c54425a --- /dev/null +++ b/twitch/src/main/resources/templates/secret.ftlh @@ -0,0 +1,3 @@ +<#include "includes/header.ftlh"> +

[TOP SECRET PAGE]

+<#include "includes/foother.ftlh">