How to search keycloak users by employeeNumber or by custom attributes? - keycloak

I wanted to search keycloak user using employeeNumber. I tried checking keycloak documentation but didn't find any API which will search based on employeeNumber/custom attributes. I m using below API to search the users with admin access.
http://localhost:8080/auth/admin/realms/Demo-Realm/users/?firstName=akshay
also tried with
http://localhost:8080/auth/admin/realms/Demo-Realm/users/?search=akshay

Although not mentioned on the release notes it is possible after Keycloak version 15.1.0 (as pointed out by #Darko) to search users by custom attributes, introduced with this commit. As one can now see on the GET /{realm}/users endpoint of the Keycloak Admin Rest API:
So in your case you would call that endpoint with the query parameter q=employeeNumber, for instances with curl:
curl 'https://${KEYCLOAL_HOST}/auth/admin/realms/${REALM_NAME}/users?q=employeeNumber:444555'
Bear in mind that the /auth path was removed starting with Keycloak 17 Quarkus distribution. So you might need to remove the /auth, namely:
curl 'https://${KEYCLOAL_HOST}/admin/realms/${REALM_NAME}/users?q=employeeNumber:444555'
Keycloak version before 15.1.0
For those with Keycloak version before 15.1.0, out-of-the-box you can use the Keycloak Admin API endpoint:
GET /{realm}/users
one can read that :
Get users Returns a list of users, filtered according to query
parameters
those (optional) query parameters being:
briefRepresentation (boolean);
email (string);
first (string);
firstName (string);
lastName (string);
max (Maximum results size (defaults to 100)) (integer);
search (A String contained in username, first or last name, or email);
username (string).
As you can see you cannot search for custom attributes. A not so great solution is to get all the users (max=-1), and filter afterwards by the custom attribute.
The other option is to extend Keycloak functionality by adding your own custom Service Provider Interfaces (SPI) and adding your custom endpoint. There you can take advantage of the searchForUserByUserAttribute method from the UserQueryProvider interface.

Related

KrakenD Config custom dynamic role based on URL

I want to add one URL configuration which would be dynamic. For eg.
URL: /api/v1/{did}
and my jwt token would contain user-id, roles where role = did (same as in URL).
There are various URL like this with different did but same endpoint and krakend should validate that one user has access to that specific URL(did), so I have roles created in keycloak as did (roles = did).
I want to specify roles in krakend json file like roles : [{did}].
Is there any way to achieve this?
That should be possible using a CEL rule (Common Expression Language). With CEL you can set an expression that makes sure that the passed {did} parameter equals to the content of the JWT attribute containing the role.
The following page has several examples that might help you: https://www.krakend.io/docs/endpoints/common-expression-language-cel/
For the testing I would suggest using the devopsfaith/krakend:watch command that hots reload the configuration on every change.

Is group name case sensitive in SAML payload (in Palantir Foundry context)?

During a SAML login via multipass, a list of groups is provided in the payload in <saml:Attribute Name="https://schemas.xmlsoap.org/claims/Group" ...>
Are these groups matched case-sensitively?
i.e.: Will a group that was provided as "AbcDef" earlier, but is provided as "abcdef" later be treated as the same group or not?
You can now modify your SAML configuration in a self-serve way via Foundry Control Panel.
For user attributes: please reach out through your internal support channel if you'd like to make user attributes case-sensitive - this option isn't available in the UI.
For user groups: case sensitivity isn't currently supported for user groups. You need to enable the “Import user groups from the identity provider” option to populate a user's groups via SAML.
This is a multipass configuration service level configuration. You will need access to the gemini or the infrastructure that configures the stack itself to change it. If you don't please reach out through your internal support channels.
What you want is to add caseInsensitive to the type in your atributes. i.e.:
users:
attributes:
'multipass:email:primary':
- Email
'multipass:family-name':
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'
'multipass:given-name':
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'
id:
fields:
- NameID
type: caseInsensitive
username:
- NameID

Store multiple credentials in Keycloak

Is it possible to store multiple credentials for a given user in Keycloak?
They don't need to be all active/enabled at the same time. The use case for us is rather that we want to store new credentials in advance but don't want to have them active yet. They should be activated/enabled at a later time after some manual user verification.
The Keycloak REST API documentation states that UserRepresentation indeed comprises an array of CredentialRepresentation but in my few tests the GET call wouldn't even return a credentials attribute.
I would say that's impossible to have more credentials for a user.
But you can always implement your own user storage SPI that implements interface CredentialInputValidator, where you can check for the valid password.
Let's say in your DB, you have 2 colums for passwords: pas_col1 and pas_col2, and 1 more column as flag, which tells what column is used for user authentication, so in isValid(RealmModel realm, UserModel user, CredentialInput input) method you can check for your conditions.
Link to SPI: https://www.keycloak.org/docs/3.4/server_development/index.html#_user-storage-spi

Algolia Secured API Keys: attributesToRetrieve parameter

with Algolia is it possible to restrict the attributes to retrieve when building a Secured API Key?
By defualt, when searching, attributesToRetrieve parameter may be used, however I am not sure if it's possible to get used during the generation of a Secured API key.
The reason of this is because we want to restrict certain attributes of a document to specific users.
Unfortunately, it's not possible to restrict the attributes to retrieve using the attributesToRetrieve query parameter while generating the Secured API key -> the user will still be able to override it at query time.
The only thing you can do is configure the unretrievableAttributes setting in your index settings. This setting forces some attributes to be non-retrievable whatever the attributeTo{Retrieve,Highlight,Snippet} query parameter you set.

What is the best way to design REST URI for nested resources

Say there are users having multiple authorizations having multiple permissions.
Retrieving all authorizations for the specified user (without permissions) could be:
GET users/{id}/authorizations
The "normal" case is to not embed permissions with authorizations for performance reason.
There are cases when authorizations must be returned with their respective permissions for that user.
Suggested solutions are:
GET users/{id}/authorizations/permissions // does not seem clear
GET users/{id}/authorizations?permissions=true // with query string
GET users/{id}/authorizationswithpermissions // new resource
Now what is the best way to design the REST URI in that case?
Your ideas
There are cases when authorizations must be returned with their respective permissions for that user.
GET users/{id}/authorizations/permissions
It is not a good idea to nest collection resource like this. Does it mean "give me all permissions of all authorizations of user id"? This is unclear. Don't do this.
GET users/{id}/authorizations?permissions=true
A query is normally used to query, search, or filter on a collection resource. This URL woud return all authorizations for user id for which permissions is true. But what does that man? This is unclear. Don't do this.
GET users/{id}/authorizationswithpermissions
Authorizations are authorizations. Their representation should not depend on the URI. Don't do this.
Content Negotiation
The solution to your problem is to use content negotiation. You only use one URL:
GET users/{id}/authorizations
This means: Give me a list of all authorizations of user id.
Now if you want to get this list without permissions, you could use the HTTP header
Accepts: application/vnd.mycompany.authorizations+xml
Let's digest this.
application: the first part of the normal MIME type application/xml
vnd: a prefix to define your own type
mycompany.authorizations: your type
xml: the second part of application/xml
Now if you want to get this list with permissions, you could use the HTTP header
Accepts: application/vnd.mycompany.authorizations.permissions+xml
Note that me now use vnd.mycompany.authorizations.permissions. The server should return the authorizatons including the permissions. Only the representations are different, not the resources.
Personnally I can't find any problem with both two last suggestions:
GET users/{id}/authorizations?permissions=true // with query string
GET users/{id}/authorizationswithpermissions // new resource
Except I would change them as follow to be more relevant:
GET users/{id}/authorizations?withPermissions=true // with query string
GET users/{id}/authorizationsANDpermissions // new resource
The first one seems to be quite confusing but your RESTful entities should be documented whatever notation you will opt for.