Explorar o código

Polish samples

Closes gh-1157
Steve Riesenberg %!s(int64=2) %!d(string=hai) anos
pai
achega
7c166a3a72

+ 32 - 15
samples/device-client/src/main/java/sample/web/DeviceController.java

@@ -36,6 +36,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
 import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
 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.OAuth2DeviceCode;
 import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
 import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
@@ -105,8 +106,22 @@ public class DeviceController {
 		Map<String, Object> responseParameters =
 				this.webClient.post()
 						.uri(clientRegistration.getProviderDetails().getAuthorizationUri())
-//						.headers(headers -> headers.setBasicAuth(clientRegistration.getClientId(),
-//								clientRegistration.getClientSecret()))
+						.headers(headers -> {
+							/*
+							 * This sample demonstrates the use of a public client that does not
+							 * store credentials or authenticate with the authorization server.
+							 *
+							 * See DeviceClientAuthenticationProvider in the authorization server
+							 * sample for an example customization that allows public clients.
+							 *
+							 * For a confidential client, change the client-authentication-method to
+							 * client_secret_basic and set the client-secret to send the
+							 * OAuth 2.0 Device Authorization Request with a clientId/clientSecret.
+							 */
+							if (!clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) {
+								headers.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret());
+							}
+						})
 						.contentType(MediaType.APPLICATION_FORM_URLENCODED)
 						.body(BodyInserters.fromFormData(requestParameters))
 						.retrieve()
@@ -142,19 +157,21 @@ public class DeviceController {
 			@RegisteredOAuth2AuthorizedClient("messaging-client-device-grant")
 					OAuth2AuthorizedClient authorizedClient) {
 
-		// The client will repeatedly poll until authorization is granted.
-		//
-		// The OAuth2AuthorizedClientManager uses the device_code parameter
-		// to make a token request, which returns authorization_pending until
-		// the user has granted authorization.
-		//
-		// If the user has denied authorization, access_denied is returned and
-		// polling should stop.
-		//
-		// If the device code expires, expired_token is returned and polling
-		// should stop.
-		//
-		// This endpoint simply returns 200 OK when client is authorized.
+		/*
+		 * The client will repeatedly poll until authorization is granted.
+		 *
+		 * The OAuth2AuthorizedClientManager uses the device_code parameter
+		 * to make a token request, which returns authorization_pending until
+		 * the user has granted authorization.
+		 *
+		 * If the user has denied authorization, access_denied is returned and
+		 * polling should stop.
+		 *
+		 * If the device code expires, expired_token is returned and polling
+		 * should stop.
+		 *
+		 * This endpoint simply returns 200 OK when the client is authorized.
+		 */
 		return ResponseEntity.status(HttpStatus.OK).build();
 	}
 

+ 15 - 1
samples/device-client/src/main/java/sample/web/authentication/OAuth2DeviceAccessTokenResponseClient.java

@@ -23,6 +23,7 @@ import org.springframework.http.converter.FormHttpMessageConverter;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
+import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
@@ -58,7 +59,20 @@ public final class OAuth2DeviceAccessTokenResponseClient implements OAuth2Access
 		ClientRegistration clientRegistration = deviceGrantRequest.getClientRegistration();
 
 		HttpHeaders headers = new HttpHeaders();
-//		headers.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret());
+		/*
+		 * This sample demonstrates the use of a public client that does not
+		 * store credentials or authenticate with the authorization server.
+		 *
+		 * See DeviceClientAuthenticationProvider in the authorization server
+		 * sample for an example customization that allows public clients.
+		 *
+		 * For a confidential client, change the client-authentication-method
+		 * to client_secret_basic and set the client-secret to send the
+		 * OAuth 2.0 Token Request with a clientId/clientSecret.
+		 */
+		if (!clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) {
+			headers.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret());
+		}
 
 		MultiValueMap<String, Object> requestParameters = new LinkedMultiValueMap<>();
 		requestParameters.add(OAuth2ParameterNames.GRANT_TYPE, deviceGrantRequest.getGrantType().getValue());

+ 10 - 0
samples/device-grant-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationProvider.java

