How to access the SignalR Hub arguments from [Authorize()]? - asp.net-core

I'm making a signalr hub for a chat app (it's not really, but lets pretend it is).
I have my authorization set up so that user can be invited to a room by the creator of the room. So there's a table that stores who owns what, and who has been granted access.
This is good. Next steps were to add claims so that I didn't have to check who had access to what on every request. I check once when a user tries to join the chat room, add their claims, and send them to the page that starts the signalr connection.
Now I want to use the [authorize] decorator on my hubs, instead of throwing boilerplate
user.Claims.Any(x=> x.ClaimType == $"CanJoinRoom_{RoomId}");
everywhere.
I've read up on how to make custom policy based authorization here:
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies#security-authorization-policies-based
I have every piece I need except one: the actual arguments that specifies the room id. I have been able to hack something from
[MyCustomAuthorizeMethod(this.Context.Request.Form["data"])]
but this seems a bit ugly, and to make it work I have to serialize this json
{"H":"myhubname","M":"Initialize","A":[39],"I":0}
Which seems really hacky. I'd much prefer to pass the RoomId as a parameter.
It is just one line down but seems a world away. Is there an elegant way to do this?

If you want to authorize invoking a given method you can put the AuthorizeAttribute on the hub method. You may also find this post on hub authorization and authentication helpful.

This is impossible because attributes are computed at compile time and therefore cannot have variables. Thanks to Pawel for pointing that out.
https://stackoverflow.com/users/1168070/pawel

Related

How to use AuthenticationSchemeOptions.Events or AuthenticationSchemeOptionsEventsType?

Ok, so as per usual, MSDN is now an automatically generated blob of useless documents, so maybe the developers lurk around here and can explain this to me.
I created a custom Authentication scheme based off of the AuthenticationHandler<TOptions> base class. I have two questions regarding this:
How do I define the type to use in AuthenticationSchemeOptions.EventsType in order to consume authentication-related events?
If the loggerFactory object a required object? Can't I just pass null to it? I want to control my output. I guess I could test this one myself. If you want to answer, go ahead, otherwise I'll test it at some point.
But what I have no clue whatsoever is for question 1. I see the class JwtBearerEvents as a sample, but I have no idea if I should be creating one exactly like that, or in general, how does this event system works at all???? I am utterly confused.
Thank you.
P. S.: I don't think it is important, but just so you know, the custom authentication handler basically validates a JWT created by a federated API server whose signing keys can be queried to verify signature. So basically it is a handler that makes a web request (then caches the keys) and uses those keys to validate the token and extract the claim data of interest, finally creating a ClaimsPrincipal user out of said claims.

Spring secutiry custom authentication manager vs custom provider vs custom UserDetailsService

I've been knocking my head up against this problem for a few days now and after seeing dozens of examples all over the web I'm no closer to a solution.
I need to to various types of login, eventually. For right now I'd settle for one. I would like to login using fields other than username and password. Let's say I want to use name, last name and birthdate.
I thought the easiest way to go was to just implement my own UserDetailsService and plug it into my provider. But UserDetailsService only has one method, loadByUsername, which doesn't seem to be the most intuitive way to load my user.
So then I thought it would be better to implement my own AuthenticationProvider ... or simply extend DaoAuthenticationProvider, and override the authenticate() method. But that method takes an Authentication as a parameter ... can I used a POJO, with only name, last name and birthdate fields, as an Authentication object?
Ditto for Authentication Manager. In fact, in the api for AbstractUserDetailsAuthenticationProvider (where the authenticate() method lives) it says that it "Performs authentication with the same contract as AuthenticationManager.authenticate(Authentication)"
But people seem to implement Providers more than Managers. oddly enough, most examples of "custom" Providers and UserDetailsServices ... all implement authentication with username and password, which is was Spring Security does by default anyway!
Can anyone shed some light on this subject? As I said, there are tons of examples but they are all very similar and none that I can find use an Authentication Object that isn't username/password.
Bonus points if someone could also tell me the best way to go about having more than one Provider/Manager -- for example, one like the one described above, and another that authenticates using name and social security number, for example -- and to use one or the other (not both, and not the second one if the first one fails!) depending on a parameter pass from the url, for example.
I'm not sure if you had already solved this challenge. But, it seems that I have a similar case with you. My login page requires additional field 'organisation' aside from 'username' and 'password'. Here is what I did:
I've used custom AuthenticationManager and custom UsernameAndPasswordAuthenticationFilter.
The custom filter is for retrieving the additional field from HttpServletRequest. I added the field to the session and retrieved it inside custom AuthenticationManager.
Performed authentication with the three fields using another bean/service.

Is session a good choice?

