SignalR-Client-Swift
SignalR-Client-Swift copied to clipboard
Headers (Authorization) Not Sent in Invoke Requests on WebSocket Connection
@moozzyk Hi,
When using HubConnectionBuilder with .withHttpConnectionOptions(), the Authorization header is properly set in the connection request. However, it is not included in invoke requests sent over the WebSocket connection.
connection = HubConnectionBuilder(url: url)
.withLogging(minLogLevel: .debug)
.withHubConnectionDelegate(delegate: self)
.withHttpConnectionOptions { options in
options.accessTokenProvider = { self.token }
options.headers["Authorization"] = "Bearer \(self.token)"
}
.withHttpConnectionOptions { options in
options.authenticationChallengeHandler = { session, challenge, completionHandler in
session.configuration.httpAdditionalHeaders?["Authorization"] = "Bearer \(self.token)"
completionHandler(.performDefaultHandling, nil)
}
}
.build()
Expected Behavior: •The Authorization header should be included in all requests, including invoke method calls.
Additional Notes: • The header works in the initial connection request but disappears when invoking methods. • It appears that URLSessionWebSocketTask does not retain the header for WebSocket messages.
The token should be preserved. It is being set here: https://github.com/moozzyk/SignalR-Client-Swift/blob/655e8bde45b4e3fc737c8ced9da242e3a76f3e69/Sources/SignalRClient/WebsocketsTransport.swift#L41
I am not sure why it isn't working for you but there is a lot going on in your setup and maybe you overwrite or send duplicate headers. The intention is that the following code should work:
connection = HubConnectionBuilder(url: url)
.withLogging(minLogLevel: .debug)
.withHubConnectionDelegate(delegate: self)
.withHttpConnectionOptions { options in
options.accessTokenProvider = { self.token }
}
.build()
I have tried multiple approaches to include the Authorization header, but none of them are working. I don’t have access to the server, so I can’t debug the request directly. The server developer confirmed that the header is empty in the received requests.
How Can I Log Headers in This Library?
connection = HubConnectionBuilder(url: url)
.withLogging(minLogLevel: .debug)
.withHubConnectionDelegate(delegate: self)
.withHttpConnectionOptions { options in
options.accessTokenProvider = { self.token }
options.headers["Authorization"] = "Bearer \(self.token)"
}
.build()
connection = HubConnectionBuilder(url: url)
.withLogging(minLogLevel: .debug)
.withHubConnectionDelegate(delegate: self)
.withHttpConnectionOptions { options in
options.accessTokenProvider = { self.token }
}
.build()
connection = HubConnectionBuilder(url: url)
.withLogging(minLogLevel: .debug)
.withHubConnectionDelegate(delegate: self)
.withHttpConnectionOptions { options in
options.headers["Authorization"] = "Bearer \(self.token)"
}
.build()
@moozzyk hi, I debugged it using Proxyman. The HTTP request header contains the Bearer token, but the HTTP switching and WebSocket headers do not include the Bearer token.
HTTP Header
Socket Header
I haven't had a chance to look into this except for finding a test that validates that the token is sent to the server and is accessible:
https://github.com/moozzyk/SignalR-Client-Swift/blob/655e8bde45b4e3fc737c8ced9da242e3a76f3e69/Tests/SignalRClientTests/HubConnectionTests.swift#L971-L999
Here is the server code: https://github.com/moozzyk/SignalR-Client-Swift/blob/655e8bde45b4e3fc737c8ced9da242e3a76f3e69/Examples/TestServer/TestHub.cs#L84-L88
There seems to be some disconnect why the test passes but it doesn't work for you. I am not sure where it is.
IIRC, as an alternative, you can try sending the token in the query params (?access_token=xxx). This is how the JavaScript/TypeScript client works because the Websocket API available in the browser doesn't allow setting headers.
Recently, I found the official package https://github.com/dotnet/signalr-client-swift