Spring Security OAuth 2.0: el secreto del cliente siempre se requiere para la concesión del código de autorización

Resuelto quintonm asked hace 8 años • 7 respuestas

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_idincluido en la solicitud y sea el client_idmismo 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 ClientDetailsinterfaz. ¿Qué debo hacer para permitir que los clientes sin un secreto se autentiquen en la /oauth/tokenURL?

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.

quintonm avatar Mar 04 '16 07:03 quintonm
Aceptado

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 ClientCredentialsTokenEndpointFilterque permite la autenticación a través de parámetros de formulario.

quintonm avatar Mar 04 '2016 15:03 quintonm

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.

ddewaele avatar Jan 31 '2018 14:01 ddewaele

Para resolver el problema, consulte el método loadUserByUsernamede clase org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService:

if (clientSecret == null || clientSecret.trim().length() == 0) {
   clientSecret = this.emptyPassword;
}

Probablemente, en su caso, emptyPasswordsu 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);
}
apo avatar Jul 17 '2019 18:07 apo