Negative logic for UMA Policy in Keycloak - keycloak

I want to manage policies for my resources in Keycloak through a UMA compliant endpoint. So I created a resource profile with scopes view_users, invite_users, edit_users.
Then I moved on to creating Policies using the Policy API.
## POST
{
"name": "can_view_users",
"logic": "NEGATIVE",
"decisionStrategy": "AFFIRMATIVE",
"clients": ["uma_postman"],
"scopes": ["view_users"],
"roles": ["uma_postman/lg_admin", "uma_postman/sales", "uma_postman/customer_admin"],
"users": ["37ae8b1e-f1b0-4e72-b6ac-5ad1e49f89d7", "3627cb69-23ed-474d-abec-8f31b230b730"]
}
I can query this(GET http://localhost:8080/auth/realms/ng_whs/authz/protection/uma-policy) and it seems that the policy is created properly.
Now my understanding is that since the decision strategy is AFFIRMATIVE & the logic is NEGATIVE, for any of the above roles - lg_admin, sales, customer_admin or the user with the above ids, I should not be allowed access to the resource.
However, when I query as a user with the above role or id, I still don't get access denied.
Now when I change the logic to POSITIVE for the same policy, the response is still the same. Am I missing something here? Any help would be really appreciated. :)
I was following the instructions from here - keycloak.org/docs/latest/authorization_services/#_service_authorization_uma_policy_api

Related

Multiple accounts in a single JWT token

I am building a solution, where a single user should be able to access resources from a API spaning multiple accounts using a JWT token.
The setup is quite simple: I have a API exposing resources related to an account, e.g:
[api]/account/{account_id}/orders
However a user should be able to access multiple accounts, but with different permissions for each account (like admin and guest). I however am unsure about how this should best be expressed in the access token, and I have not been able to find an example online addressing this issue.
My current idea would be to have a payload like:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"aud": "[api]",
"accounts": [
{
"account_id": 123,
"roles": ["admin"]
},
{
"account_id": 234,
"roles": ["guest"]
}
]
}
In theory the "roles" property could be replaced on scopes related to the specific account, mimicking then root level scopes. However, if there exist a standard way to achieve this, I would prefer going in that direction?

Update Stock_level in OCAPI

How I can update the inventory (stock_level) using (business manager API).
I use the business manager API to retrieve products. I am able to retrieve the products but I am not sure how I can set its stock (stock_level).
I have a special requirement where product quantity cannot exceed 1, so for that I need to set it in an inventory so that I can test it.
I have tried to see if I can set inventory level using product but that doesn't seem possible.
When I try to get inventory following is the error
{
"_v": "18.8",
"fault": {
"arguments": {
"method": "GET",
"path": "/data/v18_8/inventory_lists/*"
},
"type": "ClientAccessForbiddenException",
"message": "Access to resource 'GET /data/v18_8/inventory_lists/*' is not allowed for the current client."
}
}
There is actually a DATA API endpoint that can be used to update inventory. It is called the ProductInventoryRecords resource.
You can update a product inventory record with a PATCH eg:
PATCH /inventory_lists/{inventory_list_id}/product_inventory_records/{product_id}
With a ProductInventoryRecordAllocation payload as such:
{
"_resource_state" : "847f9c3c5867f641470b3046aeec31f07757991b792d722e10079926f7a289fb",
"allocation": {
"amount": 2000,
"reset_date": "2016-03-31T14:05:40.872Z"
}
}
See more about this document type here.
Please note that the best practice is to pass the _resource_state key to ensure that the record is properly updated. OCAPI checks to see if this value is the same as the current state of the record if that attribute provided.
So systems should first check the record to get the _resource_state by performing a GET on the same resource.
Edit Note that you'll need an authorization token that grants you access to the API in order to make this kind of call.
your question is not crystal clear but I will try to answer. Commerce Cloud has three distinct (OCAPI) APIs:
Shop API (provides similar access as a customer on the site)
Data API (provides similar access as a merchant using business manager)
Meta API (describes the API from a functional perspective)
To get availability of a product in the inventory use below call: {{shop_url}}/products/701644676568M/availability and look at ATS in the response.
To set the stocklevel go into to business manager or use business manager import utility. There is no out-of-the-box API to update the stocklevel.

