My question is pretty straightforward. I am using Windows Authentication in .NET Core. On the front end part of the app (Angular) I have a HTTP interceptor which sets widhcredentails: true to the all HTTP requests.
This interceptor does not work with WebSocket, so I need a solution for adding the same code from Interceptor to the SignalR service.
Here is my interceptor code:
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>
{
request = request.clone({ withCredentials: true });
return next.handle(request);
}
And here is my SignalR service:
this.requestConnection = new HubConnectionBuilder().
withUrl(`${environment.apiUrl}/request`).
withAutomaticReconnect([0, 2000, 30000, 60000, null]).
build();
this.requestConnection.
start().
then(() => console.log('Connection started')).
catch(err => console.log(`Error while starting connection: ${err}`));
Keep in mind that interceptor is added in providers array in the app.module component :
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: WinAuthInterceptor,
multi: true
}
],
SignalR service is injected in the root.
@Injectable({
providedIn: 'root'
})
Finally, I've realized what was the problem. Since I am using Windows Authentications, there was no need to add any kind of JWT Authorization. Also, the interceptor code I've posted above, makes no difference lol. Meaning you don't need withCredetials: true either in interceptor or SignalR.
Anyway, (if you are using IIS you need to configure it by following this documentation, locally it will work perfectly, but if you are hosting/deploying your app on the IIS you need to do this prior, otherwise your Context will be NULL) you need to set anonymousAuthentication property to false in launchSettings.json (.NET Core as you backend)
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:64152",
"sslPort": 44385
}
Long story short, Angular code looks like this:
this.requestConnection = new HubConnectionBuilder().
withUrl(`${environment.apiUrl}/request`).
withAutomaticReconnect([0, 2000, 30000, 60000, null]).
build();
this.requestConnection.
start().
then(() => console.log('Connection started')).
catch(err => console.log(`Error while starting connection: ${err}`));
in .NET Core I've just override OnConnectAsync() class to fetch connections and do some logic:
public override Task OnConnectedAsync()
{
var user = Context.User.Identity.Name.ToUpper();
//remove domain name
user = user[user.IndexOf("\\")..];
//remove speacial chars, excluding .
user = UserProvider.RemoveSpecialCharacters(user);
var conId = Context.ConnectionId;
if (UserProvider.UserConnections.Any(key => key.Key == user))
{
UserProvider.UserConnections[user] = conId;
}
else
{
UserProvider.UserConnections.Add(user, conId);
}
return base.OnConnectedAsync();
}