✅ C# private endpoint security: How should it be done?
Hi,
I am working on a backend API which I want to be tightly coupled with Discord (some entity keys will be Discord snowflakes, like users and servers).
My private endpoints will look like this: /users/:userId/servers/:serverId
Because of this, I am trying to figure out how to go about authorization for my private endpoints. This is a bit tricky for me because I want to do a couple things:
- Validate route parameter input (snowflake regex)
- Verify user existence and ownership (ensure user ID provided in route matches the session identity user ID and that user exists in DB)
- Verify server existence and ownership (check with discord API on writes, check database on reads, only if this is an ideal approach)
As far as I know, I am sort of limited with my options(?), because I would prefer a custom failure response object (not just basic 401-404 which .NET provides for policies, route constraints or whatnot), the cheaper checks to run first (route validation and user ownership verification), and I want reusability for multiple private endpoints, or probably all?
What are my options? What do developers normally do in these type of situations?
Thanks for any help!
101 Replies
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Oh man, that's huge topic :kekw:
Here you have playlist for authentication and authorization in C#
In general it's a huge topic and I am still not quite good at it but, since I am messing with it rn, I can tell few things:
You can make requirements and requirement handlers, so for example we could have 2 requirements here:
And second requirement for checking server existence, server owner etc.
You can then inject
IAuthorizeService
and use .AuthorizeAsync
with those requirements. You have your return value from that and then you can decide what to return from your endpoint handler ^^.
That's one way of doing that.
Or you can simply check all of that in route handler, I overengineered that xDUnknown User•2mo ago
Message Not Public
Sign In & Join Server To View
It's not just for a bot. I'd rather not reveal too much, but basically I am working on a backend API for a SaaS website and a discord bot eventually.
Users login via Discord and can register their servers, etc.
To my understanding, they run in parallel and you cannot set a specific order unless you use it in code (not as an attribute). Am I correct on this?
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
I would just use that. And then in route handler:
(sorry, I like controllers)
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
in that way you can run them with your desired order
you can also pass all your requirements but you don't have guaranteed order as specified in docs
This is what I was concerned about. For example, I'd probably want the cheap checks to run first so that heavy API calls aren't firing even when the request fails by one of the cheap checks
or you can just write single big requirement and handler for that. And in one handler check both, user ownership and server ownership
This is slightly confusing for me, I'll have to read up more on it I guess
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
That is true
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
This entire auth stuff in .NET is very confusing and complicated when you're learning it. But when you get it, you see how flexible it is
So, to see if I am understanding, let's say this specific controller's endpoints will all have the same authorization requirements after all (check user, check server ownership (only call discord API based on request method, etc), then I should just make one big policy like Scuro said and place as attribute over entire controller perhaps?
I'm sure it just needs to click for me
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
It would probably be the latter here
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Oh and you have also Resource Based Authorization, that is fun too! But I guess overkill for this scenario.
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/resourcebased?view=aspnetcore-9.0
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
So, a policy can have more than 1 requirement?
Like
yes
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
.AddPolicy("test", new(), new())
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
This definitely would work, but I was hoping to try attrributes first
unless it it doesn't end up being ideal for my use-case
I see.
Attribute wouldn't work here well
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Can one policy have multiple requirements or do I have to make them different policy names?
Like, "GetOwner" and "GetOwnerWithUpdate" or
idk those were random names
but you get the idea
Well, you could make policy for that and then in requirements handler get route params from http context to validate that xD
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
oh, there is ❤️
That is fun too
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Nevermind, I see it now
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
that makes sense
Custom Authorization Policy Providers in ASP.NET Core
Learn how to use a custom IAuthorizationPolicyProvider in an ASP.NET Core app to dynamically generate authorization policies.
this 😄
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
but you can't pass route params to attribute, can you?
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Wait woah, what is an "AuthorizeAttribute" vs
IAuthorizationRequirement / AuthorizationHandler
AuthorizationHandler
handles requirements 😄
Requirement is class that you can put in any data you want and have access to that in handlerUnknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Ohhh, AuthorizeAttribute seems to be just for further customization I am seeing
whoah, I didn't know about that
And was doing that in
ValidatePrincipal
event handler XDUnknown User•2mo ago
Message Not Public
Sign In & Join Server To View
smart
That's nice, I must check it out
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
So basically using claims to hold the in-memory data potentially needed other than some other way?
whoops. wrong reply
Oh my god XD
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
I think what will be the toughest about all of this is just how many different ways there is to do one thing, and how to strategize/structure things
Alright, pretty nice
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Well, .NET gives you a lot of tools it's up to you how you use it 😄
Except for Blazor, I feel very limited while using Blazor.
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
oh no xD
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
understandable
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Well, I am doing small project in work rn and I decided to not implement anything like that. I am just using roles from Microsoft Entra ID :kekw: But I can do that, coz project is very simple
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Whoah, that's big
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
I see
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
So, based off of what you just said, if these were my two current endpoints:
- PUT /users/:userId/servers/:serverId
- GET /users/:userId/servers/:serverId
I should probably:
Make two policies (like "PrivateEndpointPolicyWrite" and "PrivateEndpointPolicyRead", these are just example names) and make the 3 requirements which are slightly dynamic, like with the write, the requirement is set to use Discord api (eg, UseDiscordApi = true) and the read is slightly different?
If so, the only problem would be the order again, I think.
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
the firing order of them
like
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
omfg
i get it
:facepalm:
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
so you're saying the API doesn't return on the first failure, it checks all at once?
not API
auth
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
yes
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View

Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
"It is not short-circuit"
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
this is what I was concerned about mostly
yes
I understand this bit
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
In my head, I was thinking context.fail() was cancelling the auth immediately
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
I totally get this now
at least the very basic idea of it
it just clicked for me
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
no worries
thank you for your help
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
lunch?!
I haven't even slept yet, it's 6 AM
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
Jeesh
So
UK?
Germany?
I'm guessing somewhere around there
I'm not good with locations but know Wales is around 5 hours ahead
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
anyways shit, goodnight lmao
Definitely not Poland, we don't have lunch in here
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
tru, my first coffee today
hmm, you must be in similar timezone as me xD
Unknown User•2mo ago
Message Not Public
Sign In & Join Server To View
I am procrastinating since 2h ago