diff --git a/samples/device-client/samples-device-client.gradle b/samples/device-client/samples-device-client.gradle deleted file mode 100644 index 40e714eb..00000000 --- a/samples/device-client/samples-device-client.gradle +++ /dev/null @@ -1,28 +0,0 @@ -plugins { - id "org.springframework.boot" version "3.0.0" - id "io.spring.dependency-management" version "1.0.11.RELEASE" - id "java" -} - -group = project.rootProject.group -version = project.rootProject.version -sourceCompatibility = "17" - -repositories { - mavenCentral() - maven { url "https://repo.spring.io/milestone" } -} - -dependencies { - implementation "org.springframework.boot:spring-boot-starter-web" - implementation "org.springframework.boot:spring-boot-starter-thymeleaf" - implementation "org.springframework.boot:spring-boot-starter-security" - implementation "org.springframework.boot:spring-boot-starter-oauth2-client" - implementation "org.springframework:spring-webflux" - implementation "org.webjars:webjars-locator-core" - implementation "org.webjars:bootstrap:3.4.1" - implementation "org.webjars:jquery:3.4.1" - - testImplementation "org.springframework.boot:spring-boot-starter-test" - testImplementation "org.springframework.security:spring-security-test" -} diff --git a/samples/device-client/src/main/java/sample/DeviceClientApplication.java b/samples/device-client/src/main/java/sample/DeviceClientApplication.java deleted file mode 100644 index b045c6ef..00000000 --- a/samples/device-client/src/main/java/sample/DeviceClientApplication.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2020-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Steve Riesenberg - * @since 1.1 - */ -@SpringBootApplication -public class DeviceClientApplication { - - public static void main(String[] args) { - SpringApplication.run(DeviceClientApplication.class, args); - } - -} diff --git a/samples/device-client/src/main/java/sample/config/SecurityConfig.java b/samples/device-client/src/main/java/sample/config/SecurityConfig.java deleted file mode 100644 index 525189e8..00000000 --- a/samples/device-client/src/main/java/sample/config/SecurityConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2020-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package sample.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -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.config.annotation.web.configuration.WebSecurityCustomizer; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; - -/** - * @author Steve Riesenberg - * @since 1.1 - */ -@Configuration(proxyBeanMethods = false) -@EnableWebSecurity -public class SecurityConfig { - - @Bean - public WebSecurityCustomizer webSecurityCustomizer() { - return (web) -> web.ignoring().requestMatchers("/webjars/**", "/assets/**"); - } - - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/", "/authorize").permitAll() - .anyRequest().authenticated() - ) - .exceptionHandling((exceptions) -> exceptions - .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")) - ) - .oauth2Client(Customizer.withDefaults()); - // @formatter:on - return http.build(); - } - -} diff --git a/samples/device-client/src/main/java/sample/config/WebClientConfig.java b/samples/device-client/src/main/java/sample/config/WebClientConfig.java deleted file mode 100644 index e4b895d0..00000000 --- a/samples/device-client/src/main/java/sample/config/WebClientConfig.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2020-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package sample.config; - -import sample.web.authentication.DeviceCodeOAuth2AuthorizedClientProvider; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; -import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; -import org.springframework.web.reactive.function.client.WebClient; - -/** - * @author Steve Riesenberg - * @since 1.1 - */ -@Configuration -public class WebClientConfig { - - @Bean - public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { - ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = - new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); - // @formatter:off - return WebClient.builder() - .apply(oauth2Client.oauth2Configuration()) - .build(); - // @formatter:on - } - - @Bean - public OAuth2AuthorizedClientManager authorizedClientManager( - ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientRepository authorizedClientRepository) { - - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .provider(new DeviceCodeOAuth2AuthorizedClientProvider()) - .authorizationCode() - .refreshToken() - .build(); - DefaultOAuth2AuthorizedClientManager authorizedClientManager = - new DefaultOAuth2AuthorizedClientManager( - clientRegistrationRepository, authorizedClientRepository); - authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); - // Set a contextAttributesMapper to obtain device_code from the request - authorizedClientManager.setContextAttributesMapper(DeviceCodeOAuth2AuthorizedClientProvider - .deviceCodeContextAttributesMapper()); - - return authorizedClientManager; - } - -} diff --git a/samples/device-client/src/main/java/sample/web/DeviceControllerAdvice.java b/samples/device-client/src/main/java/sample/web/DeviceControllerAdvice.java deleted file mode 100644 index 06a61422..00000000 --- a/samples/device-client/src/main/java/sample/web/DeviceControllerAdvice.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package sample.web; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.oauth2.core.OAuth2AuthorizationException; -import org.springframework.security.oauth2.core.OAuth2Error; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -/** - * @author Steve Riesenberg - * @since 1.1 - */ -@ControllerAdvice -public class DeviceControllerAdvice { - - private static final Set DEVICE_GRANT_ERRORS = new HashSet<>(Arrays.asList( - "authorization_pending", - "slow_down", - "access_denied", - "expired_token" - )); - - @ExceptionHandler(OAuth2AuthorizationException.class) - public ResponseEntity handleError(OAuth2AuthorizationException ex) { - String errorCode = ex.getError().getErrorCode(); - if (DEVICE_GRANT_ERRORS.contains(errorCode)) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ex.getError()); - } - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getError()); - } - -} diff --git a/samples/device-client/src/main/resources/application.yml b/samples/device-client/src/main/resources/application.yml deleted file mode 100644 index 692d4a14..00000000 --- a/samples/device-client/src/main/resources/application.yml +++ /dev/null @@ -1,29 +0,0 @@ -server: - port: 8080 - -logging: - level: - root: INFO - org.springframework.security: trace - -spring: - thymeleaf: - cache: false - security: - oauth2: - client: - registration: - messaging-client-device-grant: - provider: spring - client-id: device-messaging-client - client-authentication-method: none - authorization-grant-type: urn:ietf:params:oauth:grant-type:device_code - scope: message.read,message.write - client-name: messaging-client-device-grant - provider: - spring: - issuer-uri: http://localhost:9000 - authorization-uri: ${spring.security.oauth2.client.provider.spring.issuer-uri}/oauth2/device_authorization - -messages: - base-uri: http://127.0.0.1:8090/messages diff --git a/samples/device-client/src/main/resources/templates/authorized.html b/samples/device-client/src/main/resources/templates/authorized.html deleted file mode 100644 index dd3cca3f..00000000 --- a/samples/device-client/src/main/resources/templates/authorized.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - Device Grant Example - - - - -
-
-
-
-

