Spring Security OAuth 2.0: el secreto del cliente siempre se requiere para la concesión del código de autorización
Según la especificación, las solicitudes de un token que utilizan la concesión del código de autorización no necesitan ser autenticadas siempre que esté client_id
incluido en la solicitud y sea el client_id
mismo que se utilizó para generar el código. Sin embargo, con la implementación de Spring Security OAuth 2.0, parece que siempre se requiere autenticación básica en el/oauth/token
punto final, incluso si al cliente nunca se le asignó un secreto.
Parece que hay soporte para permitir clientes sin secreto debido al isSecretRequired()
método en la ClientDetails
interfaz. ¿Qué debo hacer para permitir que los clientes sin un secreto se autentiquen en la /oauth/token
URL?
4.1.3. Solicitud de token de acceso
El cliente realiza una solicitud al punto final del token enviando los
siguientes parámetros utilizando el formato "application/x-www-form-urlencoded"
según el Apéndice B con una codificación de caracteres UTF-8 en HTTP.
cuerpo de entidad de la solicitud HTTP:tipo_concesión OBLIGATORIO. El valor DEBE establecerse en "código_autorización".
código OBLIGATORIO. El código de autorización recibido del servidor de autorización.
redirigir_uri OBLIGATORIO, si el parámetro "redirect_uri" se incluyó en la solicitud de autorización como se describe en la Sección 4.1.1, y sus valores DEBEN ser idénticos.
client_id OBLIGATORIO, si el cliente no se autentica con el servidor de autorización como se describe en la Sección 3.2.1.
Si el tipo de cliente es confidencial o al cliente se le emitieron credenciales de cliente (o se le asignaron otros requisitos de autenticación), el
cliente DEBE autenticarse con el servidor de autorización como se describe
en la Sección 3.2.1.
La autenticación del cliente mediante los parámetros del formulario en lugar de la autenticación básica se habilita mediante el allowFormAuthenticationForClients()
método que se muestra en el ejemplo de código siguiente.
class AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
@Override
void configure(AuthorizationServerSecurityConfigurer security) {
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients()
}
}
El allowFormAuthenticationForClients()
método desencadena la adición de lo ClientCredentialsTokenEndpointFilter
que permite la autenticación a través de parámetros de formulario.
Spring le permite definir clientes OAuth2 con un secreto vacío. Estos pueden considerarse clientes "públicos" o clientes que no pueden guardar un secreto. Piense en aplicaciones Javascript, aplicaciones móviles, etc. Por lo general, no desea tener secretos de clientes almacenados allí.
Como usted señala, de acuerdo con la especificación OAuth2, un punto final token puede optar por no requerir un secreto para estos clientes públicos.
Entonces, en Spring, simplemente defina un cliente OAuth2 con un secreto vacío y configúrelo para un conjunto limitado de tipos de concesión (código_autorización y token_actualización).
La URL del token de implementación de Spring Security aceptará un intercambio de tokens sin un secreto de cliente para ese cliente OAuth2 en particular.
Para resolver el problema, consulte el método loadUserByUsername
de clase org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService
:
if (clientSecret == null || clientSecret.trim().length() == 0) {
clientSecret = this.emptyPassword;
}
Probablemente, en su caso, emptyPassword
su codificador de contraseña no lo haya inicializado con una contraseña codificada vacía. Establecer el codificador de contraseña que falta en AuthorizationServerConfigurerAdapter
:
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.passwordEncoder(passwordEncoder);
}