Keycloak business attributes/context based access control/authorization - authorization

I am looking for support of resource attribute authorization in Keycloak.
I have a REST service which takes a datamodel (in JSON format) as body. Based on certain attribute of this Json, I want to deny or allow the request.
I know I can put my validation or kind of custom authorization logic as a layer, but I am looking if Keycloak provides any out of the box support for it like CBAC or Resource ABAC?

Related

Is it okay to call multiple microservices from your authorization microservice?

I want to add authorization details about objects, sort of like roles associated to each object in my application as claims in my jwts. So is the right way to do this by adding calls from my issuer to the individual microservices that deal with the particular object or some other way to ensure what permissions the user has with the particular object. How would I dissociate the access token upon a change in the permissions instantly?
I have a object called namespaces that holds multiple different objects inside it, would I add API calls from the sub objects microservice to the object microservice to ensure valid permissions? But then I wouldn't be able to add it to my API gateway?
For reference I'm using
Django Rest Framework Simple JWT for login
I would also like to add token authentication to integrate with other clients but that's something I'd like to do in the future.

How to pass custom argument to authorization policy

I need a custom attribute for my rest API in asp.net core MVC. I want to add this attribute optionally to some of my APIs. This attribute checks if the API is accessible to user or not based on some condition and throws a 403 if it's not accessible. I was using filters to achieve this and the issue with filter is that filter code gets executed whether the attribute is added or not to my API.
I would want that my filter code is executed only when this attribute is added to the API.
My colleague suggested that I should be using authorization policy instead of filters for this use case. Policies are executed only when it's added to the API. Also since I am throwing 403, authorization policy is a better candidate. I explored authorization policy but my issue is I am unable to pass custom attributes to Authorization policy.
For example, I was able to do this using filters and custom attributes.
[MyCustomFeature("param1", "param2")]
How can I do the same in authorization policy? I am using this example for authorization policy.
Custom Authorization attribute asp.net core
See here. Strongly recommend reading top to bottom.
The summary is that, regardless of how you tap in to the policy-basd auth system, a policy is always resolved via a single string. So, to get what you want, you need to:
Implement a custom attribute that subclasses AuthorizeAttribute and that takes the arguments you pass in and uses them to generate a policy name string. Read the "Custom Authorization attributes" example in the linked docs page closely, see how it actually stores the value of "Age" in the Policy string.
Implement and register a custom IAuthorizationPolicyProvider that can interpret the strings generated by your custom attribute and generate the appropriate policy on the fly.
There's not a ton of code involved and it's not super complex, but it's a little strange/awkward that it comes down to putting stuff into a string.

Look up the user with bearer token with Openiddict Core

I am currently using Openiddict, Identity and Entity Framework to manage my users and assign Bearer tokens to users to protect my API.
My infrastructure is currently using ASP.NET Core Web API in the back end and a separate React application in the front end. The React application makes HTTP calls to my API to retrieve it's data. There is no server side HTML rendering at all in the back end.
Everything works as I need it to for the most part. I can register users and retrieve tokens from the API. These tokens are included in my HTTP call in the Authorization header. My AuthorizationController uses this: https://github.com/openiddict/openiddict-samples/blob/dev/samples/PasswordFlow/AuthorizationServer/Controllers/AuthorizationController.cs with a few minor tweaks. My Startup.cs also uses almost exactly this https://github.com/openiddict/openiddict-samples/blob/dev/samples/PasswordFlow/AuthorizationServer/Startup.cs
In some instances, I need to make API calls to the endpoints that are specific to the user. For instance, if I need to know if a user has voted on a comment or not. Instead of passing along the users ID in a query string to get the user details, I would like to use the Bearer token I received that they use to make the API call for that endpoint. I am not sure how to do this though.
In some research I have done it looks like some samples use ASP.NET Core MVC as opposed to the API to retrieve the user with the User variable as seen here https://github.com/openiddict/openiddict-samples/blob/dev/samples/PasswordFlow/AuthorizationServer/Controllers/ResourceController.cs#L20-L31 however this seems not to apply to my infrastructure.
My question is how do I look up a user based on the Bearer token passed to the API to look up a users details from my database? I am assuming that all of the tokens passed out by the API are assigned to that specific user, right? If that's the case it should be easy to look them up based on the Bearer token.
The question is: How with Openiddict can you look up a user based on the token that was assigned to them for API calls? I need to get the user details before anything else can be done with the application first. Is there something baked internally or do I have to write my own support for this?
When you create an AuthenticationTicket in your authorization controller (which is later used by OpenIddict to generate an access token), you have to add a sub claim that corresponds to the subject/entity represented by the access token.
Assuming you use the user identifier as the sub claim, you can easily extract it from your API endpoints using User.FindFirst(OpenIdConnectConstants.Claims.Subject)?.Value and use it to make your DB lookup.

Conditional Attribute Routing

When using attribute routing, is it possible to remove routes based on certain runtime condition - such as licensing?
Something like this:
[LicensedRoute("/api/whatever")]
where '/api/whatever' is only added to the route table if the application is licensed.
Obviously I can explicitly do the check in the action method or use an action filter to validate the requests but ultimately I prefer the route not to be available if the software is not licensed.
Seems you need Attribute Routing: http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
Is it RESTful? How you store the licensing info: is it user logins? tokens? key?
You could do it RESTful and force the client to pass a token every time via token-based authentication, for example: define several "licence" levels/types (eg. Free/Trial/Basic/Pro) and then in a persistent storage (table) map tokens (guids) to a licence type.
Then using a custom attribute, mark each endpoint/controller/action with the minimum required licence type to be accessible (e.g. [MinimumLicence("Basic")]). And then create "routing tables" based on the licence required.
In this case you would deny access to routes rather than "remove" them.

RESTful API for authroization, plan features control

I am working on a web app. Front-end only interacts with back-end through RESTful API(it's called SOA architecture), and back-end only sends data to front-end in JSON.
My question is:
1) is it the best practice to design the authorization through RESTful API? or it is best to check authorization (user-> role -> privilege) at back-end code?
e.g.: do we ask user /checkPrivilege/{...} every time before executing other API?
2) How it is usually to implement 3 plans with different features & UI in RESTful API?
e.g.: do we use api to limits 5 users for this plan? or we do it at back-end code?
This is an old question, but I'll answer this anyway just in case some looks it up.
The short answer is you do it through the backend. The URI you are requesting should not contain any information about the user. Any session/identifying data should be sent in HTTP Headers.
Your RESTful API is always going to be loaded through a front controller like index.php. This is where you will want to bootstrap an authorization tool to check every single page request for credentials before executing the rest of your code.
Those credentials, at a MINIMUM, should contain a unique authorization token for the user who is making the request, and this token needs to be sent in every request (again, I recommend via an HTTP header). Bonus points if you grant a temporary access token that will expire, so as to prevent unauthorized access at a later date.
But for simplicity, let's say you are just using a permanent unique token per user. You would then store this token along with all the other data about the user, that other data should include an account_id for the account that user is a part of.
So for each request you would:
grab the user token from the HTTP Header
Look up the user based on that token.
If the user is found, then use their account_id to look up the master account their personal account is associated with
If it matches, grant them access
But remember, your URL should never contain this information in anyway. RESTful URLs are stateless.