Success!

-

This device has been activated.

-
-
- Devices -
-
-

Messages:

- - - - - - -
message
-
-
-
-
- - \ No newline at end of file diff --git a/samples/device-client/gradle.properties b/samples/messages-client/gradle.properties similarity index 100% rename from samples/device-client/gradle.properties rename to samples/messages-client/gradle.properties diff --git a/samples/messages-client/src/main/java/sample/config/SecurityConfig.java b/samples/messages-client/src/main/java/sample/config/SecurityConfig.java index 7ab8a457..8379f76a 100644 --- a/samples/messages-client/src/main/java/sample/config/SecurityConfig.java +++ b/samples/messages-client/src/main/java/sample/config/SecurityConfig.java @@ -15,7 +15,6 @@ */ package sample.config; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -31,23 +30,22 @@ import static org.springframework.security.config.Customizer.withDefaults; /** * @author Joe Grandja * @author Dmitriy Dubson + * @author Steve Riesenberg * @since 0.0.1 */ @EnableWebSecurity @Configuration(proxyBeanMethods = false) public class SecurityConfig { - @Autowired - private ClientRegistrationRepository clientRegistrationRepository; - @Bean - WebSecurityCustomizer webSecurityCustomizer() { - return (web) -> web.ignoring().requestMatchers("/webjars/**"); + public WebSecurityCustomizer webSecurityCustomizer() { + return (web) -> web.ignoring().requestMatchers("/webjars/**", "/assets/**"); } // @formatter:off @Bean - SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity http, + ClientRegistrationRepository clientRegistrationRepository) throws Exception { http .authorizeHttpRequests(authorize -> authorize @@ -58,14 +56,15 @@ public class SecurityConfig { oauth2Login.loginPage("/oauth2/authorization/messaging-client-oidc")) .oauth2Client(withDefaults()) .logout(logout -> - logout.logoutSuccessHandler(oidcLogoutSuccessHandler())); + logout.logoutSuccessHandler(oidcLogoutSuccessHandler(clientRegistrationRepository))); return http.build(); } // @formatter:on - private LogoutSuccessHandler oidcLogoutSuccessHandler() { + private LogoutSuccessHandler oidcLogoutSuccessHandler( + ClientRegistrationRepository clientRegistrationRepository) { OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = - new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository); + new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository); // Set the location that the End-User's User Agent will be redirected to // after the logout has been performed at the Provider diff --git a/samples/messages-client/src/main/java/sample/config/WebClientConfig.java b/samples/messages-client/src/main/java/sample/config/WebClientConfig.java index a03d2d13..65f82444 100644 --- a/samples/messages-client/src/main/java/sample/config/WebClientConfig.java +++ b/samples/messages-client/src/main/java/sample/config/WebClientConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ */ package sample.config; +import sample.web.authentication.DeviceCodeOAuth2AuthorizedClientProvider; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; @@ -28,35 +30,47 @@ import org.springframework.web.reactive.function.client.WebClient; /** * @author Joe Grandja + * @author Steve Riesenberg * @since 0.0.1 */ @Configuration public class WebClientConfig { @Bean - WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { + public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); + // @formatter:off return WebClient.builder() .apply(oauth2Client.oauth2Configuration()) .build(); + // @formatter:on } @Bean - OAuth2AuthorizedClientManager authorizedClientManager( + public OAuth2AuthorizedClientManager authorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) { + // @formatter:off OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .authorizationCode() .refreshToken() .clientCredentials() + .provider(new DeviceCodeOAuth2AuthorizedClientProvider()) .build(); + // @formatter:on + DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); + // Set a contextAttributesMapper to obtain device_code from the request + authorizedClientManager.setContextAttributesMapper(DeviceCodeOAuth2AuthorizedClientProvider + .deviceCodeContextAttributesMapper()); + return authorizedClientManager; } + } diff --git a/samples/messages-client/src/main/java/sample/web/AuthorizationController.java b/samples/messages-client/src/main/java/sample/web/AuthorizationController.java index 8fb8326e..22b670bd 100644 --- a/samples/messages-client/src/main/java/sample/web/AuthorizationController.java +++ b/samples/messages-client/src/main/java/sample/web/AuthorizationController.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 the original author or authors. + * Copyright 2020-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,4 +93,10 @@ public class AuthorizationController { return "index"; } + + @GetMapping(value = "/authorize", params = "grant_type=device_code") + public String deviceCodeGrant() { + return "device-activate"; + } + } diff --git a/samples/device-client/src/main/java/sample/web/DeviceController.java b/samples/messages-client/src/main/java/sample/web/DeviceController.java similarity index 85% rename from samples/device-client/src/main/java/sample/web/DeviceController.java rename to samples/messages-client/src/main/java/sample/web/DeviceController.java index a23a55aa..187f3eec 100644 --- a/samples/device-client/src/main/java/sample/web/DeviceController.java +++ b/samples/messages-client/src/main/java/sample/web/DeviceController.java @@ -16,8 +16,11 @@ package sample.web; import java.time.Instant; +import java.util.Arrays; +import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.Set; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -37,7 +40,9 @@ import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2Aut import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.security.oauth2.core.OAuth2AuthorizationException; import org.springframework.security.oauth2.core.OAuth2DeviceCode; +import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository; @@ -46,6 +51,7 @@ import org.springframework.ui.Model; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -61,6 +67,13 @@ import static org.springframework.security.oauth2.client.web.reactive.function.c @Controller public class DeviceController { + private static final Set DEVICE_GRANT_ERRORS = new HashSet<>(Arrays.asList( + "authorization_pending", + "slow_down", + "access_denied", + "expired_token" + )); + private static final ParameterizedTypeReference> TYPE_REFERENCE = new ParameterizedTypeReference<>() {}; @@ -84,17 +97,12 @@ public class DeviceController { this.messagesBaseUri = messagesBaseUri; } - @GetMapping("/") - public String index() { - return "index"; - } - - @GetMapping("/authorize") + @GetMapping("/device_authorize") public String authorize(Model model, HttpServletRequest request, HttpServletResponse response) { // @formatter:off ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId( - "messaging-client-device-grant"); + "messaging-client-device-code"); // @formatter:on MultiValueMap requestParameters = new LinkedMultiValueMap<>(); @@ -102,10 +110,12 @@ public class DeviceController { requestParameters.add(OAuth2ParameterNames.SCOPE, StringUtils.collectionToDelimitedString( clientRegistration.getScopes(), " ")); + String deviceAuthorizationUri = (String) clientRegistration.getProviderDetails().getConfigurationMetadata().get("device_authorization_endpoint"); + // @formatter:off Map responseParameters = this.webClient.post() - .uri(clientRegistration.getProviderDetails().getAuthorizationUri()) + .uri(deviceAuthorizationUri) .headers(headers -> { /* * This sample demonstrates the use of a public client that does not @@ -146,15 +156,15 @@ public class DeviceController { model.addAttribute("verificationUriComplete", responseParameters.get( OAuth2ParameterNames.VERIFICATION_URI_COMPLETE)); - return "authorize"; + return "device-authorize"; } /** - * @see DeviceControllerAdvice + * @see #handleError(OAuth2AuthorizationException) */ - @PostMapping("/authorize") + @PostMapping("/device_authorize") public ResponseEntity poll(@RequestParam(OAuth2ParameterNames.DEVICE_CODE) String deviceCode, - @RegisteredOAuth2AuthorizedClient("messaging-client-device-grant") + @RegisteredOAuth2AuthorizedClient("messaging-client-device-code") OAuth2AuthorizedClient authorizedClient) { /* @@ -175,9 +185,18 @@ public class DeviceController { return ResponseEntity.status(HttpStatus.OK).build(); } - @GetMapping("/authorized") + @ExceptionHandler(OAuth2AuthorizationException.class) + public ResponseEntity handleError(OAuth2AuthorizationException ex) { + String errorCode = ex.getError().getErrorCode(); + if (DEVICE_GRANT_ERRORS.contains(errorCode)) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ex.getError()); + } + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getError()); + } + + @GetMapping("/device_authorized") public String authorized(Model model, - @RegisteredOAuth2AuthorizedClient("messaging-client-device-grant") + @RegisteredOAuth2AuthorizedClient("messaging-client-device-code") OAuth2AuthorizedClient authorizedClient) { String[] messages = this.webClient.get() @@ -188,7 +207,7 @@ public class DeviceController { .block(); model.addAttribute("messages", messages); - return "authorized"; + return "index"; } private void saveSecurityContext(OAuth2DeviceCode deviceCode, HttpServletRequest request, diff --git a/samples/device-client/src/main/java/sample/web/authentication/DeviceCodeOAuth2AuthorizedClientProvider.java b/samples/messages-client/src/main/java/sample/web/authentication/DeviceCodeOAuth2AuthorizedClientProvider.java similarity index 98% rename from samples/device-client/src/main/java/sample/web/authentication/DeviceCodeOAuth2AuthorizedClientProvider.java rename to samples/messages-client/src/main/java/sample/web/authentication/DeviceCodeOAuth2AuthorizedClientProvider.java index 4e75c06c..23fc41cc 100644 --- a/samples/device-client/src/main/java/sample/web/authentication/DeviceCodeOAuth2AuthorizedClientProvider.java +++ b/samples/messages-client/src/main/java/sample/web/authentication/DeviceCodeOAuth2AuthorizedClientProvider.java @@ -50,9 +50,6 @@ public final class DeviceCodeOAuth2AuthorizedClientProvider implements OAuth2Aut private Clock clock = Clock.systemUTC(); - public DeviceCodeOAuth2AuthorizedClientProvider() { - } - public void setAccessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; } diff --git a/samples/device-client/src/main/java/sample/web/authentication/OAuth2DeviceAccessTokenResponseClient.java b/samples/messages-client/src/main/java/sample/web/authentication/OAuth2DeviceAccessTokenResponseClient.java similarity index 100% rename from samples/device-client/src/main/java/sample/web/authentication/OAuth2DeviceAccessTokenResponseClient.java rename to samples/messages-client/src/main/java/sample/web/authentication/OAuth2DeviceAccessTokenResponseClient.java diff --git a/samples/device-client/src/main/java/sample/web/authentication/OAuth2DeviceGrantRequest.java b/samples/messages-client/src/main/java/sample/web/authentication/OAuth2DeviceGrantRequest.java similarity index 98% rename from samples/device-client/src/main/java/sample/web/authentication/OAuth2DeviceGrantRequest.java rename to samples/messages-client/src/main/java/sample/web/authentication/OAuth2DeviceGrantRequest.java index 7a4172cd..4ec72a1f 100644 --- a/samples/device-client/src/main/java/sample/web/authentication/OAuth2DeviceGrantRequest.java +++ b/samples/messages-client/src/main/java/sample/web/authentication/OAuth2DeviceGrantRequest.java @@ -35,7 +35,7 @@ public final class OAuth2DeviceGrantRequest extends AbstractOAuth2AuthorizationG } public String getDeviceCode() { - return deviceCode; + return this.deviceCode; } } diff --git a/samples/messages-client/src/main/resources/application.yml b/samples/messages-client/src/main/resources/application.yml index a7f212dd..f39ef426 100644 --- a/samples/messages-client/src/main/resources/application.yml +++ b/samples/messages-client/src/main/resources/application.yml @@ -7,7 +7,6 @@ logging: org.springframework.web: INFO org.springframework.security: INFO org.springframework.security.oauth2: INFO -# org.springframework.boot.autoconfigure: DEBUG spring: thymeleaf: @@ -39,6 +38,13 @@ spring: authorization-grant-type: client_credentials scope: message.read,message.write client-name: messaging-client-client-credentials + messaging-client-device-code: + provider: spring + client-id: device-messaging-client + client-authentication-method: none + authorization-grant-type: urn:ietf:params:oauth:grant-type:device_code + scope: message.read,message.write + client-name: messaging-client-device-code provider: spring: issuer-uri: http://localhost:9000 diff --git a/samples/device-client/src/main/resources/static/assets/css/style.css b/samples/messages-client/src/main/resources/static/assets/css/style.css similarity index 100% rename from samples/device-client/src/main/resources/static/assets/css/style.css rename to samples/messages-client/src/main/resources/static/assets/css/style.css diff --git a/samples/device-client/src/main/resources/templates/index.html b/samples/messages-client/src/main/resources/templates/device-activate.html similarity index 84% rename from samples/device-client/src/main/resources/templates/index.html rename to samples/messages-client/src/main/resources/templates/device-activate.html index b91baa39..22a30ad8 100644 --- a/samples/device-client/src/main/resources/templates/index.html +++ b/samples/messages-client/src/main/resources/templates/device-activate.html @@ -13,8 +13,8 @@

Activation Required

-

You must activate this device. Please log in to continue.

- Log In +

You must activate this device.

+ Activate
Devices @@ -23,4 +23,4 @@
- \ No newline at end of file + diff --git a/samples/device-client/src/main/resources/templates/authorize.html b/samples/messages-client/src/main/resources/templates/device-authorize.html similarity index 95% rename from samples/device-client/src/main/resources/templates/authorize.html rename to samples/messages-client/src/main/resources/templates/device-authorize.html index 01d497e6..e378ab9b 100644 --- a/samples/device-client/src/main/resources/templates/authorize.html +++ b/samples/messages-client/src/main/resources/templates/device-authorize.html @@ -17,7 +17,7 @@

Activation Code

-
+
@@ -35,7 +35,7 @@ let csrfToken = $('[name=_csrf]').val(); if (deviceCode) { $.ajax({ - url: '/authorize', + url: '/device_authorize', method: 'POST', data: { device_code: deviceCode, @@ -58,7 +58,7 @@ clear(); location.href = '/'; } - }).done(() => window.location.href = '/authorized'); + }).done(() => window.location.href = '/device_authorized'); } } @@ -84,4 +84,4 @@ window.addEventListener('load', schedule); - \ No newline at end of file + diff --git a/samples/messages-client/src/main/resources/templates/index.html b/samples/messages-client/src/main/resources/templates/index.html index 23085c1d..0d162b0c 100644 --- a/samples/messages-client/src/main/resources/templates/index.html +++ b/samples/messages-client/src/main/resources/templates/index.html @@ -30,11 +30,14 @@