We are building ASP.NET MVC app that is supposed to manage sport objects reservations (tennis courts, squash courts etc).
Users are not supposed to act only in scope of one club at the moment of interaction with app.
Navigation to the app should be like:
appname.com/clubName or
clubName.appname.com
Questions:
1. What would be the best way to persist the data about selected club. We have implemented storing in session (injecting information about the club durint app opening), but we read that using session is rather deprecated solution. We are using ApiController so in order to get the session we had to hack the routing (registering custom RouteHandler). Is session mechanism applicable for this problem?
var session = HttpContext.Current.Session;
if (session != null)
{
service.ClubName = session[CustomSessionKeys.ClubName.ToString()].ToString();
}
Is it good idea to use subdomains for our problem?
Many thanks in advance :)
Generally a web api works differently than a normal mvc app.
In an MVC application you would use a session cookie to make the internet act like a state machine. However, this is not what is generally done for web api's. In a web api, you provide some form of authentication (e.g. via the header authentication field).
But within a request you ofcourse want to to keep track of the current user, or in asp.net terms, the current principal.
We set the principle though a Delegation handler
HttpContext.Current.User = user;
If you want some more code on how this whole authentication is done, just let me know.
This was all serverside ofcourse, on the client side, you can keep any information you want in a session store. Although you might want to consider using the local storage in stead (depending on what semantics you want to give it). They both work in the same way.
You can consult W3C webstorage specification for the complete information on both of these.
Well you have many choices I guess!
Go with the route thing as you suggested, where you keep the club Id or name as part of the URL. I would go for this if I need the link to give more meaning to the user.
Cookie! yes, if the information is not sensitive store it in a cookie. In case this cookie is only to be accessed from server side, then don't forget to make it HttpOnly
Session. I agree with you, I wouldn't choose session unless the data was very sensitive and I needed to make it secure.

Is this a correct implementation of REST?

Im steadily building the resources of my API, however after much research on the correct ways to build a RESTful API, I have been unable to find an example of how 'complex' requests should be received.
For example, as part of the login process (which is little more than an authentication key update), the following URI is dispatched by the client:
/api/auth/login
There are no values on the URI, the resource is /auth/ and the command being triggered is /login/. The actual login details are sent to the server Authorization header.
Now, what prompted me to ask this question is as I was writing a command to allow the client to get a reminder of how long the key is valid for, I was immediately drawn to getkeyexpiration or something similar as a command name.
Suddenly I felt that this doesn't sound like what I read about in the 6 constraints, this feels more like operation calls.
So, based on the above examples, is this still a RESTful API? I am concerned as I cannot think of a way to perform this by simply using URI resource names and appended values.
Thank you
EDIT:
From reading this: http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http
I am starting to understand that by naming resources and only resources with noun words, the context of how the server will operate becomes a lot clearer.
Regarding my above example:
/api/auth/login
I have used auth as a prefix of login, because that is the context of the resource. I am designing my system to be extendible and require a way to categorize resources on the URI level. Is there a standard way of doing this?
Your RESTful resources should be nouns, because HTTP provides the verbs.
I would suggest something like this instead:
/api/key
Which you can then POST to (with HTTP Authorization headers included) create a new key, returning something like this:
/api/key/1234ABCDBLAHBLAH
This is a key specific to your session, which you can then GET to retrieve details about it such as expiration time, etc. You will have to pass that key with each subsequent request, of course.
If the key stuff sounds clunky when discussed in the context of a RESTful API, it's because it usually is. Sessions are human/browser concepts, but RESTful APIs are application/integration concepts.
Since servers don't "log on" to other servers, this begs the question: if you're already OK with requiring the caller to pass an Auth header to your login API, why not just require it be passed for each API call, and forget the notion of keys altogether?

How much state can I save in session variables for a web app?

I'm coding up a REST/RPC API for a web app that I'm creating. From what I've learned it seems like one of the core ideas behind REST is to not maintain any state. That said I find myself doing things like marking a session as authenticated on the server side of things and this feels like saving state. How far should I take this practice? Where should I draw the line? There are other things that would be really convenient to save as part of the session's variables but I'm wondering how do I know when I shouldn't or shouldn't do this.
I hope this is the right venue to ask this question. I debated on whether or not to post it in programmers but this just felt more appropriate.
UPDATE:
I'm told that using a ticketing system is better than using session variables to maintain things like auth information. Could someone include and answer that has a very highly description of how such a ticketing system would work?
You are correct - REST calls are ideally stateless, and storing something in a session variable, and using that for the REST call, is anathema. You can't, for instance, guarantee that a RESTful client can even send the cookie information necessary for the session variables.
If you need authentication, then you should have REST calls that return something like a ticket, then the REST caller would send that ticket as part of another call.
UPDATE
For a ticketing system, you generally want to use the same auth or similar auth system. For instance, if you require a user name and password, you might want the ticket request to POST that. A ticket is a GUID that is passed on subsequent calls. The ticket on the server can be stored in session, or in a DB (I typically have a TICKETS table, with things like expiration dates).
$result = file_get_contents('http://site.com?action=auth&user=matt&password=pass');
// parse $result XML for ticket or auth error
// subsequent calls...
$result = file_get_contents('http://site.com?action=getSomething&ticket=" . $ticket);
QuickBase works this way - you send an API_Auth action with a username, password and api app token, and get a ticket in return. Then you pass your api app token and the ticket on subsequent calls - both GET requests and POST sends.