secure - Integrar Spring Security OAuth2 y Spring Social
spring security oauth2 example mkyong (3)
En primer lugar, le recomendaría encarecidamente que se aleje de la concesión de contraseña para dicho caso de uso.
Los clientes públicos (JavaScript, aplicaciones instaladas) no pueden mantener la confidencialidad de su cliente, por eso NO DEBEN asignarse uno: cualquier visitante que inspeccione su código JavaScript puede descubrir el secreto y así implementar la misma página de autenticación que tiene, almacenando las contraseñas de los usuarios en el proceso.
La subvención implícita se ha creado exactamente para lo que estás haciendo.
El uso de un flujo basado en la redirección tiene la ventaja de dejar el mecanismo de autenticación en manos del servidor de autorizaciones, en lugar de tener cada una de sus aplicaciones en parte: esa es principalmente la definición de inicio de sesión único (SSO) .
Dicho esto, su pregunta está estrechamente relacionada con la que acabo de responder: el servidor de Own Spring OAuth2 junto con los proveedores OAuth de terceros.
Para resumir la respuesta:
Al final, se trata de cómo su servidor de autorizaciones asegura el AuthorizationEndpoint: / oauth / authorize. Dado que su servidor de autorización funciona, usted ya tiene una clase de configuración que extiende WebSecurityConfigurerAdapter que maneja la seguridad para / oauth / authorize con formLogin. Ahí es donde necesitas integrar cosas sociales.
Simplemente no puede usar una concesión de contraseña para lo que está tratando de lograr, debe hacer que su cliente público redirija al servidor de autorización. El servidor de autorización redireccionará al inicio de sesión social como su mecanismo de seguridad para el punto final /oauth/authorize
.
Estoy trabajando con una aplicación Spring Boot + Spring Security OAuth2 que creo que fue inspirada por ejemplos de Dave Syer. La aplicación está configurada para ser un servidor de autorización OAuth2, con un único cliente público que utiliza el flujo de credenciales de contraseña del propietario del recurso. Un token exitoso está configurado para ser un JWT.
El cliente Angular público envía una solicitud POST a / oauth / token con un encabezado de autenticación básico que contiene la identificación del cliente y el secreto (esta era la forma más fácil de conseguir que el cliente se autenticara, incluso si el secreto no es privado). El cuerpo de la solicitud contiene nombre de usuario, contraseña y tipo de concesión de "contraseña".
Además de ser un servidor de autenticación, la aplicación es un servidor de recursos RESTful para usuarios, equipos y organizaciones.
Estoy intentando agregar un flujo de autenticación SSO adicional con Spring Social. Tengo configurado Spring Social para autenticarme a través de proveedores externos a través de / auth / [proveedor]; sin embargo, las siguientes solicitudes ya no tienen SecurityContext configurado correctamente. Posiblemente, ¿el servidor o cliente de Spring Security OAuth está anulando el SecurityContext?
Si puedo configurar SecurityContext correctamente después del flujo de Spring Social, tengo un TokenGranter nuevo que permite un nuevo tipo de concesión de "social" que verificará el SecurityContextHolder para el usuario preautenticado.
Me interesa tanto una solución a mi problema específico con SecurityContext (creo que es un problema con la integración Spring OAuth + Social), o un enfoque diferente para autenticarse con proveedores externos y obtener un JWT válido de nuestro propio servidor de autenticación.
¡Gracias!
Implementé spring oauth2 para asegurar mis servicios de descanso y, además, agregué el inicio de sesión social y el registro implícito para el inicio de sesión por primera vez. para el usuario usuario puede generar el token usando el nombre de usuario y la contraseña solo el problema con generar el token para el usuario social. para eso debe implementar el filtro que interceptará su solicitud / oauth / token antes del procesamiento. aquí si desea generar el token para el usuario social, pase el nombre de usuario y el token de Facebook, aquí puede usar Facebook token como contraseña y generar el token para el usuario de Facebook también. si el token de Facebook se actualizó, entonces debes escribir un desencadenador db también para actualizar tu token en la tabla de usuario ... puede ser que te ayude
Tuve un problema similar en una aplicación web generada por JHipster . Finalmente decidí ir con la opción SocialAuthenticationFilter
de Spring Social (a través del SpringSocialConfigurer
). Después de un inicio de sesión social exitoso, el servidor genera automáticamente y devuelve el token de acceso "propio" a través de la redirección a la aplicación del cliente.
Aquí está mi intento:
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter implements EnvironmentAware {
//...
@Inject
private AuthorizationServerTokenServices authTokenServices;
@Override
public void configure(HttpSecurity http) throws Exception {
SpringSocialConfigurer socialCfg = new SpringSocialConfigurer();
socialCfg
.addObjectPostProcessor(new ObjectPostProcessor<SocialAuthenticationFilter>() {
@SuppressWarnings("unchecked")
public SocialAuthenticationFilter postProcess(SocialAuthenticationFilter filter){
filter.setAuthenticationSuccessHandler(
new SocialAuthenticationSuccessHandler(
authTokenServices,
YOUR_APP_CLIENT_ID
)
);
return filter;
}
});
http
//... lots of other configuration ...
.apply(socialCfg);
}
}
Y la clase SocialAuthenticationSuccessHandler
:
public class SocialAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
public static final String REDIRECT_PATH_BASE = "/#/login";
public static final String FIELD_TOKEN = "access_token";
public static final String FIELD_EXPIRATION_SECS = "expires_in";
private final Logger log = LoggerFactory.getLogger(getClass());
private final AuthorizationServerTokenServices authTokenServices;
private final String localClientId;
public SocialAuthenticationSuccessHandler(AuthorizationServerTokenServices authTokenServices, String localClientId){
this.authTokenServices = authTokenServices;
this.localClientId = localClientId;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
log.debug("Social user authenticated: " + authentication.getPrincipal() + ", generating and sending local auth");
OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(authentication)); //Automatically checks validity
String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)
.append("?").append(FIELD_TOKEN).append("=")
.append(encode(oauth2Token.getValue()))
.append("&").append(FIELD_EXPIRATION_SECS).append("=")
.append(oauth2Token.getExpiresIn())
.toString();
log.debug("Sending redirection to " + redirectUrl);
response.sendRedirect(redirectUrl);
}
private OAuth2Authentication convertAuthentication(Authentication authentication) {
OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null,
null, null, null, null);
return new OAuth2Authentication(request,
//Other option: new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", authorities)
new PreAuthenticatedAuthenticationToken(authentication.getPrincipal(), "N/A")
);
}
private String encode(String in){
String res = in;
try {
res = UriUtils.encode(in, GeneralConstants.ENCODING_UTF8);
} catch(UnsupportedEncodingException e){
log.error("ERROR: unsupported encoding: " + GeneralConstants.ENCODING_UTF8, e);
}
return res;
}
}
De esta forma, su aplicación cliente recibirá el token de acceso de su aplicación web a través de la redirección a /#/login?access_token=my_access_token&expires_in=seconds_to_expiration
, siempre y cuando configure el REDIRECT_PATH_BASE
correspondiente en SocialAuthenticationSuccessHandler
.
Espero que ayude.