Use token's username in policy path - hashicorp-vault

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.

Related

Keycloak: mapping user information from external IDP. How do I know attribute names?

I have 2 Keycloak instances:
KC1 which is the main Keycloak for my app
KC2 which acts as an IDP (linked to KC1 via SAML protocol)
I'm trying to retrieve users info (email, name and roles, mainly) in KC1 whenever a SSO user (from KC2) connects to my app. As far as I understand this should be done via IDP mappers.
I tried creating multiple ones with the "Attribute Importer" type with no success. The main problem is that attribute name fields are just textboxes. I don't know where to look to get the correct value I should enter here. For instance for email I tried multiple things like "email", "emailAddress", "mail", etc.. (with all possible cases, i.e. all uppercase, all lowercase, camelcase, etc.) but this is just guess work.
Is there a table somewhere telling what we should enter here? Or at least some way to see what is being sent in the claims (everything is very auto-magic so it's hard to know what's going on under the hood).
The documentation ( https://www.keycloak.org/docs/latest/server_admin/index.html#_mappers ) mentions that you can put the log level to debug to see the claims. Couldn't see them personally, so not sure about that.
Edit : found the problem for basic info (I had to create client scopes with the correct protocol, in my case SAML, and then bind it in the client on the KC2 side. Then use the SAML attribute name defined in the client scope mapper).
However, I still struggle for the roles. Do I have to create them on the KC1 side as well?
Edit 2 : Solved. For future reference, the roles can be found in the access token (not the ID token like basic user info), but they have to be mapped in KC1 to be visible there.
However, I still struggle for the roles. Do I have to create them on
the KC1 side as well?
You can't simply import the roles from KC2 directly to KC1. Instead, you have to create the roles that you want in KC1, and in the appropriate IDP configuration section (of KC1) create a External Role to Role Mapper:
Where you map the role that the user has on the external IDP (i.e., KC2) to the one that the user should have in the KC1. Do that for every role that you want to map.
For SAML IdP integrations you can try the same idea but using the Advance Attribute to Role mapper:

What is the best approach to stop your platform's users to "sniff" the frontend requests to backend and modify them?

So I have a platform that works like this: Users can create accounts by logging in with their Google (I USE AUTH0) and then they can create "Projects" which contain lots of other unimportant stuff regarding my current problem (like todo lists, ability to upload files etc; they can also Edit the project by changing some of it's attributes like name, description, theme and so on). There is a home page where everyone can see each other's projects and access them (but not upload files, change the tasks in the to do lists; this is possible only by the person that owns it).
By using a tool like Burp, people can see the request made from frontend to backend, for example when accessing one of the projects, and modify it on the fly.
This is what it looks like inside Burp when they access one of the projects:
As you can see there is a Get request to /projects/idOfTheProject; they can replace the GET with DELETE for example and they will successfully delete it; they can also see what is sent to the backend when a project is edited (name changed, description, thumbnail picture etc) and change anything they want about it.
How should I prevent this?
What I've looked at so far:
a. JWT - Probably the best fitting for my situation, but required the most work to be done (as I already have my platform almost finished with no such a security measure implemented yet, so I may need to rewrite a lot of things in both backend and frontend)
b. Sending the user's id that initiated the action as well to the backend and verify if it has the necessary privileges - the worst solution as users can access each other's profile and see the id, then just change another field in the request's JSON
c. Have a sort of token for each user and send that instead of the user's id - in this way somebody can't get your token by just looking at the communication between frontend and backend (only if it is using YOUR account). That token should be taken maybe somewhere from the auth0 when they create their account? If they provide something like that; or I can just create it myself and store it alongside the other user variables. You would still see the requests in plain text but even if you modified something you would still have to "guess" the owner's token, which will be impossible.
For frontend I use NextJS and for backend Flask.
Thank you in advance!
The TL;DR is that you don’t. A determined user will always be able to see what requests are being sent out by the code running on their computer and over their network. What you are describing when asking how to prevent people from “sniffing” these requests is security through obscurity, which isn’t actually secure at all.
What you should do instead is have an authorization system on your backend which will check if the current user can perform a given action on a given resource. For example, verifying that a user is an administrator before allowing them to delete a blog post, or making sure that the current user is on the same account as another user before allowing the current user to see details about the other user.

Keycloak - Resource based Role & scope base auth

i have a scenario where i want to restrict the user in keycloak
i have user
user can have access to multiple accounts
in multiple accounts, use can be Admin or agent (reader)
user
|
|
|-------account-1
| |
| |-------admin
|-------account-2
| |
| |-------agent
How can we map this in Keycloak with Policy, Permission, and role?
any reference document any example really helpful
also based from : Resources, scopes, permissions and policies in keycloak
From the answer of Andy, i have created one resource Account and role admin & agent.
created same policies as in example.
i am looking forward to add scopes (auth scope) and roles to JWT token how to map that part so that API gateway or service can verify further.
#changa, I've rewritten my answer based on our discussion. Hope this helps!
Let me first clarify some key areas before I answer. My main focus on the answer that you've linked was really on how to play around the Evaluate tool and I didn't really dive too deeply into some of the concepts - so let's do that :)
In Keycloak, you'll encounter Client and Authorization Scopes. For a formal definition of these terms please check out the Core Concepts and Terms in the Server Administration Guide, but simply put:
Client Scopes are scopes which are granted to clients when they are requested via the scope parameter (once the resource owner permits it). Note that there's also the concept of Default Client Scope but I've chosen to keep things simple. Furthermore, you can leverage protocol and role scope mappers to tailor what claims and assertions are present in the access token.
Authorization Scopes on the other hand are granted to clients after successful evaluation of the policies against a protected resource. These scopes are not granted to clients based on user consent.
The key differences between the two is really when and how a client obtains these scopes. To help you visualize all of this, here's a scenario:
A renowned martial artist called Bob authenticates via Keycloak
Bob get presented with a consent screen where he is asked to share his name, his fighting style and his age.
Bob chooses to give access to his name and fighting style but he declines to share his age.
When we inspect the token now, we would see the following (completely made up) entries for the scope attribute of the access token: name and fighting_style.
Additionally, let's assume that we've set up a couple of protocol mappers (e.g. User Attribute Mapper Type - there are a ton) to display the values for full name and fighting style via the following token claims: fighter_name and martial_arts when the two Client Scopes above are present in the access token. In addition to two previously mentioned scopes, we would also see something like fighter_name: Robert Richards and martial_arts: Freestyle Karate when examining the access token.
Side Note: Given the length of this answer, I've decided to skip this topic but please check out this awesome video at around the 7 minute mark along with the associated GitHub Project for more information. The README is pretty good.
Additionally, let's assume that Bob is mapped to a realm role called Contestant and a client role of Fighter and we did place any restrictions in Keycloak when it comes to sharing this info. So in addition to all the things mentioned above, we would see that information inside the token as well.
Needless to say, this is an oversimplification on my part as I'm simply setting up the stage for demo. purposes and there's much more information inside the access token.
Bob doesn't like how the tournament bracket is laid out as he's eager to fight the world champ as soon as possible, so he attempts to change his placement by sending a request against tournament/tekken6/bracket/{id}. This resource is associated with the scope bracket:modify. Additionally, there is a permission which associates the resource in question with a role based policy named Referee Role Required. If Bob were a Referee then he would be granted the bracket:modify scope but since he isn't, then he is denied that scope.
I've barely touched the surface when it comes to the inner workings of the Authorization process in Keycloak. For more information, check out this practical guide. You can do some pretty cool stuff with UMA.
Ok, so that's enough theory. Let's set up our environment to demo all of this. I'm using the following:
A realm called demo
A client called my-demo-client
A client scope called client_roles
2 users - paul and law
Two realms level roles - Admin and Reader
Two client level roles - demo-admin and demo-reader
Please note that I will using Keycloak 12.0.4 and I will skip almost all the basic setup instructions. I will only share the relevant bits. If you're not sure how to set this all up, please check out the Getting Started Guide or this answer. The answer contains steps for version 8 but the differences are very minor as far as I could tell.
Associating Users And Roles
In order to associate paul with the Admin, Reader, bank-admin and bank-reader roles, please do the following:
Click on Users > View all users > Click on the ID value for paul > Click on Role Mappings > Under Realm Roles move Admin and Reader under Assigned Roles > Select my-demo-client under the Client Roles select box and move demo-admin and demo-reader under Assigned Roles like so
As for law we'll just associate him with Reader and bank-reader.
Associating a client scope with a client
Create a Client Scope by:
Clicking on the Client Scopes link on the left > Click on Create > Enter custom-client-scope for the Name field and Hit Save. It should look like this
Click on Clients on the left > Select the my-demo-client > Click on the Client Scopes tab at the top > and let's just move it to Assigned Default Client Scopes for convenience.
Inspecting the Access Token
We can easily generate an access token for our setup via Keycloak to see what it looks like. In order to do so:
Click on Evaluate tab under Client Scopes.
Select paul as the user
Click on the blue Evaluate button
Click on Generated Access Token. While inspecting the token, look for:
resource_access to see client level roles associated with paul
realm_access to see paul's realm level roles
scope to see the Client Scope that we created called custom-client-scope
If you generate a token for law, you would see less roles when compared to paul.
Obtaining a Scope After Policy Evaluation
Continuing with our setup:
I've created an account/{id} resource with two Authorization Scopes called account:read and account:modify like so
Additionally, I've created two role based policies called Only Reader Role Policy and Only Admin Role Policy where the former requires the Reader realm role while the latter requires the Admin realm role. Here's an example for reference.
Note that you can further enhance that policy at the client level if you wish but to keep things simple, I chose not to do so.
Furthermore, I've created two scoped based permissions called Read Account Scope Permission and Modify Account Scope Permission.
The Read Account Scope Permission will grant the account:read Authorization Scope if the user is either an Admin or a Reader. One key thing to notice here is the the Decision Strategy has to be set to Affirmative in order to achieve this behavior.
Modify Account Permission on the other hand grants the account:modify Authorization Scope to users with the Admin role.
Now, if you choose the evaluate the user paul (remember he is both Admin and Reader) against the Account Resource, he will be granted both the account:read and account:modify Authorization Scopes. Let's see if this true. Here's our Evaluate screen and notice that I did not associate any roles with paul since this was already done via the Users > Role Mappings tab
And here are the results of that evaluation as predicted
Here is the evaluation result for law. Since he's not an Admin he'll be denied the account:modify scope but he'll be granted the account:read scope.
And finally, we can further confirm this by click on Show Authorization Data which shows the permissions inside the access token for law
Hopefully this helps you see where each piece of the puzzle fits in your architecture. Cheers!

Extend user access token in Keycloak with external data

We use the Keycloak service as SSO solution and provide the resulting JWT to different microservices and that works very well.
But now we have the problem that the JWT must be extended with data from an external resource when the user tries to login.
More tangible, a user has access to different markets with an unique ID as identifier, but we didn't see the management which user have access to which market inside the Keycloak service.
What could be the best solution for this problem?
After reading the docs an custom User Storage SPI is an answer, but I think that is a little bit to much..
As information we use Keycloak 3.1.0 as a standalone service with an postgres DB
The way you add extra data/information to your keycloak JWT token payloads, comes by means of adding "client-scopes" configured with the proper protocol mappers within them, that allows you to add any amount of custom extra information to your Id-token and access-token.
One example of this, would be having extra variables in your users, and then in the protocol mappers within the (newly-created) "client-scope", you can add a protocol-mappers of type "User-Attribute", so that your specific user variable will appear in your token the way you configured on your "protocol-mapper". There are many types of "protocol mappers" that'll allow you to map diverse type information to your tokens (is not just for mapping user variables).
This was addressed on this question before:
Keycloak User Storage SPI Implementation
I'm copying here the part which is relevant to you:
Origianl question was:
[How to]"Retrieve some attributes from external datasource, map it to keycloak's id and access token. Need to retrieve users unique id and add it as subject id in the jwt. That's the id, rest of the services can use to retrieve the id, when this token is passed to other services."
[Answer:]
For this, the best you can do is:
Add those user's unique data as users attributes (see them on the Admin console)
Create a "Client scope" on Keycloak, with a corresponding mapper of type "user property" to map each of those values you'd like to add (from your user data) to your Id-token and access-token. You also need to tie your client with your just created "client scope". This may sound a little bit confusing, but this video is great material and I bilieve it'll help you alot: https://www.youtube.com/watch?v=ZxpY_zZ52kU (arround min 6:30 you'll see how to add extra user info to your tokens)

REST, caching, and authorizing with multiple user roles

We have a multi-tenant system with multiple different levels of access--sometimes even for the same user as they switch between multiple roles. We're beginning a discussion on moving over to a RESTful implementation of things. I'm just starting to get my feet wet with the whole REST thing.
So how do I go about limiting access to the correct records when they access a resource, particularly when taking caching into consideration? If user A access example.com/employees they would receive a different response than user B; user A may even receive a different response as he switches to a different role. To help facilitate caching, should the id of the role be somehow incorporated into the uri? Maybe something like example.com/employees/123 (which violates the rules of REST), or as some sort of subordinate resource like example.com/employees/role/123 (which seems silly, since role/### is going to be appended to URIs all over the place). I can help but think I'm missing something here.
edited to mention multi-tenancy
Having the user credentials act as an out of band resource identifier (ie. presenting different views on the same URL to different roles) will turn nasty down the road. Users and applications exchange URLs between them, things turn sour when that happens and the URL simply returns different content for different credentials.
I would say that each role has a different view of the world, therefore each role should access a different path to the service:
admins connect to example.com/admin/employees
users connect to example.com/users/employees
role foo probably connects to example.com/foo/employees
This way you separate the 'this role sees the world as such and such' part from the 'this view of the world is accessible to role foo' part. An admin can connect to example.com/users/employees and verify how an ordinary user sees the world, w/o the admin having to impersonate a lower privileged alias first.
You can also use the DNS part for same purpose: admin.example.com/employees vs. users.example.com/employees. This is specially viable for a related scenario, when the 'role' is not a security role but a multi-tenant namespace (ie. each service provisioned account gets its own 'view' of the service).