.NET Core SignalR: How to accomplish resource-based authorization?
All my SignalR clients connect using a JWT bearer token. I utilize the [Authorize]
attribute in my SignalR Hub
.
This token contains a userId
which can be used to check if a user has read access on the resource through the resource's users
property which contains a List<PuppyUserPermission>
that look like this:
public class PuppyUserPermission
public string userId get; set;
public bool read get; set;
public bool write get; set;
The question is: how do I connect the dots here? Ideally, instead of something like
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
await Clients.All.SendAsync(pup);
I would so something like the following (this is more pseudo code than anything else, as I don't use valid methods):
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
var clients = Puppy.users.Where(u => u.read == true);
await clients.SendAsync(pup);
Basically, I'd like to ensure that the clients recieving the Puppy
object via SignalR would be authorized users on the resource. Problem is, Clients
is just a list of string
client IDs, and I'm not sure how to go about tying them to actual users on my Puppy
resource.
How do I go about achieving this?
.net-core authorization signalr jwt
add a comment |
All my SignalR clients connect using a JWT bearer token. I utilize the [Authorize]
attribute in my SignalR Hub
.
This token contains a userId
which can be used to check if a user has read access on the resource through the resource's users
property which contains a List<PuppyUserPermission>
that look like this:
public class PuppyUserPermission
public string userId get; set;
public bool read get; set;
public bool write get; set;
The question is: how do I connect the dots here? Ideally, instead of something like
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
await Clients.All.SendAsync(pup);
I would so something like the following (this is more pseudo code than anything else, as I don't use valid methods):
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
var clients = Puppy.users.Where(u => u.read == true);
await clients.SendAsync(pup);
Basically, I'd like to ensure that the clients recieving the Puppy
object via SignalR would be authorized users on the resource. Problem is, Clients
is just a list of string
client IDs, and I'm not sure how to go about tying them to actual users on my Puppy
resource.
How do I go about achieving this?
.net-core authorization signalr jwt
add a comment |
All my SignalR clients connect using a JWT bearer token. I utilize the [Authorize]
attribute in my SignalR Hub
.
This token contains a userId
which can be used to check if a user has read access on the resource through the resource's users
property which contains a List<PuppyUserPermission>
that look like this:
public class PuppyUserPermission
public string userId get; set;
public bool read get; set;
public bool write get; set;
The question is: how do I connect the dots here? Ideally, instead of something like
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
await Clients.All.SendAsync(pup);
I would so something like the following (this is more pseudo code than anything else, as I don't use valid methods):
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
var clients = Puppy.users.Where(u => u.read == true);
await clients.SendAsync(pup);
Basically, I'd like to ensure that the clients recieving the Puppy
object via SignalR would be authorized users on the resource. Problem is, Clients
is just a list of string
client IDs, and I'm not sure how to go about tying them to actual users on my Puppy
resource.
How do I go about achieving this?
.net-core authorization signalr jwt
All my SignalR clients connect using a JWT bearer token. I utilize the [Authorize]
attribute in my SignalR Hub
.
This token contains a userId
which can be used to check if a user has read access on the resource through the resource's users
property which contains a List<PuppyUserPermission>
that look like this:
public class PuppyUserPermission
public string userId get; set;
public bool read get; set;
public bool write get; set;
The question is: how do I connect the dots here? Ideally, instead of something like
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
await Clients.All.SendAsync(pup);
I would so something like the following (this is more pseudo code than anything else, as I don't use valid methods):
[Authorize]
public class PuppyHub : Hub
public async Task SendPuppy(Puppy pup)
var clients = Puppy.users.Where(u => u.read == true);
await clients.SendAsync(pup);
Basically, I'd like to ensure that the clients recieving the Puppy
object via SignalR would be authorized users on the resource. Problem is, Clients
is just a list of string
client IDs, and I'm not sure how to go about tying them to actual users on my Puppy
resource.
How do I go about achieving this?
.net-core authorization signalr jwt
.net-core authorization signalr jwt
asked Nov 12 '18 at 20:45
Nickdb93
196115
196115
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
From the beginning, I had the feeling that the answer lay in IUserIdProvider
, but I didn't see how that would work for multiple users.
I finally found the answer, but it'll definitely need some cleanup.
First, create your own implementation of IUserIdProvider
as follows:
public class MyUserIdProvider : IUserIdProvider
public string GetUserId(HubConnectionContext connection)
var username = connection.User.Claims.Where(x => x.Type == "THE_CLAIM_YOU_WANT_TO_USE_TO_IDENTIFY_USERS").First().Value;
return username;
Next, register it using DI:
services.AddSingleton<IUserIdProvider, MyUserIdProvider >();
Now, when you want to send events from the server, use DI in your constructor to pull down an instance of your SignalR Hub
as per usual:
private IHubContext<PuppyHub> puppyHub get;
public UsersController(IHubContext<PuppyHub> _puppyHub)
puppyHub = _puppyHub;
Then, where when you want to tell your clients about the new Puppy
:
// ... typical controller code
// assume we have a var, puppy, with a list of authorized users
// use System.Linq to get a list of userIds where the user is authorized to read the puppy
var authorizedUsers = (IReadOnlyList<string>)puppy.users.Where(x => x.permissions.read == true).Select(i => i._id).ToList();
// send the new puppy to the authorized users
await puppyHub.Clients.Users(authorizedUsers).SendAsync("SendPuppy", puppy);
And viola! You have now done resource-based authorization with SignalR.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53269827%2fnet-core-signalr-how-to-accomplish-resource-based-authorization%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
From the beginning, I had the feeling that the answer lay in IUserIdProvider
, but I didn't see how that would work for multiple users.
I finally found the answer, but it'll definitely need some cleanup.
First, create your own implementation of IUserIdProvider
as follows:
public class MyUserIdProvider : IUserIdProvider
public string GetUserId(HubConnectionContext connection)
var username = connection.User.Claims.Where(x => x.Type == "THE_CLAIM_YOU_WANT_TO_USE_TO_IDENTIFY_USERS").First().Value;
return username;
Next, register it using DI:
services.AddSingleton<IUserIdProvider, MyUserIdProvider >();
Now, when you want to send events from the server, use DI in your constructor to pull down an instance of your SignalR Hub
as per usual:
private IHubContext<PuppyHub> puppyHub get;
public UsersController(IHubContext<PuppyHub> _puppyHub)
puppyHub = _puppyHub;
Then, where when you want to tell your clients about the new Puppy
:
// ... typical controller code
// assume we have a var, puppy, with a list of authorized users
// use System.Linq to get a list of userIds where the user is authorized to read the puppy
var authorizedUsers = (IReadOnlyList<string>)puppy.users.Where(x => x.permissions.read == true).Select(i => i._id).ToList();
// send the new puppy to the authorized users
await puppyHub.Clients.Users(authorizedUsers).SendAsync("SendPuppy", puppy);
And viola! You have now done resource-based authorization with SignalR.
add a comment |
From the beginning, I had the feeling that the answer lay in IUserIdProvider
, but I didn't see how that would work for multiple users.
I finally found the answer, but it'll definitely need some cleanup.
First, create your own implementation of IUserIdProvider
as follows:
public class MyUserIdProvider : IUserIdProvider
public string GetUserId(HubConnectionContext connection)
var username = connection.User.Claims.Where(x => x.Type == "THE_CLAIM_YOU_WANT_TO_USE_TO_IDENTIFY_USERS").First().Value;
return username;
Next, register it using DI:
services.AddSingleton<IUserIdProvider, MyUserIdProvider >();
Now, when you want to send events from the server, use DI in your constructor to pull down an instance of your SignalR Hub
as per usual:
private IHubContext<PuppyHub> puppyHub get;
public UsersController(IHubContext<PuppyHub> _puppyHub)
puppyHub = _puppyHub;
Then, where when you want to tell your clients about the new Puppy
:
// ... typical controller code
// assume we have a var, puppy, with a list of authorized users
// use System.Linq to get a list of userIds where the user is authorized to read the puppy
var authorizedUsers = (IReadOnlyList<string>)puppy.users.Where(x => x.permissions.read == true).Select(i => i._id).ToList();
// send the new puppy to the authorized users
await puppyHub.Clients.Users(authorizedUsers).SendAsync("SendPuppy", puppy);
And viola! You have now done resource-based authorization with SignalR.
add a comment |
From the beginning, I had the feeling that the answer lay in IUserIdProvider
, but I didn't see how that would work for multiple users.
I finally found the answer, but it'll definitely need some cleanup.
First, create your own implementation of IUserIdProvider
as follows:
public class MyUserIdProvider : IUserIdProvider
public string GetUserId(HubConnectionContext connection)
var username = connection.User.Claims.Where(x => x.Type == "THE_CLAIM_YOU_WANT_TO_USE_TO_IDENTIFY_USERS").First().Value;
return username;
Next, register it using DI:
services.AddSingleton<IUserIdProvider, MyUserIdProvider >();
Now, when you want to send events from the server, use DI in your constructor to pull down an instance of your SignalR Hub
as per usual:
private IHubContext<PuppyHub> puppyHub get;
public UsersController(IHubContext<PuppyHub> _puppyHub)
puppyHub = _puppyHub;
Then, where when you want to tell your clients about the new Puppy
:
// ... typical controller code
// assume we have a var, puppy, with a list of authorized users
// use System.Linq to get a list of userIds where the user is authorized to read the puppy
var authorizedUsers = (IReadOnlyList<string>)puppy.users.Where(x => x.permissions.read == true).Select(i => i._id).ToList();
// send the new puppy to the authorized users
await puppyHub.Clients.Users(authorizedUsers).SendAsync("SendPuppy", puppy);
And viola! You have now done resource-based authorization with SignalR.
From the beginning, I had the feeling that the answer lay in IUserIdProvider
, but I didn't see how that would work for multiple users.
I finally found the answer, but it'll definitely need some cleanup.
First, create your own implementation of IUserIdProvider
as follows:
public class MyUserIdProvider : IUserIdProvider
public string GetUserId(HubConnectionContext connection)
var username = connection.User.Claims.Where(x => x.Type == "THE_CLAIM_YOU_WANT_TO_USE_TO_IDENTIFY_USERS").First().Value;
return username;
Next, register it using DI:
services.AddSingleton<IUserIdProvider, MyUserIdProvider >();
Now, when you want to send events from the server, use DI in your constructor to pull down an instance of your SignalR Hub
as per usual:
private IHubContext<PuppyHub> puppyHub get;
public UsersController(IHubContext<PuppyHub> _puppyHub)
puppyHub = _puppyHub;
Then, where when you want to tell your clients about the new Puppy
:
// ... typical controller code
// assume we have a var, puppy, with a list of authorized users
// use System.Linq to get a list of userIds where the user is authorized to read the puppy
var authorizedUsers = (IReadOnlyList<string>)puppy.users.Where(x => x.permissions.read == true).Select(i => i._id).ToList();
// send the new puppy to the authorized users
await puppyHub.Clients.Users(authorizedUsers).SendAsync("SendPuppy", puppy);
And viola! You have now done resource-based authorization with SignalR.
answered Nov 12 '18 at 22:19
Nickdb93
196115
196115
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53269827%2fnet-core-signalr-how-to-accomplish-resource-based-authorization%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown