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

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:

Related

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.

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!

Capture IDP User attributes in SAP cloud foundry app via SDK UserAccesor API

I wanted to capture user attributes coming from SAP IDP(Identity & Authentication tenant service like department,salutation ,company etc ,via UserAccessor SDK api,but although those attributes are set and has value in IDP user and all the integration with IDP and sub account is in place post authentication ,user attributes object is empty ,i am only able to retrieve specific attributes like first names ,last name,email address ,user groups etc via JWT and UserAccessor api ,but no luck with other attributes ,in IDP i have mentioned these attributes as well under assertion attributes in SAP Identity authentication tenant .
Please guide and help in this matter .
Thanks Siddharth
Update: As we have now identified the problem, I will update my answer to reflect that. The original answer below is outdated:
Okay so the problem is that you haven't mapped any additional user attributes from your Identity Provider (IdP) to your JWT. As far as I'm aware there are three things you will need to do:
You need to create attributes in your xs-security.json (the file you used to configure your XSUAA service instance). This documentation should explain how to do that.
You need to configure which attributes are exposed by your IdP (in your case the SAP Identity & Authentication service. This documentation looks like a good place to start looking).
You need to map the attributes exposed by your IdP to the attributes defined in your xs-security.json. You will probably need to reconfigure (i.e. delete, recreate and rebind) your XSUAA service instance with the updated config, before you can do this step. Then, navigate to your application in the Cloud Platform Cockpit, from the left toolbar click "Security > Roles" and create your mapping.
Let me know if this works for you!
Original Answer:
As far as I'm aware the default IdP does not support SAML. Without SAML, I'm not sure whether you can propagate any attributes from your IdP into the JWT.
Please also check out this discussion for more information.

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)

How to scope and persist claims to different clients in IdentityServer 3?

I'm new to IdentityServer3 and have multiple MVC clients where users have claims which potentially could conflict and give undesired authorization.
Here is an example with two clients able to send emails and notifications to the users. A user might have access to both applications but should only be able to recieve notifications in Application A. How can we prevent the user from recieving notifications in Application B?
Application A
Claim Type: ApplicationFunctionality Claim Value:
RecieveNotifications
Claim Type: ApplicationFunctionality Claim Value: RecieveEmails
Application B
Claim Type: ApplicationFunctionality Claim Value: RecieveEmails
Would a resonable solution be to implement somekind of logic in a class using the IUserService interface?
Would it be correct to use claims in the way I described above across multiple clients, where we sometimes reuse claims for cross-client functionality. I guess it would require me to namespace the claims (perhaps using the requested scope name the client sends to IdentityServer) in order to distinguish claims for different clients and prevent unauthorized access between the clients.
Here is an example of user claim types/claim values:
Name: John Doe
Email: john.doe#acme.com
PreferedLanguages: English,Swedish,Spanish
ApplicationFunctionality: ClientA.RecieveEmails
ApplicationFunctionality: ClientB.RecieveEmails
ApplicationFunctionality: ClientA.RecieveNotifications
ApplicationFunctionality: ClientB.RecieveNotifications
ApplicationFunctionality: ClientA.ViewBackorders
ApplicationFunctionality: ClientA.DeleteBackorder
ApplicationFunctionality: ClientB.SearchProductInformation
CompanyID: 1145
CompanyID: 6785
CompanyName: Acme Inc
ApplicationLicense: ClientA.PayingNormalUser
ApplicationLicense: ClientB.FreeUser
A user from Company Acme Inc have several CompanyID's which is used when filtering data we request from webservices\databases in the data layer. The user have access to multiple applications where he/she could have different levels of functionality depending on what license they have bought in the applications. Some functionality exist in multiple clients but that doesn't mean the user are authorized to same functionality in all clients he/she have access to.
I would appreciate some guidelines about claims, or perhaps point me to some good resources about the subject. I have read that claims primary is used for identity related information (email, name, department, favorite color, shoe size etc), but if no role\permissions style claims should be used with claims then how should information about what a user is authorized to do in the clients be persisted and how should data be filtered in webservices/databases (resource providers) so the user only sees data he/she are authorized to see?
My first thoughts where that the id_token and access token would be convenient to use since they are issued by the STS (IdentityServer) and then later persisted in cookies. The STS would first be required to perform lookup of user account in Active Directory which contains user identity related information together with an lookup (using the username of the Active Directory user account) in custom database containing information about role\permissions and claims of the user.
How should I persist the roles/permissions and claims of a user if not using cookie persisted tokens provided by IdentityServer?
Clients (applications) and users can have their own set of claims. It looks like you want to have applications which have access to different resources. This is where you should use scopes. Basically define two scopes which define action on that resource (this is one common way of doing it) ie one for 'reading' emails and one for 'writing' emails (eg emails.read and emails.write) subsequently the other scopes can be backorders.read and backorders.delete. It's just good practice to have consistent naming here.
Ok now since weve defined those two scopes, you can now define two clients, one which has only the emails.read scope and the other one has both the read and write scopes. All this means is that one client has access to more resources than the other.
All the user identity claims should stick to the user itself. Application/client specific should never be associated with the user. Name,Email,ApplicationLicense, and PreferredLanguages are all valid claims for the user because they describe the user itself and what can be asserted about them.
For "complex" authorization you may want to look at this sample for some ideas on how to set up compound security policies or authorization.
It sounds like you want to expose a different value to different clients for the same claim. This seems like a logical thing to want to do, especially if you are integrating with clients that are not within your control and thus cannot dictate to them what to expect in each claim, or what scopes to request. A simple example might be the "roles" claim - you may wish to send different values depending on the app that's making the request. If you're joining someone else's enterprise, perhaps with multiple OpenID Connect Providers, you don't always have a choice over the scopes or claim names.
I feel that Nat Sakimura eludes to this in the OpenID Connect FAQ video, https://www.youtube.com/watch?v=Kb56GzQ2pSk (1 minute 40s), the idea that an entity might want to expose a different identity to different clients.
In terms of implementation, we've added a table with [identityId, clientId, attributeName, attributeValue] to allow us to store the same identity attribute for different clients. In our case, these identity attributes become claims in the outgoing JWT. As most attributes about a user are global (i.e. not client specific), we treat the data in this table as overrides to a base set, which saves duplicating the same data for each client unnecessarily. The iUserService.GetProfileDataAsync() method has access to the Client, so can tailor its response depending on the consumer of the data.