How to Register Keycloak Password Hash Service Provider SPI - keycloak

Background
I need to migrate a user database for a bespoke app into Keycloak. I have created a keycloak-add-user.json file that imports the users successfully. Migrated user passwords are hashed in the original system, however I've implemented a Keycloak Password Hash SPI service class that uses the existing algorithm to validate the hash and salt value of a migrated user. The Hash SPI class implements PasswordHashProviderFactory and PasswordHashProvider from the Keycloak SPI and is based on `Pbkdf2PasswordHashProvider'.
public class MyPasswordHashProvider implements PasswordHashProviderFactory, PasswordHashProvider {
public static final String ID = "XXXX";
The issue
When a migrated user tries to authenticate with keycloak an error is logged by org.keycloak.hash.PasswordHashManager
Could not find hash provider XXXX for password
My jar contains an initialisation file META-INF/services/org.keycloak.models.PasswordHashProviderFactory with a single line containing the full classname of the HashProvider implementation.
my.folder.MyPasswordHashProvider
This was based on the Federation SPI doco, but documentation for the Keycloak Password Hash SPI seems to be non-existent. What am I missing, or what do I need to do to register and use my Hash Provider with Keycloak?

In the newer versions of keycloak (I checked 2.5.4), the file needs to be META-INF/services/org.keycloak.credential.hash.PasswordHashProviderFactory

This turned out to be a copy/paste error - the initialisation file had the wrong package name 'model' rather than 'hash' and therefore didn't match the PasswordHashProviderFactory.
In the provider jar the initialisation file needs to be named:
META-INF/services/org.keycloak.credential.hash.PasswordHashProviderFactory
and contain a single line with the full name of the implementation factory class - in this case:
my.folder.MyPasswordHashProvider

Related

Is there an elegant way to clone a Keycloak realm with all its configurations (clients and roles) for a multitenant application?

I'm building a multitenant application and I'm using Keycloak for authentication and authorization.
Foreach each tenant, the idea is to have a dedicated Keycloak realm. Each tenant will have exactly the same roles and clients.
I have tried to export one existing realm, use it as template and import it for new tenant. Problem: I'm facing database constraint violation due to internal id.
Question: Is there an elegant way to achieve this, having a template to create a new realm ?
Be sure that the feature for uploading script is enabled. For a deployment with a docker-compose just add this:
command: -Dkeycloak.profile.feature.upload_scripts=enabled
Export your realm (the one to be used as model)
Remove all line containing "id:" and "_id:"
Search and replace template realm name by the new realm name
In Keycloak UI admin console, Add new realm, provide the file and that is all.
You can use the cleaned exported file as template.
Can't comment due to rep,
but I'd like to add to #Youssouf Maiga's answer,
that you should also modify any fields that contain values under "authenticationFlowBindingOverrides":
Replace any entries that have values assigned under "direct_grant" or "browser"
i.e
"authenticationFlowBindingOverrides": {
"direct_grant": "f5d1wb45e-27eb-4466-937439-9cc8a615ad65e",
"browser": "5b23141a1c-7af8d-410e-a9b451f-0eec12039c72e9"
},
replaced with
"authenticationFlowBindingOverrides": {},
I tried cloning my realm based on this and got an error saying:
"Unable to resolve auth flow binding override for: direct_grant" when importing the modified realm export.
Keycloak version 16.1.1
What you could do is configure everything using the Keycloak Terraform provider. That way you only have to define the configuration once, in code, and then apply it using Terraform. See for the documentation: https://registry.terraform.io/providers/mrparkers/keycloak/latest/docs
An advantage of this is that you can put your code in an SCM tool (e.g. git), so you can track your changes, and go back to a previous version if necessary.

Keys created from one HSM client are not available for use in another client

I am building a solution to store keys and encrypt\decrypt data using an HSM. I am using a network HSM manufactured by Thales. The thing I have noticed is that a key generated in client machine 1 is inaccessible in client machine 2. The key can only be used to encrypt\decrypt data in client machine 1. Is there any thing that needs to be changed in my implementation or is there something to be changed in net-HSM configuration to enable this. I am using PKCS11Iterop library for all the key management operations.
I am using token based OCS protection.
I suppose your client machine 1 has a new file in kmdata/local directory associated to the new key generated.
But your client machine 2 has not this file in his kmdata/local directory.
You have to find a way to share the kmdata/local directory, for instance, using NFS.

Class loading for jaas custom login modules in WebSphere Liberty

UPDATE: Some context on the problem below. My goal is to handle requests for users where they supply a Kafka topic with each request. I use Message Hub deployed on Bluemix as Kafka provider. The requests will pass the broker URL, topic name, username, password and API key. Message Hub on Bluemix requires JAAS authentication and provides a login module with different LoginModule implementations. Some are based on CallbackHandlers, others on CredentialProviders.
I picked the one implemented in com.ibm.messagehub.login.MultiUserLoginModule. With that module I should only have to supply a custom credential provider like:
KafkaClient {
com.ibm.messagehub.login.MultiUserLoginModule required
credentialProvider="myApp.CustomCredentialProvider";
};
The challenges are in the class loader and how the CustomCredentialProvider can get the username/password from the request passed to the MultiUserLoginModule at runtime. What configuration do I have to use to get that working?
DETAILS: I have a web application running in WebSphere Liberty 8.5.5 and want to authenticate with a third-party service. That third-party service implements a JAAS LoginModule with a CredentialProvider. My web app extends the CredentialProvider with a CustomCredentialProvider to pass credentials.
What I don't understand is how the class loading is supposed to work. My server.xml defines:
The web application
<webApplication id="streaming-service" location="streaming-service.war" name="streaming-service"/>
The third-party login module
<jaasLoginModule className="com.ibm.messagehub.login.MultiUserLoginModule" controlFlag="REQUIRED" id="KafkaClient" libraryRef="messageHubLoginLib">
<options credentialProvider="myApp.CustomCredentialProvider" serviceName="kafka"/>
</jaasLoginModule>
The library that implements the third-party login module
<library id="messageHubLoginLib">
<fileset dir="${server.output.dir}" includes="messagehub.login-1.0.0.jar"/>
</library>
The login context
<jaasLoginContextEntry id="KafkaClient" loginModuleRef="KafkaClient" name="KafkaClient"/>
The result of the above configuration is a ClassNotFoundException for my CustomCredentialProvider:
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: myApp.CustomCredentialProvider
at com.ibm.messagehub.login.MultiUserLoginModule$MultiUserCallbackHandler.<clinit>(MultiUserLoginModule.java:80)
How do I have to change my configuration for the third-party JAAS login module to find myApp.CustomCredentialProvider implemented in my streaming-service web app?
Note: I already tried to generate a streaming-service.jar and add it directly to the messageHubLoginLib. That resolves the ClassNotFoundException but the CustomCredentialProvider class is loaded completely outside the context of my running web application and still gives me no access my credentials.
You were nearly there with the separate streaming-service.jar. Here are all the steps that are needed.
Identify the classes (from your app) that need to be visible to the login module.
Put all those classes into your messageHubLoginLib (e.g. in a separate streaming-service.jar)
DELETE those classes from your app.
Configure the app with a class loader child element that references the login module library using a commonLibraryRef attribute:
<webApplication id="streaming-service" location="streaming-service.war" name="streaming-service">
<classloader commonLibraryRef="messageHubLoginLib" />
</webApplication>
Generate a streaming-service.jar and add it directly to the messageHubLoginLib should be the right way to do. In this case, you have a jar file that is share-able between your JAAS login module and Web App.
However, you said "CustomCredentialProvider class is loaded completely outside the context of my running web application and still gives me no access my credentials". It sounds like you trying to store the credential in the CustomCredentialProvider class for uses between the login module and web app.
The CustomCredentialProvider class should be independent between the login module and web app. When request come in and try to access the web app, the server trigger the login module for authentication. If it passed, the access to the web app will be successfully.
I don't see you posted. May be you are missing the following configuration?
<jaasLoginContextEntry id="system.WEB_INBOUND" name="system.WEB_INBOUND" loginModuleRef="KafkaClient,hashtable,certificate,token" />
Can you place the MultiUserLoginModule and CustomCredentialProvider jar file in the ${server.config.dir}/lib/global directory and change the libraryRef point to global directory in your server.xml file as following:
<jaasLoginModule className="com.ibm.messagehub.login.MultiUserLoginModule" controlFlag="REQUIRED" id="KafkaClient" libraryRef="global">
<options credentialProvider="myApp.CustomCredentialProvider" serviceName="kafka"/>
</jaasLoginModule>

Client identifier in jboss httpinvoker (auditing)

I am using httpinvoker in JBoss 4.0.4 (little old) for EJB invocations.
Since there are so many clients that make calls to my server, I want to identify the clients for each call in server.
Is there a way to do this with JBoss httpinvoker?
I could imagine adding a header to identify my client in each HTTP request, but cannot find a way to add a header in httpinvoker.
Auditing builds on a name, and thus on an authentication scheme somehow.
Therefore I suggest using the standard client authentication infrastructure to solve your problem. This works for RMI as well (it's not bound to HTTP), and the user ID is even passed down into your EJBs.
Server
Put the EJB in a security-domain (ejb.jar: META-INF/jboss.xml)
You could use the application-policy other which just the UsersRolesLoginModule (conf/login-config.xml); this is the default policy, it's already configured.
Add users.properties and roles.properties to your ejb.jar file (top level package): These are used by the UsersRolesLoginModule
For each user, add his name and a (dummy) password to users.properties
Client
Create a callback class which implements a javax.security.auth.callback.CallbackHandler: This callback is used, when the authentication needs the user and the password.
Create a javax.security.auth.login.LoginContext; pass the callback handler as the 2nd argument; call login() on the instance of the LoginContext
Connect normally to the EJB server using an InitialContext
Add -Djava.security.auth.login.config=.../jboss-4/client/auth.conf when you start the client
This way a user ID is passed from the client to the EJB (as part of the standard authentication process). Now, in the EJB methods, you can get the user ID by calling getCallerPrincipal() on the SessionContext instance. I have tested this against JBoss 4.2.3
Additional information: JBoss client authentication
Addendum 1:
Using RMI or HTTP, the password is not transported in a secure way. In this case just use a dummy password, this is OK for auditing.
On the other hand, if you use RMI over SSL or HttpInvoker over HTTPS, you could change to a real and secure authentication quickly.
Addendum 2:
I am not sure, if it works without defining roles. Possibly you have to
Add a line in roles.properties for each user: Add a connect role, for example
Add role definitions in ejb-jar.xml as well: security-role-ref for each EJB, and security-role and method-permission in the assembly-descriptor
Update
As there is already a login module, there might be another possibility:
If you have the source code of the login module, you could possibly use another TextCallback to get additional information from the client (in your case a user ID). The information could be used to create a custom Principal. Within the EJB, the result of getCallerPrincipal() could be cast to the custom principal.

BizTalk MSMQ userid and password in a bindings file

I'm setting up a solution to deploy, driven by a batch file so it's reproducible
- I've got a binding file that works but I've now added on my MSMQ adapters
- works on my local machine, but I've found I have to add a userid and password to get it to work on the actual server
- it's in the domain, my virtual dev machine is just workgroup
Is there someway to add the userid and password to the file ?
- seems unlikely as that'd have the password in clear text, but what's the solution
- I sort of think something w.r.t. SSO, but that is an area I've not been near
You can put the userid and password into any BizTalk binding that supports authentication, including MSMQ. For security, the password is not exported, you just get a mask.
The userName and password sections of the binding file are not exported unless they have been configured, so the simplest thing to do is configure a MSMQ send port with userName and password manually and export the bindings - this forces the elements containing userName and the masked password to be generated into the binding file.
What you are looking for in your binding file is the <TransportTypeData> element of your MSMQ send port. This contains all of your adapter config information as encoded data.
Within that element there is a userName and password section. The password will be masked out with asterisks. Put the password for the environment there and import the binding.
The part of the encoded data with username and password will look something like below:
&lt;userName&gt;YourUserName&lt;/userName&
amp;gt;&lt;password&gt;******&lt;/password&gt;
For security reasons, when you export
bindings, BizTalk Server removes the
passwords for the bindings from the
file. After importing the bindings,
you must reconfigure passwords for
send ports and receive locations
before they will function. You
configure passwords in the Transport
Properties dialog box of the BizTalk
Server Administration console for the
send port or receive location. For
instructions, see How to Create a Send
Port. See also How to Create a Receive
Location.
From http://msdn.microsoft.com/en-us/library/aa558708.aspx
If you however open the biding file and scroll down to the line with the properties for the MSMQ Adapter you'll find the empty nodes. All you then have to do is to fill these out and the right values and they will be used the next time you import the binding file.
Of course you'll have to remember to redo this every time you export a new binding ...