❔ SignalR

Trying to send a message from a client to specific client (like private chat)
25 Replies
Protagonist
ProtagonistOP2y ago
First i tried doing this without Identity but it seems like the Context.UserIdentifier will always be null
public async Task SetUserIdentifier(string userIdentifier)
{
try
{
Console.WriteLine($"Setting user identifier to {userIdentifier}");

var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserName == userIdentifier);

if (user == null)
{
user = new User { UserName = userIdentifier };
await _dbContext.Users.AddAsync(user);
await _dbContext.SaveChangesAsync();
}

await Groups.RemoveFromGroupAsync(Context.ConnectionId, user.Id);
await Groups.AddToGroupAsync(Context.ConnectionId, user.Id);
await Clients.Caller.SendAsync("UserIdentifierSet", user.Id);

}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
public async Task SetUserIdentifier(string userIdentifier)
{
try
{
Console.WriteLine($"Setting user identifier to {userIdentifier}");

var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserName == userIdentifier);

if (user == null)
{
user = new User { UserName = userIdentifier };
await _dbContext.Users.AddAsync(user);
await _dbContext.SaveChangesAsync();
}

await Groups.RemoveFromGroupAsync(Context.ConnectionId, user.Id);
await Groups.AddToGroupAsync(Context.ConnectionId, user.Id);
await Clients.Caller.SendAsync("UserIdentifierSet", user.Id);

}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
Im just reading and trial and error as im going
Protagonist
ProtagonistOP2y ago
enter user Id first then you want to send to a specific user, so you use their UserId and enter a message
Protagonist
ProtagonistOP2y ago
The Context.User.Identifier is meant to automatically set based on the authentication But it seems like it isnt being set here Can anyone help out/ im using the user.id in the code above instead of the Context.User.Identifier because it returns me null
JakenVeina
JakenVeina2y ago
what is Context.User.Identifier?
Protagonist
ProtagonistOP2y ago
returns the unique identifier for the current user associated with the connection
JakenVeina
JakenVeina2y ago
let's see your auth config, then
Protagonist
ProtagonistOP2y ago
builder.Services.AddDbContext<ApplicationDBContext>(options =>
{
options.UseInMemoryDatabase(databaseName: "MyDatabase");
});
builder.Services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDBContext>()
.AddDefaultTokenProviders();
builder.Services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
builder.Services.AddDbContext<ApplicationDBContext>(options =>
{
options.UseInMemoryDatabase(databaseName: "MyDatabase");
});
builder.Services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDBContext>()
.AddDefaultTokenProviders();
builder.Services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
and i do call the authentication on use
JakenVeina
JakenVeina2y ago
okay
Protagonist
ProtagonistOP2y ago
do u see the problem>?
JakenVeina
JakenVeina2y ago
no oh, wait you did post your config let's see CustomUserIdProvider
Protagonist
ProtagonistOP2y ago
public string GetUserId(HubConnectionContext connection)
{
// Get the authenticated user's ID from the ClaimsPrincipal
var userIdClaim = connection.User?.FindFirst(ClaimTypes.NameIdentifier);

if (userIdClaim != null)
{
return userIdClaim.Value;
}

// If the user is not authenticated or the NameIdentifier claim is not present, return null
return null;
}
public string GetUserId(HubConnectionContext connection)
{
// Get the authenticated user's ID from the ClaimsPrincipal
var userIdClaim = connection.User?.FindFirst(ClaimTypes.NameIdentifier);

if (userIdClaim != null)
{
return userIdClaim.Value;
}

// If the user is not authenticated or the NameIdentifier claim is not present, return null
return null;
}
well i just checked the UserIdclaim seems to be null howcomes its null tho
JakenVeina
JakenVeina2y ago
what other claims are there?
Protagonist
ProtagonistOP2y ago
i believe thats the only one
JakenVeina
JakenVeina2y ago
well, don't believe find out
Protagonist
ProtagonistOP2y ago
it is the only one would i have to put all the other claims on false if im not using them? could that be why?
JakenVeina
JakenVeina2y ago
so, wait is it there or not? if it's there, what's the problem?
Protagonist
ProtagonistOP2y ago
that claim is the only one there the problem im facing is that idprovider should assign the Context.UserIdentifier a value if its not null but it is null
JakenVeina
JakenVeina2y ago
okay, so again if the claim is there then what's wrong? if Context.UserIdentifier is null, I have to assume you're not correctly configuring SignalR to use your CustomerUserIdProvider except, then how are you able to confirm what claims are present? show me the ClaimsPrincipal
Protagonist
ProtagonistOP2y ago
public async Task SetUserIdentifier(string userIdentifier)
{
try
{
Console.WriteLine($"Setting user identifier to {userIdentifier}");

var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserName == userIdentifier);

if (user == null)
{
user = new User { UserName = userIdentifier };
await _dbContext.Users.AddAsync(user);
await _dbContext.SaveChangesAsync();
}

var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName)
};
var userIdentity = new ClaimsIdentity(claims, "login");
var userPrincipal = new ClaimsPrincipal(userIdentity);


await Groups.RemoveFromGroupAsync(Context.ConnectionId, user.Id);
await Groups.AddToGroupAsync(Context.ConnectionId, user.Id);
await Clients.Caller.SendAsync("UserIdentifierSet", user.Id);

}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
public async Task SetUserIdentifier(string userIdentifier)
{
try
{
Console.WriteLine($"Setting user identifier to {userIdentifier}");

var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserName == userIdentifier);

if (user == null)
{
user = new User { UserName = userIdentifier };
await _dbContext.Users.AddAsync(user);
await _dbContext.SaveChangesAsync();
}

var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName)
};
var userIdentity = new ClaimsIdentity(claims, "login");
var userPrincipal = new ClaimsPrincipal(userIdentity);


await Groups.RemoveFromGroupAsync(Context.ConnectionId, user.Id);
await Groups.AddToGroupAsync(Context.ConnectionId, user.Id);
await Clients.Caller.SendAsync("UserIdentifierSet", user.Id);

}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
this too confusing
JakenVeina
JakenVeina2y ago
what is?
Henkypenky
Henkypenky2y ago
are u using HttpContext directly in the component?
Protagonist
ProtagonistOP2y ago
the identity stuff and how SIgnalR is meant to know from authentication and give it a value could this be because everything is on the same page like setting a id/username, and it first checks if the user is logged in? indirectly through hubconnectioncontext hmmm
JakenVeina
JakenVeina2y ago
no this is because your auth system is not working thus, I asked to see your ClaimsPrincipal the one that led you to give a bunch of conflicting answers
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server