PUT list to a mapping collection. Only id array in request body?

I'm designing a REST interface for my service. My service will be Role and Permission based. Therefor a Role will contain Permissions.
Meaning a Role will have a collection of Permissions -> roles/1/permissions
Now I would like to change the set of Permissions for a Role. As I understand, a correct request for this would be:
PUT roles/1/permissions
[
{
id: 1,
permissionName: "read"
}, {
id: 2,
permissionName: "write"
}, {
id: 3,
permissionName: "delete"
}
]
As this basically only maps existing permissions (/permissions) to a role, there is a lot of unnecessary information sent. Especially if this example would contain a resource which is much more detailed as a Permission.
Would it be okay to only send an array of ids in the body?
PUT roles/1/permissions
{
ids:[1,2,3]
}
I would reach the same, with only the information I actually need. Is there a problem with this approach? I'm afraid that this might hurting the stateless principle of REST.
Sending the permission identifiers is just fine to create a link between the a given role and a set of permissions.
On server side, you should validate the permission identifiers and return a 422 if they are invalid. See this answer for further details.
The stateless constraint determines that each request must contain all of the information necessary to be understood by the server, rather than be dependent on the server remembering prior requests. And session state should be handled entirely by the client:
5.1.3 Stateless
[...] each request
from client to server must contain all of the information necessary to
understand the request, and cannot take advantage of any stored
context on the server. Session state is therefore kept entirely on the
client. [...]
Sending only the permission identifiers won't break the stateless constraint.
For more details on the stateless constraint, refer to this answer.
Your REST API is completely fine and it does not violate the stateless principle in any way. Your REST API will be using a different resource model for GET and PUT methods, which is also fine.

How to post two resources in the same request?

I have /companies and /users resources. My business logic prevents creating company without first user. Only way I can think of:
POST /companies
{
"name": "Harvey's Broiler",
"user": {
"firstName": "Jojo",
"lastName": "Stomopolous",
"email": "jojostomopolous#harveysbroiler.com",
"password": "password"
}
}
Response:
{
"id": 10001,
"name": "Harvey's Broiler",
"user": {
"id": 10002,
"firstName": "Jojo",
"lastName": "Stomopolous",
"email": "jojostomopolous#harveysbroiler.com"
}
}
Later, they can be reachable as:
GET /companies/10001
Response:
{
"id": 10001,
"name": "Harvey's Broiler"
}
and
GET /users/10002
or
GET /companies/10001/users/10002
Response:
{
"id": 10002,
"firstName": "Jojo",
"lastName": "Stomopolous",
"email": "jojostomopolous#harveysbroiler.com"
}
This is a common question developers encounter when designing APIs.
The first question you should ask yourself is are the Company and User resources same order citizens? By order, I mean are they the same importance, are they both resources you massively operate with and have independent roles and operations in the system you are building? My hunch is the answer is yes. If the answer is no, then the User is only a way of denoting the founder of the Company, and you have no problem, just put the User as an embedded object like you already did.
However, if my hunch is right that you have some business logic around User and Company, I would do just that, keep them separate, under separate endpoints.
If you need a User to create a Company, than implement that logic. If a Company is attempted to be created with a missing User, return an error (HTTP response 400, or something along those lines). Of course, that should be documented for the user. The request is than like this:
POST /companies
{
"name": "Harvey's Broiler",
"user": 1234
}
Mashing the creation of two objects under the same request artifically can only lead to issues. Now you need to return the status for both (a User is created, but Company failed?), return two IDs (what if you also need to add other information, tax details, you get a third ID) and so on.
The only valid reason for creating the User along with the Company is if a User is very often created along with the Company, if not always, and you need to reduce the number of API calls, so you only fire one, but I am not sure that is the case.
If you can't even have a User without a Company, than see if you can revise the requirements or create the User/Company in two steps. First fire a request for a User "placeholder" (let's say the User will not be visible in a list of Users or such, it will not be valid), and after creating Company, the User becomes valid and visible, and other operations become permitted. Until that, there is no User, only a placeholder for it. The same can be logic can be reversed for Company.
And another thing, I will not go into this kind of nesting:
GET /companies/10001/users/10002
First, it is usually hard to program (you get a lot of boilerplate), and it is a possible maintenance nightmare. You can extrapolate the case to:
GET /companies/10001/users/10002/accounts/24314/bank/address
And fetch a bank address for a bank of a user who founded a company. I'm hesitant to implement this kind of approach if I do not have to.
Also, please consider reading about HATEOAS. It might help you if you need this kind of nesting. Actually I will always encourage at least considering the HATEOAS principle when starting a new API.

