'Can't get username with SignalR and jwt token
Trying to learn SignalR and netcore kinda both at the same time and I am trying to get the username of the logged in user based on its jwt token.
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = "https://localhost:7005/";
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/chathub/negotiate")))
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(builder.Configuration.GetValue<string>("AppSettings:Secret"));
tokenHandler.ValidateToken(accessToken, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
var username = int.Parse(jwtToken.Claims.First(x => x.Type == "unique_name").Value);
context.HttpContext.Items["username"] = username;
context.HttpContext.Items["token"] = accessToken;
}
catch
{
}
}
return Task.CompletedTask;
}
};
});
And Hub method is:
public override async Task OnConnectedAsync()
{
var username = Context.GetHttpContext().Items["username"];
_connections.Add("bob", Context.ConnectionId);
await Clients.All.SendAsync("UpdateConnectionsList", _connections.GetConnections("bob"));
}
So username is null when I start the connection. What I don't understand here, is when I added the options to Authentication service my breakpoints would go inside there, now it just skips this code and I don't understand whats wrong.
Or am I doing it all wrong? When OnConnectedAsync happens is not after options.Events like above?
This is the angular code
private startConnection() {
const url = 'https://localhost:7005/chathub';
const token = localStorage.getItem('token')?.toString()!;
this.hubConnection = new HubConnectionBuilder()
.withUrl(`${url}?access_token=${token}`)
.build();
this.hubConnection
.start()
.then(() => {
console.log('Connection started!');
})
.catch((err:any) => console.log('Error while establishing connection :('));
this.hubConnection.on('UpdateConnectionsList', (connections) => {
this.connections = connections;
});
this.hubConnection.on('SendMessage', (nick: string, receivedMessage: string) => {
const text = `${nick}: ${receivedMessage}`;
this.messages.push(text);
});
}
Thank you for your time and help
Edit: I solved the issue and after breaking the step in button there were multiple problems:
int.Parsething, I think I tried random things and I didn't took that line in the account anymore.- not throwing a proper exception in the catch or having a global exception handling
path.StartsWithSegments("/chathub/negotiate")is justchathubsince I get two requests and I don't actually care about negotiate(I think, maybe thats a hook where I can do something else, I don't know what), this is why this code got skipped since second request is about what I want not about negotiation with the server
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
