Polish samples
Closes gh-1157
This commit is contained in:
@@ -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.annotation.RegisteredOAuth2AuthorizedClient;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
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.OAuth2DeviceCode;
|
||||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||||
@@ -105,8 +106,22 @@ public class DeviceController {
|
|||||||
Map<String, Object> responseParameters =
|
Map<String, Object> responseParameters =
|
||||||
this.webClient.post()
|
this.webClient.post()
|
||||||
.uri(clientRegistration.getProviderDetails().getAuthorizationUri())
|
.uri(clientRegistration.getProviderDetails().getAuthorizationUri())
|
||||||
// .headers(headers -> headers.setBasicAuth(clientRegistration.getClientId(),
|
.headers(headers -> {
|
||||||
// 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 Device Authorization Request with a clientId/clientSecret.
|
||||||
|
*/
|
||||||
|
if (!clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) {
|
||||||
|
headers.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret());
|
||||||
|
}
|
||||||
|
})
|
||||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
.body(BodyInserters.fromFormData(requestParameters))
|
.body(BodyInserters.fromFormData(requestParameters))
|
||||||
.retrieve()
|
.retrieve()
|
||||||
@@ -142,19 +157,21 @@ public class DeviceController {
|
|||||||
@RegisteredOAuth2AuthorizedClient("messaging-client-device-grant")
|
@RegisteredOAuth2AuthorizedClient("messaging-client-device-grant")
|
||||||
OAuth2AuthorizedClient authorizedClient) {
|
OAuth2AuthorizedClient authorizedClient) {
|
||||||
|
|
||||||
// The client will repeatedly poll until authorization is granted.
|
/*
|
||||||
//
|
* 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 OAuth2AuthorizedClientManager uses the device_code parameter
|
||||||
// the user has granted authorization.
|
* 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 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.
|
* If the device code expires, expired_token is returned and polling
|
||||||
//
|
* should stop.
|
||||||
// This endpoint simply returns 200 OK when client is authorized.
|
*
|
||||||
|
* This endpoint simply returns 200 OK when the client is authorized.
|
||||||
|
*/
|
||||||
return ResponseEntity.status(HttpStatus.OK).build();
|
return ResponseEntity.status(HttpStatus.OK).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.springframework.http.converter.FormHttpMessageConverter;
|
|||||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||||
import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
|
import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
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.OAuth2AuthorizationException;
|
||||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||||
@@ -58,7 +59,20 @@ public final class OAuth2DeviceAccessTokenResponseClient implements OAuth2Access
|
|||||||
ClientRegistration clientRegistration = deviceGrantRequest.getClientRegistration();
|
ClientRegistration clientRegistration = deviceGrantRequest.getClientRegistration();
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
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<>();
|
MultiValueMap<String, Object> requestParameters = new LinkedMultiValueMap<>();
|
||||||
requestParameters.add(OAuth2ParameterNames.GRANT_TYPE, deviceGrantRequest.getGrantType().getValue());
|
requestParameters.add(OAuth2ParameterNames.GRANT_TYPE, deviceGrantRequest.getGrantType().getValue());
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package sample.authentication;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import sample.web.authentication.DeviceClientAuthenticationConverter;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
import org.springframework.security.core.Authentication;
|
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.core.endpoint.OAuth2ParameterNames;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
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.client.RegisteredClientRepository;
|
||||||
|
import org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter;
|
||||||
import org.springframework.util.Assert;
|
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 {
|
public final class DeviceClientAuthenticationProvider implements AuthenticationProvider {
|
||||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1";
|
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1";
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|||||||
@@ -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.authentication.OAuth2ClientAuthenticationToken;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @author Steve Riesenberg
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
@Transient
|
@Transient
|
||||||
public class DeviceClientAuthenticationToken extends OAuth2ClientAuthenticationToken {
|
public class DeviceClientAuthenticationToken extends OAuth2ClientAuthenticationToken {
|
||||||
|
|
||||||
|
|||||||
@@ -74,20 +74,40 @@ public class SecurityConfig {
|
|||||||
HttpSecurity http, RegisteredClientRepository registeredClientRepository,
|
HttpSecurity http, RegisteredClientRepository registeredClientRepository,
|
||||||
AuthorizationServerSettings authorizationServerSettings) throws Exception {
|
AuthorizationServerSettings authorizationServerSettings) throws Exception {
|
||||||
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
|
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)
|
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
|
||||||
.deviceAuthorizationEndpoint((deviceAuthorizationEndpoint) -> deviceAuthorizationEndpoint
|
.deviceAuthorizationEndpoint((deviceAuthorizationEndpoint) -> deviceAuthorizationEndpoint
|
||||||
.verificationUri("/activate")
|
.verificationUri("/activate")
|
||||||
)
|
)
|
||||||
.clientAuthentication((clientAuthentication) ->
|
.clientAuthentication((clientAuthentication) -> clientAuthentication
|
||||||
clientAuthentication
|
.authenticationConverter(deviceClientAuthenticationConverter)
|
||||||
.authenticationConverter(
|
.authenticationProvider(deviceClientAuthenticationProvider)
|
||||||
new DeviceClientAuthenticationConverter(
|
|
||||||
authorizationServerSettings.getDeviceAuthorizationEndpoint()))
|
|
||||||
.authenticationProvider(
|
|
||||||
new DeviceClientAuthenticationProvider(
|
|
||||||
registeredClientRepository))
|
|
||||||
)
|
)
|
||||||
.oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
|
.oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
package sample.web.authentication;
|
package sample.web.authentication;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import sample.authentication.DeviceClientAuthenticationToken;
|
import sample.authentication.DeviceClientAuthenticationToken;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
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.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @author Steve Riesenberg
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
public final class DeviceClientAuthenticationConverter implements AuthenticationConverter {
|
public final class DeviceClientAuthenticationConverter implements AuthenticationConverter {
|
||||||
private final RequestMatcher deviceAuthorizationRequestMatcher;
|
private final RequestMatcher deviceAuthorizationRequestMatcher;
|
||||||
private final RequestMatcher deviceAccessTokenRequestMatcher;
|
private final RequestMatcher deviceAccessTokenRequestMatcher;
|
||||||
|
|||||||
Reference in New Issue
Block a user