1

I have a Web Api 2 endpoint which I am trying to secure with a custom Authorize attribute. Inside of that attribute I check if the user has the necessary roles like:

            if (!user.HasRoleInInstitution(institutionId, Role.SomeRole))
            {
                filterContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
                return;
            }

The problem I am having is the institutionId. The endpoint should be accessible in institution context in which every user can have different roles in different institutions so the check should check if the user has roles in the given institution the user is accessing.

I could store the currently accessed institutionId in Session like:

var session = HttpContext.Current.Session;

This however:

A) Is against REST principles as the endpoint should be stateless

B) Sessions access tend to take long so this introduces a performance overhead not tolerable in scenarios like Authorization.

I could also pass the institutionId from the client on every request and then use RouteData to retrieve it in the Attribute like:

var institutionId = filterContext.ControllerContext.RouteData["institutionId"]; 

The problem with this approach is:

A) If another developer uses "someInstitutionId" instead of "institutionId" as route parameter then this check will break

B) The passing of the institutionId on every request is a horrible waste of bandwidth

Finally I could just add a currently accesed institutionId prop to user or pass around cookies but that forces the user to relog every time he wants to use a different institution and he cannot have multiple instances of the application open for different institutions which is a hard requirement.

What would be the best approach for scenarios like that?

qubits
  • 1,227
  • 3
  • 20
  • 50
  • research JWT (Json Web Tokens). store the necessary permissions in the token and validate it when request is made – Nkosi Oct 31 '18 at 12:35
  • "The passing of the institutionId on every request is a horrible waste of bandwidth" Why? How big is it? – NetizenKane Nov 02 '18 at 11:41

1 Answers1

1

So you don't want to use Session because it's against REST (and that's great!) but you don't want the client application to send you the institutionId inside the request... This is a problem of logic. I mean just think about it.

How the client application can provide you the information if it's not inside the request because you don't use Session? It HAS to be inside EVERY request. And it's not a "horrible waste of bandwitch", your institutionId is not a 2Go information so...

Just use the JWT, store the institutionId inside, like this every time the client will try to access a method inside your controller the Authorize attribute will check if he's got the access and it will work greatly even if he had multiple instance of the application because the institutionId will be provided by the JWT on EVERY request! :)

And if you don't want the user to login each time he opens the application inside an another institution just make the client application write the institutionId inside the token. So he logs in with ClientApp1 you give him a token without institutionId, but when ClientApp1 make a call it write the institutionId inside the token, like this you can check the access and if the client open ClientApp2 you automaticly provide the token that you provide to ClientApp1 (so the one without institutionId) and ClientApp2 will overwrite the institutionId and send you the institudionId related to ClientApp2.

Max
  • 794
  • 3
  • 7
  • This is the same suggestion I said with passing it around in the cookie but instead of a cookie header you have a JWT claim. I am absolutely aware of JWT token authentication and use it on every new project that I am starting since that's the most optimal way of handling these kind of situation nowadays but the application is an old brown-leaf project with a robust domain and authentication mechanisms existing with forms authentication running identity framework and switching it over to JWT now is unrealistic. Thanks and + regardless for the effort answering. – qubits Nov 02 '18 at 11:49
  • If the back-end use Identity Framework you can use Bearer token, it's easy to implement and it would provide you the same flexibility: https://stackoverflow.com/questions/42086149/asp-net-identity-bearer-token-vs-jwt-pros-and-cons http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/ – Max Nov 02 '18 at 15:41
  • It's an old post, I already have it implemented with institution passed through routes, I was mainly thinking whenever there is a better way outside of passing tokens around. It's not an answer to my question concretely but I will tag it as so since it is theoretically the best answer for new projects. – qubits Nov 04 '18 at 12:10