Can it be done record-base authorization with keycloak? - keycloak

I am using keycloak in my application for authentication. But currently I need to implement an access list rule mapping so that I can determine whether a user has access to content or not.
Here is what I am trying to accomplish:
Does user have permission to API/entity
- If it does;
* Can it read ?
* Can it write ?
* Can it update ?
* Can it delete?
- If any of these questions yes then user can read, write, update and delete:
* Records that he/she created
* Records that created by his/hers management (role based hierarchy)
My question is that could it be implemented with this kind of authentication (access list) using keycloak?

Related

With SSO (like for example Keycloak), how does one handle/synchronise users in own databases?

Consider the following scenario: you have a SSO service (let's say Keycloak), and X applications, that have their own databases, where somewhere in each database, you're referencing a user_id. How to handle this? How to satisfy the foreign constrain problem? Should one synchronise Keycloak, and the applications? How? What are some best practices? What are some experiences?
I've been using Keycloak for several years, and in my experience there are several scenarios regarding synchronizing user data between Keycloak
and your application's database :
Your application is the owner of the user data.
Keycloak is only used for authentication/authorization purposes. In this scenario, your application creates/updates a keycloak user using the admin rest API when needed.
Keycloak is the owner of the user data and you don't need more info than the userid in your database.
In this scenario everything regarding users could be managed by Keycloak (registration, user account parameters, even resource sharing using the authorization services).
Users would be referenced by userid in the database when needed.
NB: You can easily add custom data to the user in Keycloak using the user attributes but one interesting possibility is to extend the user model directly using this : https://www.keycloak.org/docs/latest/server_development/index.html#_extensions_jpa
Keycloak is the owner of the user data and you need more than just the user id (email, firstname, etc)
If performance is not an issue, you could retrieve user info via the Admin Rest API when needed.
If performance is an issue you'll need a copy of Keycloak's user data in your app's database, and you would want that copy to be updated on every user changes.
To do that you could implement callbacks in keycloak (using SPIs: https://www.keycloak.org/docs/latest/server_development/index.html#_events), that will notify your application when an user is created/updated.
NB : You could also use a Change Data Capture tools (like Debezium: https://debezium.io/) to synchronize Keycloak's database with yours.
There's pros and cons to each scenario, you'll have to choose the one which better suits your needs :)

Use token's username in policy path

I have a Vault server where users will log-in using Userpass auth method and making use of kv secret engine.
The structure is like below -
-- user-kv
-- u1
-- u1-secret1
-- u1-secret2
-- u2
-- u2-secret1
-- u2-secret2
-- u3
-- u3-secret1
Here, u1, u2 , u3 are username of the users logged in using Userpass auth.
Now, for each user, I want to allow access to his path only. His path refers to this structure user-kv/<username>/ For example -
u1 --> user-kv/u1/*
u2 --> user-kv/u2/*
u3 --> user-kv/u3/*
and so on....
I am currently doing this by creating a separate policy for each user and and assigning it to him. I believe this is not the right way as when number of users grow, it would be difficult to maintain.
Is there a way to specify the logged-in user's username in the path in a policy. Something like -
path user-kv/{{username}}/* {
capabilities = ["read", "update", "create" ]
}
I have tried with templated policies but it doesn't work.
path user-kv/{{identity.entity.metadata.username}}/*
path user-kv/{{identity.entity.name}}/*
I can do something like user-kv/+/* but that would mean every user would have access to other's path.
Can anyone point out a more elegant way or provide links for further research?
I don't have a Vault running at the moment to check this out, sorry, but I believe that the templated policy you tried should work. The key is to create an identity that is associated (via an alias) with the userpass user. It's been a while since I've done this, so I can't remember the details, but check out the docs: https://www.vaultproject.io/docs/secrets/identity
The basic idea you have is feasible, but it is a lot more complex than that.
First, some background
A user in Vault is called and entity. When you authenticate for the very first time, a Vault entity will be created automatically, unless one already exists.
Obviously, you had to login with some auth backend. Let's say you used LDAP. Whatever you actually used is irrelevant for this discussion.
When you authenticated, an entity alias was created to tie this specific user in that specific auth backend to an entity.
With that background information, here is where it gets complicated.
Vault supports multiple auth backends, and you can tie them all to a single entity. So if our user prefers to login with the Github auth backend, he still keeps his access rights (aka policies). That happens because you would have set the entity alias prior to the user logging in.
Now even if you are using a single auth backend, Vault will still behave like that, because it can't know what the future holds.
Now back to your question.
To allow a path to represent a user, you must use the syntax described here. But to use them, you need to know in advance either:
The name of the entity
The name of the user in the auth backend
Option #2 will also require you to assign multiple policies (one per auth backend). I suggest you go with option 1.
The easiest way to acheive what you want (even if it not that easy) is to provision entities before they log in, and associate metadata to it.
Say you add the metadata kv-user=u3 to the entity that represents the user named u3, Then use {{ identity.entity.metadata.kv-user }} in your policy file.

JBPM 7: How to get login user information

I would like to get login user (username, roles ...) when start new process via KieSession.
Any one can help?
UserGroupCallback is the kie API entrypoint that it is responsible for verifying whether a user or group exists and for collecting groups for a specific user.
Notice that default UserGroupCallback is based on the security context, therefore it can only retrieve information about authenticated user.
You can see different custom implementations here:
https://github.com/kiegroup/jbpm/tree/master/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/identity
And this is the property for configuring a custom one: org.jbpm.ht.custom.callback

RESTful API Design based on the RBAC model

The problem to face lies in the design of a RESTful API that can manage requests from multiple roles in an RBAC-based solution.
Currently we have different resources that can be accessed from different users, which can have one or more roles grouped according to their privileges.
The API we're trying to define must be as clear as possible to the client but without the overhead of adding additional metadata to the URL that could damage and even conflict with the REST practices and definitions. Therefore, we must avoid at all costs include information about the roles inside the URL. The plan is to use JWT tokens that carry in their payloads the info needed to know which permissions has the user making the request.
Having raised our current situation, let's provide an example and state the problem to solve:
Suppose we have * financiers * and * providers * as users with some roles who both want to access ** attentions ** (our resource). Should we add before the resource ** attentions ** information about the * user * whose trying to access the resource?
The endpoints in that case should be defined (as an example) as:
https://example.com/api/v1/financiers/:id/attentions
https://example.com/api/v1/providers/:id/attentions
This way we're attempting to inform the respective controllers that we want the ** attentions ** for that specific role / user which are, in some way, a sub-resource of them.
On the other hand, we could simply implement a much simpler endpoint as follows:
https://example.com/api/v1/attentions
The logic about which attentions return from the database should be now implemented in an unique method that must handle this two roles (and potentially new ones that could come up in the following features). All the information needed must be obtained from the payload from the token, exposing a much more generic API and freeing the web client from the responsibility of which endpoint call depending on the role.
I want to highlight that the attentions are managed in a Microservices Architecture and, hence, the logic to retrieve them is gathered in a single service. The cost of the API Gateway to route the two (and potentially more) of the endpoints from the first solution is a variable not to discard in our specific situation.
Having exposed our current situation:
Which we'll be the best approach to handle this issue?
Is there another alternative not contemplated that could ease the role management and provide a clean API to expose to the client?
In the second solution, is correct to return only the attentions accessible to that specific user based on the roles that it has? Isn't it counterintuitive to access an endpoint and only get some of the resources from that collection (and not all) based on its role?
I hope that someone could clarify the approach we're taking as there are little and none literature that I've found regarding this issue.
There there are multiple solutions for such kind of filtration, and developer have to select one depending on given situation.
As per my experience I can list following.
Structure
When data can't be accessed directly and developer has to use a relation (i.e a table JOIN). In that case URL have to include both the main and sub entities. Before going with this approach a good check is to ask, if the same URL can be used with POST ?
Example
If we have to fetch list of roles assigned to a specific user or want to assign additional roles then we can use
GET users/:uid/roles
POST users/:uid/roles
Security
With Multi-tenant systems where each user can have his/her private resources, i.e other users are prohibited from accessing those resources. Developer should save tenancy information and to filter the resources according to current authentication, without bothering client or requiring any additional info in URL
Example
Phone album of the user
GET photos
POST photos
Search
If it is not security or structure related but client still want to filter the result set depending on his scenario. then developer should use query-string for the filtration.
Example
Client have to fetch messages from his/her inbox or outbox or want messages which are not yet read. or he/she want to search his/her inbox
GET messages?folder=inbox
GET messages?folder=inbox&status=unread
GET messages?search=nasir

Allowing a user to update their own profile using the REST API

I have been experimenting with the REST API using my logged in user account's token to then make PUT requests on my user record to update some custom attributes.
In order to get to this work I had to grant my user account the manage-users role in Keycloak, prior to this I was getting forbidden responses back.
I can now make the PUT request successfully, and after logging out and logging back in I can see the updated attributes I set in my PUT request.
But I have now allowed my user to be able to manage all users in my realm, which I dont want to allow.
Instead I only want to be able to update my own account details.
I know the user can view their own profile and make changes on the Keycloak provided screens. But for certain custom attributes I want to be able to do this from the client side application they are logged in to, so using the REST API but not granting them a role that could allow them to update other users details.
Is this possible?
According to the User section Keycloak's Admin REST API, this is not possible.
One solution would be for your client app to send the update request to a backend. The backend will verify that the update request is legit (aka the JWT is verified and the update does apply to the user requesting the change).
Another solution would be to theme the User Account Service's screens to add input fields for your custom attributes, as the documentation says that:
This screen can be extended to allow the user to manage additional attributes. See the Server Developer Guide for more details.
The second option seems the more secure. I hope that helps.
This seems to be possible with the Account Management API.
Unfortunately, I didn't find any official documentation about that. However, there's an example in Keycloak that demonstrates how to do it.