xhr_streaming fails (Spring + Zuul + SockJS) - spring

I've got the following testing script (executed with node, real client is a browser, result is the same):
const SockJS = require('sockjs-client');
const webstomp = require('webstomp-client');
let sock = new SockJS(/*INSERT_URL_HERE*/);
let stomp = webstomp.over(sock, {
heartbeat: false,
});
stomp.connect({}, function() {
console.log('connected');
}, function() {
console.log('disconnected');
});
Versions in use:
Spring Boot - 1.5.3
Spring Cloud Netflix - 1.3.1
Nginx - 1.11
RabbitMQ - 3.6.9
To exclude parts of our infrastructure (Like NGINX as Proxy to route subdomains etc.) being the root of evil, I tried connecting to the Spring based Stomp Broker Relay (using RabbitMQ as real Broker) directly, via the NGINX Proxy and through Zuul.
The first two variants work as intended, but the third one (Using Zuul as Gateway with the ResourceServer annotation) fails. Increasing the timeouts didn't help, as the problem seems to reside in the "handshake". This is what I could get from the client side logs so far (Log for the first 2 variants, everything works fine, even webstomp could be established):
sockjs-client:main using url http://domain.tld/stomp +0ms
sockjs-client:utils:url same http://domain.tld/stomp http://localhost/ false +4ms
sockjs-client:info-receiver http://domain.tld/stomp +3ms
Opening Web Socket...
sockjs-client:info-receiver doXhr http://domain.tld/stomp/info +5ms
sockjs-client:driver:xhr GET http://domain.tld/stomp/info undefined +1ms
sockjs-client:driver:xhr data {"entropy":394670331,"origins":["*:*"],"cookie_needed":true,"websocket":false} +100ms
sockjs-client:driver:xhr end +2ms
sockjs-client:info-receiver finish { entropy: 394670331,
origins: [ '*:*' ],
cookie_needed: true,
websocket: false } 103 +1ms
sockjs-client:info-receiver _cleanup +5ms
sockjs-client:main _receiveInfo 103 +1ms
sockjs-client:main info { entropy: 394670331,
origins: [ '*:*' ],
cookie_needed: true,
websocket: false,
nullOrigin: false,
sameOrigin: false,
sameScheme: true } +1ms
sockjs-client:utils:transport disabled from server websocket +0ms
sockjs-client:utils:transport enabled xhr-streaming +1ms
sockjs-client:utils:transport disabled xdr-streaming +0ms
sockjs-client:utils:transport enabled eventsource +0ms
sockjs-client:utils:transport disabled iframe-eventsource +0ms
sockjs-client:utils:transport disabled htmlfile +1ms
sockjs-client:utils:transport disabled iframe-htmlfile +0ms
sockjs-client:utils:transport enabled xhr-polling +0ms
sockjs-client:utils:transport disabled xdr-polling +0ms
sockjs-client:utils:transport disabled iframe-xhr-polling +0ms
sockjs-client:utils:transport disabled jsonp-polling +0ms
sockjs-client:main 3 enabled transports +0ms
sockjs-client:main attempt xhr-streaming +0ms
sockjs-client:main using timeout 824 +0ms
sockjs-client:main transport url http://domain.tld/stomp/365/5rfribd0 +1ms
sockjs-client:sender-receiver http://domain.tld/stomp/365/5rfribd0/xhr_streaming +0ms
sockjs-client:buffered-sender http://domain.tld/stomp/365/5rfribd0 +1ms
sockjs-client:polling http://domain.tld/stomp/365/5rfribd0/xhr_streaming +0ms
sockjs-client:polling _scheduleReceiver +2ms
sockjs-client:receiver:xhr http://domain.tld/stomp/365/5rfribd0/xhr_streaming +0ms
sockjs-client:driver:xhr POST http://domain.tld/stomp/365/5rfribd0/xhr_streaming null +1ms
sockjs-client:driver:xhr data hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
+60ms
sockjs-client:receiver:xhr _chunkHandler 200 +0ms
sockjs-client:receiver:xhr message hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +0ms
sockjs-client:polling message hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +0ms
sockjs-client:sender-receiver poll message hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +1ms
sockjs-client:main _transportMessage hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +0ms
sockjs-client:main heartbeat undefined +5ms
sockjs-client:driver:xhr data o
+0ms
sockjs-client:receiver:xhr _chunkHandler 200 +0ms
sockjs-client:receiver:xhr message o +0ms
sockjs-client:polling message o +0ms
sockjs-client:sender-receiver poll message o +2ms
sockjs-client:main _transportMessage o +0ms
sockjs-client:main _open xhr-streaming 0 +1ms
Web Socket Opened...
>>> CONNECT
accept-version:1.2,1.1,1.0
heart-beat:0,0
>>> length 110
sockjs-client:buffered-sender send "CONNECT\naccept-version:1.2,1.1,1.0\nheart-beat:0,0\n\n\u0000" +2ms
sockjs-client:buffered-sender sendSchedule 1 +0ms
sockjs-client:ajax-based create ajax sender http://domain.tld/stomp/365/5rfribd0 ["CONNECT\naccept-version:1.2,1.1,1.0\nheart-beat:0,0\n\n\u0000"] +0ms
sockjs-client:driver:xhr POST http://domain.tld/stomp/365/5rfribd0/xhr_send ["CONNECT\naccept-version:1.2,1.1,1.0\nheart-beat:0,0\n\n\u0000"] +0ms
sockjs-client:main connected xhr-streaming +2ms
sockjs-client:driver:xhr end +111ms
sockjs-client:ajax-based finish 204 +0ms
sockjs-client:buffered-sender sendScheduleWait +1ms
sockjs-client:buffered-sender timeout +26ms
sockjs-client:buffered-sender sendSchedule 0 +0ms
sockjs-client:driver:xhr data a["CONNECTED\nserver:RabbitMQ/3.6.9\nsession:session--67Xn59asIOtXSwEHL4NZQ\nheart-beat:0,0\nversion:1.2\n\n\u0000"]
+186ms
sockjs-client:receiver:xhr _chunkHandler 200 +1ms
sockjs-client:receiver:xhr message a["CONNECTED\nserver:RabbitMQ/3.6.9\nsession:session--67Xn59asIOtXSwEHL4NZQ\nheart-beat:0,0\nversion:1.2\n\n\u0000"] +0ms
sockjs-client:polling message a["CONNECTED\nserver:RabbitMQ/3.6.9\nsession:session--67Xn59asIOtXSwEHL4NZQ\nheart-beat:0,0\nversion:1.2\n\n\u0000"] +0ms
sockjs-client:sender-receiver poll message a["CONNECTED\nserver:RabbitMQ/3.6.9\nsession:session--67Xn59asIOtXSwEHL4NZQ\nheart-beat:0,0\nversion:1.2\n\n\u0000"] +0ms
sockjs-client:main _transportMessage a["CONNECTED\nserver:RabbitMQ/3.6.9\nsession:session--67Xn59asIOtXSwEHL4NZQ\nheart-beat:0,0\nversion:1.2\n\n\u0000"] +0ms
sockjs-client:main message xhr-streaming CONNECTED
server:RabbitMQ/3.6.9
session:session--67Xn59asIOtXSwEHL4NZQ
heart-beat:0,0
version:1.2
+0ms
<<< CONNECTED
server:RabbitMQ/3.6.9
session:session--67Xn59asIOtXSwEHL4NZQ
heart-beat:0,0
version:1.2
connected to server RabbitMQ/3.6.9
connected
sockjs-client:driver:xhr data a["\n"]
+4ms
sockjs-client:receiver:xhr _chunkHandler 200 +0ms
sockjs-client:receiver:xhr message a["\n"] +0ms
sockjs-client:polling message a["\n"] +0ms
sockjs-client:sender-receiver poll message a["\n"] +0ms
sockjs-client:main _transportMessage a["\n"] +0ms
sockjs-client:main message xhr-streaming
+0ms
<<< PONG
But when using Zuul, the following happens (the "Handshake" request fails by timing out):
sockjs-client:main using url http://domain.tld/stomp +0ms
sockjs-client:utils:url same http://domain.tld/stomp http://localhost/ false +4ms
sockjs-client:info-receiver http://domain.tld/stomp +3ms
Opening Web Socket...
sockjs-client:info-receiver doXhr http://domain.tld/stomp/info +8ms
sockjs-client:driver:xhr GET http://domain.tld/stomp/info undefined +1ms
sockjs-client:driver:xhr data {"entropy":886967672,"origins":["*:*"],"cookie_needed":true,"websocket":false} +280ms
sockjs-client:driver:xhr end +3ms
sockjs-client:info-receiver finish { entropy: 886967672,
origins: [ '*:*' ],
cookie_needed: true,
websocket: false } 284 +1ms
sockjs-client:info-receiver _cleanup +4ms
sockjs-client:main _receiveInfo 284 +1ms
sockjs-client:main info { entropy: 886967672,
origins: [ '*:*' ],
cookie_needed: true,
websocket: false,
nullOrigin: false,
sameOrigin: false,
sameScheme: false } +1ms
sockjs-client:utils:transport disabled from server websocket +2ms
sockjs-client:utils:transport enabled xhr-streaming +1ms
sockjs-client:utils:transport disabled xdr-streaming +0ms
sockjs-client:utils:transport enabled eventsource +0ms
sockjs-client:utils:transport disabled iframe-eventsource +1ms
sockjs-client:utils:transport disabled htmlfile +0ms
sockjs-client:utils:transport disabled iframe-htmlfile +0ms
sockjs-client:utils:transport enabled xhr-polling +0ms
sockjs-client:utils:transport disabled xdr-polling +0ms
sockjs-client:utils:transport disabled iframe-xhr-polling +1ms
sockjs-client:utils:transport disabled jsonp-polling +0ms
sockjs-client:main 3 enabled transports +0ms
sockjs-client:main attempt xhr-streaming +6ms
sockjs-client:main using timeout 2272 +0ms
sockjs-client:main transport url http://domain.tld/stomp/490/5sugacsu +0ms
sockjs-client:sender-receiver http://domain.tld/stomp/490/5sugacsu/xhr_streaming +1ms
sockjs-client:buffered-sender http://domain.tld/stomp/490/5sugacsu +0ms
sockjs-client:polling http://domain.tld/stomp/490/5sugacsu/xhr_streaming +0ms
sockjs-client:polling _scheduleReceiver +0ms
sockjs-client:receiver:xhr http://domain.tld/stomp/490/5sugacsu/xhr_streaming +0ms
sockjs-client:driver:xhr POST http://domain.tld/stomp/490/5sugacsu/xhr_streaming null +1ms
sockjs-client:main _transportTimeout +2s
sockjs-client:main _transportClose undefined 2007 Transport timed out +0ms
sockjs-client:main attempt eventsource +0ms
sockjs-client:main using timeout 2272 +1ms
sockjs-client:main transport url http://domain.tld/stomp/490/s50jl3qh +1ms
sockjs-client:sender-receiver http://domain.tld/stomp/490/s50jl3qh/eventsource +0ms
sockjs-client:buffered-sender http://domain.tld/stomp/490/s50jl3qh +0ms
sockjs-client:polling http://domain.tld/stomp/490/s50jl3qh/eventsource +0ms
sockjs-client:polling _scheduleReceiver +1ms
sockjs-client:receiver:eventsource http://domain.tld/stomp/490/s50jl3qh/eventsource +0ms
sockjs-client:receiver:eventsource error 0 Event { type: 'error' } +28ms
sockjs-client:receiver:eventsource cleanup +1ms
sockjs-client:receiver:eventsource close network +0ms
sockjs-client:polling close null network undefined +202ms
sockjs-client:polling _scheduleReceiver +0ms
I hope anyone has an idea to solve this. It seems like the sockjs response isn't returned by Zuul or something in this direction. Even using Trace on serverside didn't show up any errors...
The gateway itself is a simple setup with #SpringBootApplication, #EnableZuulProxy, #EnableResourceServer and this configuration:
# increase the timeout of the proxy
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
zuul:
host:
connect-timeout-millis: 3000
socket-timeout-millis: 60000
# We don't want to automatically register all service available on Eureka
ignored-services: "*"
retryable: true
# Default is "Cookie,Set-Cookie,Authorization", but we want to forward the Bearer Token
sensitive-headers: Cookie,Set-Cookie
routes:
stomp:
path: /stomp/**
serviceId: stomp
strip-prefix: true

Assuming that you are having a micro-services architecture because you are already using Zuul as API proxy (gateway). For micro-services, I would suggest to have a separate service for web socket, having it's independent port and independent configurations.
you can have whatever security implementation done in this service to secure your Web socket connection. Handling socket with zuul is sort of impossible, because it is just a proxy, it routes requests and response, but not very great solution for sockets.

Related

How do I solve getting 401 Unauthorized in response to attempting to obtain a token?

I've got an Identity Server (using IdentityServer4), a Web API that uses the Identity Server for authorization, and a Xamarin application that is using the Identity Server to log-in and authenticate the API.
When I run all three parts locally from Visual Studio I'm able to login using the Xamarin app, obtain a token, and use that token to make API calls. However, when I publish the Identity Server to a web server (on the same network), it fails at the point that it tries to get the token. So, it shows the login page, appears to accept the login, but the POST to get the token fails with the 401 Unauthorised error in the response.
I've also configured the Identity Server to allow Swagger to connect for testing the API, and that does allow me to sign in (using Implicit) using the Identity Server installed on a Web Server.
This is the method that does the POST in the Xamarin app (mostly copied from the eShopOnContainers example):
public async Task<TResult> PostAsync<TResult>(string uri, string data, string clientId, string clientSecret)
{
HttpClient httpClient = CreateHttpClient(string.Empty);
if (!string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(clientSecret))
{
AddBasicAuthenticationHeader(httpClient, clientId, clientSecret);
}
var content = new StringContent(data);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
HttpResponseMessage response = await httpClient.PostAsync(uri, content);
await HandleResponse(response);
string serialized = await response.Content.ReadAsStringAsync();
TResult result = await Task.Run(() =>
JsonConvert.DeserializeObject<TResult>(serialized, _serializerSettings));
return result;
}
Here's the calling method for getting the token:
public async Task<UserToken> GetTokenAsync(string code)
{
string data = string.Format("grant_type=authorization_code&code={0}&redirect_uri={1}&code_verifier={2}",
code, WebUtility.UrlEncode(Settings.Service.IdentityCallback), _codeVerifier);
var token = await _requestProvider.PostAsync<UserToken>(
Settings.Service.IdentityTokenEndpoint, data, Settings.Service.IdentityClientId, Settings.Service.IdentityClientSecret);
return token;
}
The uri is "http://myserver:5002/connect/token" and headers are:
Accept: "application/json"
Authorization: "Basic SW5zdGVtLkFDSVMuTW9iaWxlOnNlY3JldA=="
ContentType: "application/x-www-form-urlencoded"
The log on the web server gives me this:
info: IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator[0]
Showing login: User is not authenticated
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 3.4723ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DCompany.App.Mobile%26client_secret%3Dsecret%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520app_api%2520offline_access%26redirect_uri%3Dhttp%253A%252F%252Fmyserver%253A5002%252FAccount%252FRedirect%26nonce%3D0dc5d79410db46739c798ce004ac89b8%26code_challenge%3DAuKmnO1hMcoEK3VeVNiVDka2U5F23HBnR0_MtxeWA3c%26code_challenge_method%3DS256%26state%3D031db7b77c7249aebb6f7ae205dac016
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Route matched with {action = "Login", controller = "Account"}. Executing action IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer) with arguments (/connect/authorize/callback?client_id=Company.App.Mobile&client_secret=secret&response_type=code%20id_token&scope=openid%20profile%20app_api%20offline_access&redirect_uri=http%3A%2F%2Fmyserver%3A5002%2FAccount%2FRedirect&nonce=0dc5d79410db46739c798ce004ac89b8&code_challenge=AuKmnO1hMcoEK3VeVNiVDka2U5F23HBnR0_MtxeWA3c&code_challenge_method=S256&state=031db7b77c7249aebb6f7ae205dac016) - Validation state: Valid
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action method IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer), returned result Microsoft.AspNetCore.Mvc.ViewResult in 0.3611ms.
info: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[1]
Executing ViewResult, running view Login.
info: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[4]
Executed ViewResult - view Login executed in 1.7974ms.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer) in 2.4715ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 3.1044ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/css/site.css
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
The file /css/site.css was not modified
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.6236ms 304 text/css
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/lib/bootstrap/js/bootstrap.js
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
The file /lib/bootstrap/js/bootstrap.js was not modified
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.3461ms 304 application/javascript
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/lib/jquery/jquery.js
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
The file /lib/jquery/jquery.js was not modified
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.2798ms 304 application/javascript
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/icon.png
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
The file /icon.png was not modified
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.2655ms 304 image/png
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/lib/bootstrap/css/bootstrap.css
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
The file /lib/bootstrap/css/bootstrap.css was not modified
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.26ms 304 text/css
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 POST http://myserver:5002/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DCompany.App.Mobile%26client_secret%3Dsecret%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520app_api%2520offline_access%26redirect_uri%3Dhttp%253A%252F%252Fmyserver%253A5002%252FAccount%252FRedirect%26nonce%3D0dc5d79410db46739c798ce004ac89b8%26code_challenge%3DAuKmnO1hMcoEK3VeVNiVDka2U5F23HBnR0_MtxeWA3c%26code_challenge_method%3DS256%26state%3D031db7b77c7249aebb6f7ae205dac016 application/x-www-form-urlencoded 712
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Route matched with {action = "Login", controller = "Account"}. Executing action IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer) with arguments (IdentityServer4.Quickstart.UI.LoginInputModel, login) - Validation state: Valid
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[10]
AuthenticationScheme: idsrv signed in.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action method IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer), returned result Microsoft.AspNetCore.Mvc.ViewResult in 1.0902ms.
info: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[1]
Executing ViewResult, running view Redirect.
info: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[4]
Executed ViewResult - view Redirect executed in 10.0474ms.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action IdentityServer4.Quickstart.UI.AccountController.Login (Company.IdentityServer) in 12.3805ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 13.1928ms 302 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/connect/authorize/callback?client_id=Company.App.Mobile&client_secret=secret&response_type=code%20id_token&scope=openid%20profile%20app_api%20offline_access&redirect_uri=http%3A%2F%2Fmyserver%3A5002%2FAccount%2FRedirect&nonce=0dc5d79410db46739c798ce004ac89b8&code_challenge=AuKmnO1hMcoEK3VeVNiVDka2U5F23HBnR0_MtxeWA3c&code_challenge_method=S256&state=031db7b77c7249aebb6f7ae205dac016
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint for /connect/authorize/callback
info: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint[0]
ValidatedAuthorizeRequest
{
"ClientId": "Company.App.Mobile",
"ClientName": "App Mobile",
"RedirectUri": "http://myserver:5002/Account/Redirect",
"AllowedRedirectUris": [
"http://myserver:5002/Account/Redirect"
],
"SubjectId": "eb194e4a-a2f7-482c-8c43-204567ebd591",
"ResponseType": "code id_token",
"ResponseMode": "fragment",
"GrantType": "hybrid",
"RequestedScopes": "openid profile app_api offline_access",
"State": "031db7b77c7249aebb6f7ae205dac016",
"Nonce": "0dc5d79410db46739c798ce004ac89b8",
"SessionId": "0ed1a950919c3b368e1249ec74e35f2c",
"Raw": {
"client_id": "Company.App.Mobile",
"client_secret": "secret",
"response_type": "code id_token",
"scope": "openid profile app_api offline_access",
"redirect_uri": "http://myserver:5002/Account/Redirect",
"nonce": "0dc5d79410db46739c798ce004ac89b8",
"code_challenge": "AuKmnO1hMcoEK3VeVNiVDka2U5F23HBnR0_MtxeWA3c",
"code_challenge_method": "S256",
"state": "031db7b77c7249aebb6f7ae205dac016"
}
}
info: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint[0]
Authorize endpoint response
{
"SubjectId": "eb194e4a-a2f7-482c-8c43-204567ebd591",
"ClientId": "Company.App.Mobile",
"RedirectUri": "http://myserver:5002/Account/Redirect",
"State": "031db7b77c7249aebb6f7ae205dac016",
"Scope": "openid profile app_api offline_access"
}
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[10]
AuthenticationScheme: idsrv signed in.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 40.3114ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://myserver:5002/Account/Redirect
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.9519ms 404
The address "http://myserver:5002/Account/Redirect" doesn't actually exist because the client is a Xamarin app, so I don't think the 404 at the end is an issue. There doesn't seem to be anything in the log for the call to obtain the token.
Here's the Client config for the Identity Server:
new Client
{
ClientName = "ACIS Mobile",
ClientId = "Instem.ACIS.Mobile",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = {$"{identityUri}/Account/Redirect"},
RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = {$"{identityUri}/Account/Redirecting"},
AllowedCorsOrigins = { "http://xamarinapp" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"acis_api"
},
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true
},
new Client
{
ClientName = "Swagger UI",
ClientId="swaggerui",
AllowedGrantTypes=GrantTypes.Implicit,
AllowAccessTokensViaBrowser=true,
RedirectUris = { $"{webApiUri}/oauth2-redirect.html" },
PostLogoutRedirectUris={ $"{webApiUri}/" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"acis_api"
}
}
The Identity server startup configuration is pretty simple:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddIdentityServer()
.AddInMemoryClients(Config.GetClients(Configuration))
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddTestUsers(Config.GetUsers())
//.AddDeveloperSigningCredential();
.AddSigningCredential("some certificate thumbprint", System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, NameType.Thumbprint);
services.AddAuthentication()
.AddMicrosoftAccount(options =>
{
options.ClientId = "someclientid";
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientSecret = "somesecret";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
In IIS I've configured it to allow Anonymous and Basic authentication.
This is pretty much all new to me and I was making progress until this point, but I can't see any reason why it's giving me the 401 Unauthorized error, and I can't even see anything in any logs to give me anything to go on.
Edit:
I found a log file with more information:
2019-01-08 12:08:51 172.26.2.174 POST /Account/Login ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DCompany.App.Mobile%26client_secret%3Dsecret%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520app_api%2520offline_access%26redirect_uri%3Dhttp%253A%252F%252Fmyserver%253A5002%252FAccount%252FRedirect%26nonce%3Ddc06cb800d6f4f729df03a986ff2f165%26code_challenge%3DN343zy63pcw_E75ET0HZQWGU_5ALC6H6sXt836z6mzo%26code_challenge_method%3DS256%26state%3D86f26cf6a5184d9a8263aac954711819 5002 - 172.16.190.147 Mozilla/5.0+(Windows+NT+10.0;+WOW64;+WebView/3.0)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/64.0.3282.140+Safari/537.36+Edge/17.17134 http://myserver:5002/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DCompany.App.Mobile%26client_secret%3Dsecret%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520app_api%2520offline_access%26redirect_uri%3Dhttp%253A%252F%252Fmyserver%253A5002%252FAccount%252FRedirect%26nonce%3Ddc06cb800d6f4f729df03a986ff2f165%26code_challenge%3DN343zy63pcw_E75ET0HZQWGU_5ALC6H6sXt836z6mzo%26code_challenge_method%3DS256%26state%3D86f26cf6a5184d9a8263aac954711819 302 0 0 156
2019-01-08 12:09:49 172.26.2.174 GET /connect/authorize/callback client_id=Company.App.Mobile&client_secret=secret&response_type=code%20id_token&scope=openid%20profile%20app_api%20offline_access&redirect_uri=http%3A%2F%2Fmyserver%3A5002%2FAccount%2FRedirect&nonce=dc06cb800d6f4f729df03a986ff2f165&code_challenge=N343zy63pcw_E75ET0HZQWGU_5ALC6H6sXt836z6mzo&code_challenge_method=S256&state=86f26cf6a5184d9a8263aac954711819 5002 - 172.16.190.147 Mozilla/5.0+(Windows+NT+10.0;+WOW64;+WebView/3.0)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/64.0.3282.140+Safari/537.36+Edge/17.17134 http://myserver:5002/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DCompany.App.Mobile%26client_secret%3Dsecret%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520app_api%2520offline_access%26redirect_uri%3Dhttp%253A%252F%252Fmyserver%253A5002%252FAccount%252FRedirect%26nonce%3Ddc06cb800d6f4f729df03a986ff2f165%26code_challenge%3DN343zy63pcw_E75ET0HZQWGU_5ALC6H6sXt836z6mzo%26code_challenge_method%3DS256%26state%3D86f26cf6a5184d9a8263aac954711819 302 0 0 593
2019-01-08 12:10:33 172.26.2.174 POST /connect/token - 5002 Company.App.Mobile 172.16.190.147 - - 401 1 1326 50
2019-01-08 12:10:33 172.26.2.174 GET /Account/Redirect - 5002 - 172.16.190.147 Mozilla/5.0+(Windows+NT+10.0;+WOW64;+WebView/3.0)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/64.0.3282.140+Safari/537.36+Edge/17.17134 http://myserver:5002/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DCompany.App.Mobile%26client_secret%3Dsecret%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520app_api%2520offline_access%26redirect_uri%3Dhttp%253A%252F%252Fmyserver%253A5002%252FAccount%252FRedirect%26nonce%3Ddc06cb800d6f4f729df03a986ff2f165%26code_challenge%3DN343zy63pcw_E75ET0HZQWGU_5ALC6H6sXt836z6mzo%26code_challenge_method%3DS256%26state%3D86f26cf6a5184d9a8263aac954711819 404 0 0 15
It's the connect/token line that has the 401 error.
I had Basic Authentication enabled in IIS for the Identity Server. Once I turned that off, it works fine.

Xamarin Mobile with IdentityServer 3

I am trying to establish a secure connection for my mobile app using Identity server 3 and Xamarin. I have a web app that works perfectly using the identity server but can’t for the life of me get it working with mobile. I have it asking for credentials, logging in and getting an access token. However when I try to make a call using the token I still get HttpContext.User.Identity.IsAuthenticated as false and the call fails.
I created a new client in the identity server for the mobile app and have it as the following:
new IdentityServer3.Core.Models.Client
{
Enabled = true,
ClientName = "MyMobile Mobile App",
ClientId = "myMobile",
ClientSecrets = { new Secret("myMobileSecret".Sha256()) },
Flow = Flows.Hybrid,
RedirectUris = new List<string>
{
…
},
PostLogoutRedirectUris = new List<string>
{
…
},
RequireConsent = false,
AllowAccessToAllScopes = true,
RequireSignOutPrompt = false
}
My code is as follows:
var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint);
var dic = new Dictionary<string, string>();
dic.Add("client_id", GlobalSetting.Instance.ClientId);
dic.Add("client_secret", GlobalSetting.Instance.ClientSecret);
dic.Add("response_type", "code token");
dic.Add("scope", "openid profile roles");
dic.Add("redirect_uri", GlobalSetting.Instance.IdentityCallback);
dic.Add("nonce", Guid.NewGuid().ToString("N"));
_currentCSRFToken = Guid.NewGuid().ToString("N");
dic.Add("state", _currentCSRFToken);
var authorizeUri = authorizeRequest.Create(dic);
LoginWebView.Source = authorizeUri;
On response…
private async Task NavigateAsync(string url)
{
var unescapedUrl = System.Net.WebUtility.UrlDecode(url);
if (unescapedUrl.StartsWith(GlobalSetting.Instance.IdentityCallback))
{
LoginWebView.IsVisible = false;
var authResponse = new AuthorizeResponse(url);
if (!string.IsNullOrWhiteSpace(authResponse.Code))
{
var userToken = await _identityService.GetTokenAsync(authResponse.Code);
string accessToken = userToken.AccessToken;
if (!string.IsNullOrWhiteSpace(accessToken))
{
Authorization.AccessToken = accessToken;
Authorization.IdToken = authResponse.IdentityToken;
Application.Current.MainPage = _homePage;
}
}
}
…
}
public async Task<UserToken> GetTokenAsync(string code)
{
string data = string.Format("grant_type=authorization_code&code={0}&redirect_uri={1}&code_verifier={2}", code, WebUtility.UrlEncode(GlobalSetting.Instance.IdentityCallback), _codeVerifier);
var token = await _requestProvider.PostAsync<UserToken> (GlobalSetting.Instance.TokenEndpoint, data, GlobalSetting.Instance.ClientId, GlobalSetting.Instance.ClientSecret);
return token;
}
And then when I make a call…
RestClient rest = new RestClient(GlobalSetting.DefaultBaseUrl);
var request = new RestRequest("Partner/GetMyItem", Method.POST);
request.AddParameter("detail", MyEnumValue.ToString());
//tried both of the following…
request.AddParameter("Authorization", string.Format("Bearer {0}", Authorization.AccessToken), ParameterType.HttpHeader);
rest.AddDefaultHeader("Authorization", string.Format("Bearer {0}", Authorization.AccessToken));
IRestResponse res = rest.Post(request);
Function…
[HttpPost]
[ValidateInput(false)]
[AuthAttribute(Roles = …)]
[HandleForbidden]
public string GetMyItem(MyEnum detail)
In the server identity log I have the following…
2018-07-23 14:03:11.508 +00:00 [Information] Start authorize request
2018-07-23 14:03:11.508 +00:00 [Information] Start authorize request protocol validation
2018-07-23 14:03:11.508 +00:00 [Information] "Authorize request validation success"
"{
\"ClientId\": \"myMobile\",
\"ClientName\": \"myMobile App\",
\"RedirectUri\": \"https://localhost:44000/\",
\"AllowedRedirectUris\": [
\"https://localhost:44000/\",
...
],
\"SubjectId\": \"unknown\",
\"ResponseType\": \"code token\",
\"ResponseMode\": \"fragment\",
\"Flow\": \"Hybrid\",
\"RequestedScopes\": \"openid profile roles\",
\"State\": \"a971d692ae8f424493966023f5934b70\",
\"Nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
\"Raw\": {
\"client_id\": \"myMobile\",
\"client_secret\": \"myMobileSecret\",
\"response_type\": \"code token\",
\"scope\": \"openid profile roles\",
\"redirect_uri\": \"https://localhost:44000/\",
\"nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
\"state\": \"a971d692ae8f424493966023f5934b70\"
}
}"
2018-07-23 14:03:11.524 +00:00 [Information] User is not authenticated. Redirecting to login.
2018-07-23 14:03:11.524 +00:00 [Information] End authorize request
2018-07-23 14:03:11.524 +00:00 [Information] Redirecting to login page
2018-07-23 14:03:11.524 +00:00 [Debug] Protecting message: "{\"ReturnUrl\":\"https://....net/identity/connect/authorize?client_id=myMobile&client_secret=myMobileSecret&response_type=code%20token&scope=openid%20profile%20roles&redirect_uri=https%3A%2F%2Flocalhost%3A44000% 2F&nonce=ec42d50463cc418dacbd04f1c43873d0&state=a971d692ae8f424493966023f5934b70\",\"ClientId\":\"myMobile\",\"AcrValues\":[],\"Created\":636679513915083066}"
2018-07-23 14:03:11.570 +00:00 [Information] Login page requested
2018-07-23 14:03:11.570 +00:00 [Debug] signin message passed to login: "{
\"ReturnUrl\": \"https://...net/identity/connect/authorize?client_id=myMobile&client_secret=myMobileSecret&response_type=code%20token&scope=openid%20profile%20roles&redirect_uri=https%3A%2F%2Flocalhost%3A44000% 2F&nonce=ec42d50463cc418dacbd04f1c43873d0&state=a971d692ae8f424493966023f5934b70\",
\"ClientId\": \"myMobile\",
\"IdP\": null,
\"Tenant\": null,
\"LoginHint\": null,
\"DisplayMode\": null,
\"UiLocales\": null,
\"AcrValues\": [],
\"Created\": 636679513915083066
}"
2018-07-23 14:03:11.570 +00:00 [Information] rendering login page
2018-07-23 14:03:12.007 +00:00 [Information] CSP Report endpoint requested
2018-07-23 14:03:12.007 +00:00 [Information] CSP Report data: "{\"csp-report\":{\"document-uri\":\"https://...net/identity/login?signin=df9bdfc781a634b806ecc6555e9989ca\",\"referrer\":\"\",\"blocked-uri\":\"\",\"violated-directive\":\"script-src 'self'\",\"original-policy\":\"default-src 'self'; script-src 'self' ; style-src 'self' 'unsafe-inline' style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; img-src *; font-src font-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; report-uri https://devs3server.azurewebsites.net/identity/csp/report\",\"effective-directive\":\"script-src\",\"status-code\":200,\"source- file\":\"https://devs3server.azurewebsites.net/identity/login?signin=df9bdfc781a634b806ecc6555f9989ca\"}}"
2018-07-23 14:03:12.007 +00:00 [Information] Rendering 204
2018-07-23 14:03:26.772 +00:00 [Information] Login page submitted
2018-07-23 14:03:26.803 +00:00 [Information] Login credentials successfully validated by user service
2018-07-23 14:03:26.803 +00:00 [Information] Calling PostAuthenticateAsync on the user service
2018-07-23 14:03:26.819 +00:00 [Information] issuing primary signin cookie
2018-07-23 14:03:26.819 +00:00 [Information] redirecting to: https://....net/identity/connect/authorize?client_id=myMobile&client_secret=myMobileSecret&response_type=code token&scope=openid profile roles&redirect_uri=https:%2F%2Flocalhost:44000% 2F&nonce=ec42d50463cc418dacbd04f1c43873d0&state=a971d692ae8f424493966023f5934b70
2018-07-23 14:03:26.866 +00:00 [Information] Start authorize request
2018-07-23 14:03:26.881 +00:00 [Information] Start authorize request protocol validation
2018-07-23 14:03:26.881 +00:00 [Information] "Authorize request validation success"
"{
\"ClientId\": \"myMobile\",
\"ClientName\": \"my Mobile App\",
\"RedirectUri\": \"https://localhost:44000/\",
\"AllowedRedirectUris\": [
\"https://localhost:44000/\",
...
],
\"SubjectId\": \"2957b247-43ed-4aea-b5b4-c0a76a613942\",
\"ResponseType\": \"code token\",
\"ResponseMode\": \"fragment\",
\"Flow\": \"Hybrid\",
\"RequestedScopes\": \"openid profile roles\",
\"State\": \"a971d692ae8f424493966023f5934b70\",
\"Nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
\"SessionId\": \"3e67194d4c5ba7d1c8586948377f9fe7\",
\"Raw\": {
\"client_id\": \"myMobile\",
\"client_secret\": \"myMobileSecret\",
\"response_type\": \"code token\",
\"scope\": \"openid profile roles\",
\"redirect_uri\": \"https://localhost:44000/\",
\"nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
\"state\": \"a971d692ae8f424493966023f5934b70\"
}
}"
2018-07-23 14:03:26.881 +00:00 [Information] Creating Hybrid Flow response.
2018-07-23 14:03:26.881 +00:00 [Information] Creating Implicit Flow response.
2018-07-23 14:03:26.881 +00:00 [Debug] Creating access token
2018-07-23 14:03:26.881 +00:00 [Debug] Creating JWT access token
2018-07-23 14:03:26.912 +00:00 [Debug] Adding client "myMobile" to client list cookie for subject "2957b247-43ed-4aea-b5b4-c0a76a613942"
2018-07-23 14:03:26.912 +00:00 [Information] End authorize request
2018-07-23 14:03:26.912 +00:00 [Information] Redirecting to: https://localhost:44000/
2018-07-23 14:03:28.950 +00:00 [Information] Start token request
2018-07-23 14:03:28.950 +00:00 [Debug] Start client validation
2018-07-23 14:03:28.950 +00:00 [Debug] Start parsing Basic Authentication secret
2018-07-23 14:03:28.950 +00:00 [Debug] Parser found secret: "BasicAuthenticationSecretParser"
2018-07-23 14:03:28.950 +00:00 [Information] Secret id found: "myMobile"
2018-07-23 14:03:28.950 +00:00 [Debug] Secret validator success: "HashedSharedSecretValidator"
2018-07-23 14:03:28.950 +00:00 [Information] Client validation success
2018-07-23 14:03:28.950 +00:00 [Information] Start token request validation
2018-07-23 14:03:28.950 +00:00 [Information] Start validation of authorization code token request
2018-07-23 14:03:28.950 +00:00 [Information] Validation of authorization code token request success
2018-07-23 14:03:28.950 +00:00 [Information] Token request validation success
{
"ClientId": "myMobile",
"ClientName": "my Mobile App",
"GrantType": "authorization_code",
"AuthorizationCode": "dc7be1793efe246ca817d7d35298b355",
"Raw": {
"grant_type": "authorization_code",
"code": "dc7be1793efe246ca817d7d35298b355",
"redirect_uri": "https://localhost:44000/",
"code_verifier": ""
}
}
can someone please help me get a xamarin mobile app to work with identity server 3 to call apis?
Your API needs to be registered as a client with your Identity Server as a resource scope.
Then, you need to wire up bearer authentication in your API's middleware by using UseBearerTokenAuthentication. This is necessary so that the API can authorize incoming requests that are using the Authorization header with the Bearer Schema.
Finally, your mobile app needs to request that scope when issuing an authentication request. However, you also need to make sure your that Mobile app client is registered with that scope in Identity Server

Cast devices freeze when casting audio streams

I have an issue with casting some third party audio streams. I have relied heavily on https://developers.google.com/cast/docs/player and followed those instructions on how to create a custom receiver for playing the streams.
After just a second or so after starting the stream (I don't get any sound) the Cast devices freezes and they stop responding to debug via Chrome and they don't react to stopping the Cast session. Often they are so locked that even issuing a reboot via the Home app doesn't work; I have to physically disconnect the power.
It's the same behaviour on Chromecast v2 (1.22.79313), Chromecast Ultra (1.22.78017) and Google Home (1.22.78295).
What could the cause of this freeze be? Is this caused by some very broken streams? Is it a known issue? Are there any workarounds? Shouldn't one expect the Cast devices to handle this and give some error message and not crash like this?
This is the log I get from the Chrome Developer Tools before the connection is reset:
cast_receiver.js:67 [ 0.268s] [cast.receiver.IpcChannel] Opening platform websocket
cast_receiver.js:67 [ 0.292s] [cast.receiver.CastReceiverManager] Version: 2.0.0.0049
cast_receiver.js:67 [ 0.305s] [cast.receiver.MediaManager] Using default Player
cast_receiver.js:67 [ 0.314s] [cast.receiver.IpcChannel] Opening message bus websocket
cast_receiver.js:67 [ 0.322s] [cast.receiver.IpcChannel] IpcChannel opened
cast_receiver.js:67 [ 0.326s] [cast.receiver.CastMessageBus] Dispatching CastMessageBus message
cast_receiver.js:67 [ 0.333s] [cast.receiver.CastReceiverManager] Underlying message bus is open
[...]
media_player.js:25 [ 0.628s] [cast.player.api.Player] Version: 1.0.0.40
[...]
media_player.js:25 [ 6.682s] [cast.player.api.Player] load
media_player.js:25 [ 6.707s] [goog.net.XhrIo] Opening Xhr [GET http://thirdpartyserver.example.com/playlist.m3u8 -1]
media_player.js:25 [ 6.721s] [goog.net.XhrIo] Will abort after 30000ms if incomplete, xhr2 false [GET http://thirdpartyserver.example.com/playlist.m3u8 -1]
media_player.js:25 [ 6.725s] [goog.net.XhrIo] Sending request [GET http://thirdpartyserver.example.com/playlist.m3u8 -1]
media_player.js:51 Mixed Content: The page at 'https://example.com/custom_receiver.html?debug=true' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://thirdpartyserver.example.com/playlist.m3u8'. This content should also be served over HTTPS.
media_player.js:25 [ 6.735s] [cast.player.core.MediaSourceManager] open
media_player.js:25 [ 6.923s] [goog.net.XhrIo] Request complete [GET http://thirdpartyserver.example.com/playlist.m3u8 200]
media_player.js:25 [ 6.975s] [cast.player.core.QualityManager] 0: initial 82625
media_player.js:25 [ 6.986s] [cast.player.hls.Playlist] update: http://thirdpartyserver.example.com/chunklist_w941582493.m3u8
media_player.js:25 [ 6.993s] [goog.net.XhrIo] Opening Xhr [GET http://thirdpartyserver.example.com/chunklist_w941582493.m3u8 -1]
media_player.js:25 [ 6.999s] [goog.net.XhrIo] Will abort after 30000ms if incomplete, xhr2 false [GET http://thirdpartyserver.example.com/chunklist_w941582493.m3u8 -1]
media_player.js:25 [ 7.004s] [goog.net.XhrIo] Sending request [GET http://thirdpartyserver.example.com/chunklist_w941582493.m3u8 -1]
media_player.js:51 Mixed Content: The page at 'https://example.com/custom_receiver.html?debug=true' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://thirdpartyserver.example.com/chunklist_w941582493.m3u8'. This content should also be served over HTTPS.
media_player.js:25 [ 7.127s] [goog.net.XhrIo] Request complete [GET http://thirdpartyserver.example.com/chunklist_w941582493.m3u8 200]
media_player.js:25 [ 7.140s] [cast.player.hls.Playlist] update in: 3000
media_player.js:25 [ 7.161s] [cast.player.core.SegmentManager] 0: seek success 0
media_player.js:25 [ 7.169s] [goog.net.XhrIo] Opening Xhr [GET http://thirdpartyserver.example.com/media_w941582493_4220443.aac -1]
media_player.js:25 [ 7.174s] [goog.net.XhrIo] Will abort after 10000ms if incomplete, xhr2 false [GET http://thirdpartyserver.example.com/media_w941582493_4220443.aac -1]
media_player.js:25 [ 7.180s] [goog.net.XhrIo] Sending request [GET http://thirdpartyserver.example.com/media_w941582493_4220443.aac -1]
media_player.js:51 Mixed Content: The page at 'https://example.com/custom_receiver.html?debug=true' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://thirdpartyserver.example.com/media_w941582493_4220443.aac'. This content should also be served over HTTPS.
media_player.js:25 [ 7.311s] [goog.net.XhrIo] Request complete [GET http://thirdpartyserver.example.com/media_w941582493_4220443.aac 200]
media_player.js:25 [ 7.322s] [cast.player.core.QualityManager] 0: current=1018961.04, average=1444314.43
media_player.js:25 [ 7.330s] [cast.player.core.SegmentManager] 0: process segment
media_player.js:25 [ 7.338s] [cast.player.hls.Adaptation] process segment
media_player.js:25 [ 7.357s] [cast.player.core.SegmentManager] 0: segment processed
media_player.js:25 [ 7.363s] [cast.player.core.SourceBufferManager] 0: queue append
media_player.js:25 [ 7.382s] [goog.net.XhrIo] Opening Xhr [GET http://thirdpartyserver.example.com/media_w941582493_4220444.aac -1]
media_player.js:25 [ 7.387s] [goog.net.XhrIo] Will abort after 10000ms if incomplete, xhr2 false [GET http://thirdpartyserver.example.com/media_w941582493_4220444.aac -1]
media_player.js:25 [ 7.392s] [goog.net.XhrIo] Sending request [GET http://thirdpartyserver.example.com/media_w941582493_4220444.aac -1]
media_player.js:51 Mixed Content: The page at 'https://example.com/custom_receiver.html?debug=true' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://thirdpartyserver.example.com/media_w941582493_4220444.aac'. This content should also be served over HTTPS.
media_player.js:25 [ 7.515s] [goog.net.XhrIo] Request complete [GET http://thirdpartyserver.example.com/media_w941582493_4220444.aac 200]
media_player.js:25 [ 7.521s] [cast.player.core.QualityManager] 0: current=1113553.96, average=1179706.05
media_player.js:25 [ 7.528s] [cast.player.core.SegmentManager] 0: process segment
media_player.js:25 [ 7.533s] [cast.player.hls.Adaptation] process segment
Update - more info:
The response headers for that first request (playlist.m3u8) are as follows:
Accept-Ranges:bytes
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Access-Control-Allow-Methods:OPTIONS, GET, POST, HEAD
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Date, Server, Content-Type, Content-Length
Cache-Control:no-cache
Content-Length:105
Content-Type:application/vnd.apple.mpegurl
Date:Tue, 21 Mar 2017 13:44:37 GMT
Server:WowzaStreamingEngine/4.5.0
The response body for that first request (playlist.m3u8) is as follows:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=80053,CODECS="mp4a.40.2"
chunklist_w941582493.m3u8
The response headers for that second request (chunklist_w941582493.m3u8) are as follows:
Accept-Ranges:bytes
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Access-Control-Allow-Methods:OPTIONS, GET, POST, HEAD
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Date, Server, Content-Type, Content-Length
Cache-Control:no-cache
Content-Length:213
Content-Type:application/vnd.apple.mpegurl
Date:Tue, 21 Mar 2017 13:44:37 GMT
Server:WowzaStreamingEngine/4.5.0
The response body for that second request (chunklist_w941582493.m3u8) is typical something as follows:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:4272014
#EXTINF:1.95,
media_w1552860397_4272014.aac
#EXTINF:2.09,
media_w1552860397_4272015.aac
#EXTINF:1.95,
media_w1552860397_4272016.aac
The response headers for that second request (media_w941582493_4220443.aac) are as follows:
Accept-Ranges:bytes
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Access-Control-Allow-Methods:OPTIONS, GET, POST, HEAD
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Date, Server, Content-Type, Content-Length
Cache-Control:no-cache
Content-Length:19757
Content-Type:audio/x-aac
Date:Tue, 21 Mar 2017 13:44:37 GMT
Server:WowzaStreamingEngine/4.5.0
Searching the bug tracker for the Google Cast SDK I found a relevant bug report.
All I had to do was to add cast.player.api.HlsSegmentFormat.MPEG_AUDIO_ES to cast.player.api.CreateHlsStreamingProtocol(). Now the stream works just fine and the Cast devices don't crash or freeze.

GCDWebServer returns HTTPRequest status zero with no responseText

I have the following javascript app that receives data from GCDWebServer that runs on an OSX app.
var HttpClient = function() {
this.get = function(aUrl, aCallback) {
var anHttpRequest = new XMLHttpRequest();
anHttpRequest.open( "GET", aUrl, true );
anHttpRequest.onreadystatechange = function() {
if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200) {
aCallback(anHttpRequest.responseText);
document.write (anHttpRequest.responseText);
}
else {
document.write ("Not Ok: ReadyState=" + anHttpRequest.readyState + " Status= " + anHttpRequest.status);
}
}
anHttpRequest.send( null );
}
}
var client = new HttpClient();
client.get('http://xxx.xxx.x.xx:8080?var=param', function(response) {
document.write ("Success");
});
The Cocoa app runs the following code:
[webServer addDefaultHandlerForMethod:#"GET"
requestClass:[GCDWebServerRequest class]
asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithJSONObject:dict];
completionBlock(response);
});
I always get an anHttpRequest.readyState = 4 and anHttpRequest.status = 0. The anHttpRequest.responseText is empty.
However, when I open any browser and type http://xxx.xxx.x.xx:8080?var=param I get the correct results. So the server is sending the data properly.
Here is the log from GCDWebServer
[DEBUG] Did open connection on socket 13
[DEBUG] Did connect
[DEBUG] Connection received 312 bytes on socket 13
[DEBUG] Connection on socket 13 preflighting request "GET /" with 312 bytes body
[DEBUG] Connection on socket 13 processing request "GET /" with 312 bytes body
[DEBUG] Connection sent 175 bytes on socket 13
[DEBUG] Connection sent 107 bytes on socket 13
[DEBUG] Did close connection on socket 13
[VERBOSE] [xxx.xxx.x.xx:8080] xxx.xxx.x.xx:52401 200 "GET /" (312 | 282)
[DEBUG] Did disconnect
Any ideas?
Thanks in advance.
This isn't an issue with your GCDWebServer but is simply a CORS issue. If you make the same request against your server from something like curl then you will see the correct 200 HTTP status. To get the correct response from a browser you will need to have your server send the following header:
Access-Control-Allow-Origin: *
This tells the browser that it is allowed to pass back the full response it gets from your server to the JavaScript initiating the request. Without that response header the browser essentially drops all the data it received and should print out an error message in your browser's console.

What website supports http/2 on port 80 with no SSL?

I would like to run a wireshark on http/2 for port 80 to
1. be able to test out an http/2 client
2. follow a wireshark trace to understand the protocol better
Is there a website that supports http/2 on port 80? When I go to google, it is always changing me to https.
thanks,
Dean
The Jetty project implements a HTTP/2 server that can work with both encrypted HTTP/2 and clear-text HTTP/2.
You can easily setup locally a Jetty h2c server with support for direct HTTP/2 communication as well as support for HTTP/1.1 upgrade to HTTP/2.
I recommend you don't bomb a public server with your experiments :)
This is the server code:
public class H2C
{
public static void main(String[] args) throws Exception
{
Server server = new Server();
HttpConfiguration config = new HttpConfiguration();
HttpConnectionFactory h1 = new HttpConnectionFactory(config);
HTTP2CServerConnectionFactory h2 = new HTTP2CServerConnectionFactory(config);
ServerConnector connector = new ServerConnector(server, h1, h2);
connector.setPort(8080);
server.addConnector(connector);
server.setHandler(new AbstractHandler()
{
#Override
protected void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
// Your code here.
}
});
server.start();
}
}
You can use a HTTP/2 client to test the server, such as nghttp, and watch the traffic via Wireshark.
Testing clear-text HTTP/2 via upgrade (using the -u flag, the -v flag is for verbosity):
$ nghttp -uv http://localhost:8080/
[ 0.000] Connected
[ 0.000] HTTP Upgrade request
GET / HTTP/1.1
host: localhost:8080
connection: Upgrade, HTTP2-Settings
upgrade: h2c
http2-settings: AAMAAABkAAQAAP__
accept: */*
user-agent: nghttp2/1.7.1
[ 0.001] HTTP Upgrade response
HTTP/1.1 101 Switching Protocols
[ 0.001] HTTP Upgrade success
[ 0.001] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=1>
(dep_stream_id=11, weight=16, exclusive=0)
[ 0.001] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_HEADER_TABLE_SIZE(0x01):4096]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.001] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.002] recv (stream_id=1) :status: 200
[ 0.002] recv (stream_id=1) server: Jetty(9.4.z-SNAPSHOT)
[ 0.002] recv (stream_id=1) date: Fri, 20 May 2016 09:38:52 GMT
[ 0.002] recv HEADERS frame <length=45, flags=0x05, stream_id=1>
; END_STREAM | END_HEADERS
(padlen=0)
; First response header
[ 0.002] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
Or testing clear-text HTTP/2 directly:
$ nghttp -v http://localhost:8080/
[ 0.000] Connected
[ 0.000] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.000] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[ 0.000] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[ 0.000] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[ 0.000] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[ 0.000] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[ 0.000] send HEADERS frame <length=38, flags=0x25, stream_id=13>
; END_STREAM | END_HEADERS | PRIORITY
(padlen=0, dep_stream_id=11, weight=16, exclusive=0)
; Open new stream
:method: GET
:path: /
:scheme: http
:authority: localhost:8080
accept: */*
accept-encoding: gzip, deflate
user-agent: nghttp2/1.7.1
[ 0.095] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_HEADER_TABLE_SIZE(0x01):4096]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.095] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.096] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.105] recv (stream_id=13) :status: 200
[ 0.105] recv (stream_id=13) server: Jetty(9.4.z-SNAPSHOT)
[ 0.105] recv (stream_id=13) date: Fri, 20 May 2016 09:39:30 GMT
[ 0.105] recv HEADERS frame <length=45, flags=0x05, stream_id=13>
; END_STREAM | END_HEADERS
(padlen=0)
; First response header
[ 0.106] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])

Resources