I'm working in a Notifications Service using SignalR in .net 6.0. I need to get data user through a token by query, however, it arrives like null. I don't find more information and I don't know what else to do.
My Program.cs:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
//ValidIssuer = builder.Configuration["Jwt:Issuer"],
// ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey
(Encoding.UTF8.GetBytes(builder.Configuration["secreatKey"])),
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true
};
o.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
if (string.IsNullOrEmpty(accessToken) == false)
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
My Hub:
public class NotificationHub : Hub<INotificationHub>
{
//Crea la Conexion
private readonly NotificationMemoryStorage _notificationStorage;
public NotificationHub(NotificationMemoryStorage notificationMemoryStorage)
{
_notificationStorage = notificationMemoryStorage;
}
public override async Task OnConnectedAsync()
{
var userId = GetUserIdFromToken();
if(!string.IsNullOrEmpty(userId))
{
var notifications = _notificationStorage.GetNotifications(userId);
foreach (var notification in notifications)
{
await Clients.User(userId).SendNotification(notification);
}
_notificationStorage.ClearNotifications(userId);
var response = new ServerResponse
{
status = "Acepted",
};
await Clients.Client(Context.ConnectionId).ConnectionResponse(response);
}
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
public async Task MessageCheck(NotificationRequestModel request)
{
//meter validaciones
switch (request.Target.Device)
{
case "Admin":
if (request.Target.User.Contains("*"))
{
SendNotificationToAllUsers(request.Notification);
}
else
{
//SendNotificationToSpecificUser(request, request.Target.User);
}
break;
}
}
//Desconecta del Servidor
public async Task SendNotificationToAllUsers(NotificationModel message)
{
await Clients.All.SendNotificationToAllUsers(message);
}
private string GetUserIdFromToken()
{
var token = Context.GetHttpContext();
var jwt = token.Request.Headers["access_token"];
var identity = (ClaimsIdentity)Context.User.Identity;
var userIdClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
return userIdClaim?.Value;
}
//public async Task SendNotificationToSpecificUser(NotificationRequestModel message, List<string> target)
//{
// foreach (var item in target)
// {
// //if (ConnectedUsers.TryGetValue(item, out var user))
// //{
// await Clients.Client(user.ConnectionId).SendNotification(message);
// //}
// }
//}
}
In here the data arrives as null:
private string GetUserIdFromToken()`enter code here`
{
var token = Context.GetHttpContext();
var jwt = token.Request.Headers["access_token"];
var identity = (ClaimsIdentity)Context.User.Identity;
var userIdClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
return userIdClaim?.Value;
}
Attach Image: enter image description here
I recognize I don't know what I'm doing.
Some minor issues along the way, try it like this
Step 1:
Remove bearer-prefix from the querystring request
?access_token=bearerXXXX
--> ?access_token=XXXX
Step 2:
Read the token from the query and apply the token and a bearer-prefix with a space to the authorization header in the OnMessageReceived event
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
if (!string.IsNullOrEmpty(accessToken))
{
context.Request.Headers.Add("Authorization", $"Bearer {token}");
}
return Task.CompletedTask;
}
Step 3:
Enforce the authorization on your hub by adding the Authorize-attribute to the class
[Authorize]
public class NotificationHub : Hub<INotificationHub>