Architectural REST: How do I design a REST API for request+approval, 2 resources or 1?

Let's say you are creating a REST API for a system that requires approval, e.g. a group membership system (closest analogy I can think of).
My resource for membership is /membership. I can see 3 possibilities:
A. Single resource.
So a new request is POST /api/membership which creates {group: 10, user:1, status:"pending"}. The org admin then approves by PATCH /api/membership/:membership {status: "member"}
Pro: single API.
Con: Harder to easily differentiate between different member types; after all, a "pending" member isn't really a member. More importantly, a request to join isn't actually a membership.
B. Separate resources.
A new request is POST /api/join which creates a request to join {group: 10, user: 1, status:"pending"}. The org admin then approves by PATCH /api/join/:join {status: "approved"}. This then automatically (on the server) creates another resources at /api/membership/:membership.
Pro: Cleanly separates requests to join from actual memberships.
Con: Seems redundant (the properties of a request and a membership are similar), and depends on automatically juggling one resource from another on the back-end.
C. Separate resources and requests.
Just like Option B, except that the org admin approves in 2 steps. First POST /api/membership {group:10, user:1} and then PATCH /api/join/:join {status:"approved"}.
Pro: Cleanly separates requests from actual memberships. Also does not rely on background processing of one resource to affect another.
Con: Relying on the UI to do it is even messier!
Help?
I would handle this as two separate resources. A membership request and a membership are two different things. In addition, they may happen to have very similar properties now, but if they diverge in the future you'll be stuck. I would do
POST /membership-requests
{
"memberId": 7,
"groupId": 15
}
to create the request. The admin could do
GET /membership-requests?groupId=15&status=pending
to get requests by group, and then
PUT /membership-requests/12345
{
"status": "approved"
}
to approve the request. You could use server-side business logic to detect the status change and create the membership. That PUT could then return a link to the membership:
{
"memberId": 7,
"groupId": 15,
"status": "approved",
"membership": "/memberships/298"
}
If you do this, your business logic needs to make sure that only pending requests can have their status changed.
If you only use one resource, how will you handle rejected memberships? To me, it doesn't make sense to do a
GET /memberships?status=rejected
because if the request is rejected, that's not really a membership.
Option A is the one I'd choose. It's clean and simple to understand. If I was writing a client app to the API I'd be quickly able to grok it.
The other options force your resources to be verbs (join) which is usually a sign that you're on the wrong track. Well-designed RESTful APIs have the application protocol (usually HTTP) be the layer for your verbs (POST, GET, etc.) and the resources (represented by your URIs) be your nouns.
As to your Con for Option A:
Con: Harder to easily differentiate between different member types;
after all, a "pending" member isn't really a member. More importantly,
a request to join isn't actually a membership.
I think this is a huge Pro, not a Con. For a resource representing members, "membership type" sounds like a perfectly reasonable attribute of that resource. There are plenty of states of membership that you could have later in the member's life, such as "good standing", "dunning", "elapsed", "revoked", "cancelled", "idle", or others. You wouldn't want to create a separate resource for each of those states either, so I'd stick with it being an attribute of the same membership resource to retain flexibility for the future.