@@ -17,6 +17,7 @@ package sample.authentication;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import sample.web.authentication.DeviceClientAuthenticationConverter;
 
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
@@ -28,8 +29,17 @@ import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
 import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
+import org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter;
 import org.springframework.util.Assert;
 
+/**
+ * @author Joe Grandja
+ * @author Steve Riesenberg
+ * @since 1.1
+ * @see DeviceClientAuthenticationToken
+ * @see DeviceClientAuthenticationConverter
+ * @see OAuth2ClientAuthenticationFilter
+ */
 public final class DeviceClientAuthenticationProvider implements AuthenticationProvider {
 	private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1";
 	private final Log logger = LogFactory.getLog(getClass());

+ 5 - 0
samples/device-grant-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationToken.java

@@ -23,6 +23,11 @@ import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 
+/**
+ * @author Joe Grandja
+ * @author Steve Riesenberg
+ * @since 1.1
+ */
 @Transient
 public class DeviceClientAuthenticationToken extends OAuth2ClientAuthenticationToken {
 

+ 28 - 8
samples/device-grant-authorizationserver/src/main/java/sample/config/SecurityConfig.java

@@ -74,20 +74,40 @@ public class SecurityConfig {
 			HttpSecurity http, RegisteredClientRepository registeredClientRepository,
 			AuthorizationServerSettings authorizationServerSettings) throws Exception {
 		OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
+
+		/*
+		 * This sample demonstrates the use of a public client that does not
+		 * store credentials or authenticate with the authorization server.
+		 *
+		 * The following components show how to customize the authorization
+		 * server to allow for device clients to perform requests to the
+		 * OAuth 2.0 Device Authorization Endpoint and Token Endpoint without
+		 * a clientId/clientSecret.
+		 *
+		 * CAUTION: These endpoints will not require any authentication, and can
+		 * be accessed by any client that has a valid clientId.
+		 *
+		 * It is therefore RECOMMENDED to carefully monitor the use of these
+		 * endpoints and employ any additional protections as needed, which is
+		 * outside the scope of this sample.
+		 */
+		DeviceClientAuthenticationConverter deviceClientAuthenticationConverter =
+				new DeviceClientAuthenticationConverter(
+						authorizationServerSettings.getDeviceAuthorizationEndpoint());
+		DeviceClientAuthenticationProvider deviceClientAuthenticationProvider =
+				new DeviceClientAuthenticationProvider(registeredClientRepository);
+
+		// @formatter:off
 		http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
 			.deviceAuthorizationEndpoint((deviceAuthorizationEndpoint) -> deviceAuthorizationEndpoint
 				.verificationUri("/activate")
 			)
-			.clientAuthentication((clientAuthentication) ->
-				clientAuthentication
-					.authenticationConverter(
-						new DeviceClientAuthenticationConverter(
-							authorizationServerSettings.getDeviceAuthorizationEndpoint()))
-					.authenticationProvider(
-						new DeviceClientAuthenticationProvider(
-							registeredClientRepository))
+			.clientAuthentication((clientAuthentication) -> clientAuthentication
+				.authenticationConverter(deviceClientAuthenticationConverter)
+				.authenticationProvider(deviceClientAuthenticationProvider)
 			)
 			.oidc(Customizer.withDefaults());	// Enable OpenID Connect 1.0
+		// @formatter:on
 
 		// @formatter:off
 		http

+ 5 - 1
samples/device-grant-authorizationserver/src/main/java/sample/web/authentication/DeviceClientAuthenticationConverter.java

@@ -16,7 +16,6 @@
 package sample.web.authentication;
 
 import jakarta.servlet.http.HttpServletRequest;
-
 import sample.authentication.DeviceClientAuthenticationToken;
 
 import org.springframework.http.HttpMethod;
@@ -33,6 +32,11 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.util.StringUtils;
 
+/**
+ * @author Joe Grandja
+ * @author Steve Riesenberg
+ * @since 1.1
+ */
 public final class DeviceClientAuthenticationConverter implements AuthenticationConverter {
 	private final RequestMatcher deviceAuthorizationRequestMatcher;
 	private final RequestMatcher deviceAccessTokenRequestMatcher;