I have a traditional web react app and built it to apk through capacitor, the authentication in http routes is done by a jwt in http only cookie, below are some configs I needed to do at capacitor config to use cookies :
plugins: {
"CapacitorCookies": {
"enabled": true
},
"CapacitorHttp": {
"enabled": true
}
}
The problem is that I can use my cookies to get auth in http but not in websockets (it only occurs in apk not on web version of app), below I’m connecting to websockets in react:
public initializeWebSocket() {
const socket = new WebSocket(this.wsUrl);
this.stompClient = Stomp.over(socket);
this.stompClient.connect(
{},
(frame) => {
console.log('Connected: ' + frame);
this.stompClient?.subscribe('/user/queue/notifications', (message) => {//web socket notificacoes
console.log("mensagem pura do websocket")
console.log(message)
if (message.body) {
console.log("MENSAGEM DO WEB SOCKET");
console.log(message.body);
this.notficationThrower(JSON.parse(message.body) as UserNotificationDTO);//isso executara o call back que o componente react passou como parametro de onNotificationMessage
}
});
},
(error) => {
console.error('STOMP error: ', error);
alert('STOMP error: ' + error)
}
);
}
And below my backend websocket config:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Autowired
private UserRepository userRepository;
@Autowired
private TokenService tokenService;
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic","/queue"); // /topic é global, qeue é privado
config.setUserDestinationPrefix("/user");
config.setApplicationDestinationPrefixes("/app"); // Prefixo para mensagens enviadas do cliente
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOriginPatterns("*")
.addInterceptors(httpSessionHandshakeInterceptor());
}
@Bean
public HandshakeInterceptor httpSessionHandshakeInterceptor() {
return new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request;
HttpServletRequest servletRequest = servletServerRequest.getServletRequest();
String token = tokenService.recoverToken(servletRequest);
if(token==null){
return false;
}
if(tokenService.validateToken(token)==null){
return false;
}
attributes.put("username", tokenService.getUsernameFromJWT(token));
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
};
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {//autenticar websocket
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (accessor != null) {
String username = (String) accessor.getSessionAttributes().get("username");
UserDetails userDetails = userRepository.findByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
accessor.setUser(authentication);
}
return message;
}
});
}
}
Again… I’m able to connect to websocket in the built react app (vite) but I can’t connect to websocket in built apk app (capacitor) since the cookie falling at:
public String recoverToken(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("token".equals(cookie.getName())) {
return cookie.getValue(); // Retorna o valor do cookie
}
}
}
return null; // Retorna null se o cookie não for encontrado
}
is null, but for other http requests the cookie of capacitor is not null
The problem is not in CORS config, for some reason my cookies are getting null when I connect to my websocket