Solución:
Entendiendo que la pregunta es un poco antigua, espero que lo siguiente pueda ser útil para aquellos que buscan la respuesta correcta para la pregunta.
OP preguntó no sobre la invalidación de tokens, sino sobre cómo invalidar httpSession en el servidor Spring OAuth2 justo después de que la autenticación del usuario pasara con éxito y un access_token válido o un código de autorización (para la posterior obtención de access_token) devuelto a un cliente.
Todavía no existe una solución lista para usar para este caso de uso. Pero la solución de trabajo del colaborador más activo de spring-security-oauth, Dave Syer, se puede encontrar aquí en GitHub
Simplemente copie el código de allí:
@Service
@Aspect
public class SessionInvalidationOauth2GrantAspect {
private static final String FORWARD_OAUTH_CONFIRM_ACCESS = "forward:/oauth/confirm_access";
private static final Logger logger = Logger.getLogger(SessionInvalidationOauth2GrantAspect.class);
@AfterReturning(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")
public void authorizationAdvice(JoinPoint joinpoint, ModelAndView result) throws Throwable {
// If we're not going to the confirm_access page, it means approval has been skipped due to existing access
// token or something else and they'll be being sent back to app. Time to end session.
if (!FORWARD_OAUTH_CONFIRM_ACCESS.equals(result.getViewName())) {
invalidateSession();
}
}
@AfterReturning(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")
public void authorizationAdvice(JoinPoint joinpoint, View result) throws Throwable {
// Anything returning a view and not a ModelView is going to be redirecting outside of the app (I think).
// This happens after the authorize approve / deny page with the POST to /oauth/authorize. This is the time
// to kill the session since they'll be being sent back to the requesting app.
invalidateSession();
}
@AfterThrowing(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", throwing = "error")
public void authorizationErrorAdvice(JoinPoint joinpoint) throws Throwable {
invalidateSession();
}
private void invalidateSession() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
HttpSession session = request.getSession(false);
if (session != null) {
logger.warn(String.format("As part of OAuth application grant processing, invalidating session for request %s", request.getRequestURI()));
session.invalidate();
SecurityContextHolder.clearContext();
}
}
}
agregar pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
Otra solución podría ser establecer el tiempo de espera de la sesión en un valor muy pequeño. La forma más sencilla de lograrlo es poner lo siguiente en application.yml config:
server:
session:
timeout: 1
Pero no es la solución ideal, ya que el valor mínimo que podría proporcionar el proveedor es 1 (cero está reservado para sesiones infinitas) y es en minutos, no en segundos.
Por lo que tengo entendido, está intentando cerrar la sesión mediante programación después de haber realizado un determinado conjunto de acciones. Probablemente debería mirar en SecurityContextLogoutHandler y ver cómo funciona. Hay un método para cerrar la sesión allí. Creo que llamarlo como un consejo resolverá tu problema.
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
Assert.notNull(request, "HttpServletRequest required");
if (invalidateHttpSession) {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
}
SecurityContextHolder.clearContext();
}
Primero: en su configuración declare bean con token store para oauth
@Bean
@Primary
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
Para el enfoque del controlador hicimos la siguiente clase
@Controller
public class TokenController {
@RequestMapping(value = "/oauth/token/revoke", method = RequestMethod.POST)
public @ResponseBody void create(@RequestParam("token") String value) {
this.revokeToken(value);
}
@Autowired
TokenStore tokenStore;
public boolean revokeToken(String tokenValue) {
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
if (accessToken == null) {
return false;
}
if (accessToken.getRefreshToken() != null) {
tokenStore.removeRefreshToken(accessToken.getRefreshToken());
}
tokenStore.removeAccessToken(accessToken);
return true;
}
}
Si no desea utilizar este enfoque, puede obtener el cableado automático del token del usuario actual Principal
:
OAuth2Authentication authorization = (OAuth2Authentication) principal;
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authorization.getDetails();
String token = details.getTokenValue();
O incluso cableado automático OAuth2Authentication
:
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
String token = details.getTokenValue();