11-07-2022 04:48 AM
Hi All,
I'm integrating the alfresco rest API with an external application. using the latest version of Alfresco configured with Keyclok as an identity server with the open-source module provided by @afaust (alfresco-keycloak).
Keycloak has been configured with 2 different realms each one with its user provider and roles and Alfresco has been configured with 2 Authentication subsystems and different Keycloak adapters:
-Dauthentication.chain=keycloak1:keycloak,keycloak2:keycloak -Dsynchronization.import.cron=\"0 0 0/4 ? * * *\" -Dsynchronization.allowDeletions=true"
This configuration works well when logging in through Alfresco Share, chaining across each subsystem until the user logs in successfully.
But the same configuration won't work with the Alfresco public API. When my external application calls an endpoint with a valid Bearer token Alfresco uses just the first of two adapters configured so if my token has been released by the last keycloak realm it always fails and a 401 error is returned.
I can't find any solution to this problem or any documentation about that. I can't understand if the authorization mechanism used to authorize for rest-API doesn't use the same security chain as Alfresco Share.
Does anybody else have the same problem and found a solution to fix it?
Thanks in advance.
Stefano
11-08-2022 07:17 AM
Hi,
The way Alfresco's SSO handling works is a bit different then normal username + password authentication. The latter chains over all subsystems, whereas by design, the SSO handling only works for the first SSO-enabled subsystem. Similarily, the RemoteUserMapper which - dependending on subsystem - can extract user names from headers / handle bearer tokens, is also only called for the first subsystem which provides such a component. This is why the alfresco-keycloak module by default also only handles a Bearer token via the first instance. But I have actually run into this kind of problem in a customer project, albeit not with two Keycloak realms but with a custom-built "magic cookie" authentication subsystem. In my alfresco-utility project - which is a dependency for alfresco-keycloak - I provide a chaining RemoteUserMapper implementation. Unfortunately, I have not included a prepared patch that can simply be enabled (which I really should have), and at this time, it would be necessary to manually apply that via a Spring override context XML file, i.e. in alfresco/extension/authentication-services-override-context.xml (the path I used in the customer's project). Such a context file would only need to contain the following bean:
<!-- default proxy has "first active wins" semantic, we want "first successful wins" --> <bean id="RemoteUserMapper" class="de.acosix.alfresco.utility.repo.subsystems.SubsystemChainingRemoteUserMapper"> <property name="applicationContextManager" ref="Authentication" /> <property name="sourceBeanName" value="remoteUserMapper" /> </bean>
I hope this helps in your case. If it does, please get back to me and ideally also raise a new issue in alfresco-keycloak, so that I have a reminder to include that in documentation as well as provide a pre-bundled patch in future versions.
Note that this patch would onyl fix the "two realms" use case for the Repository-tier (ACS), not Share SSO. Share SSO has not been designed at all to support multiple SSO authentication instances, there are no preparations in alfresco-keycloak to support this, and it would take some significant refactoring effort to achieve this within the Share architecture. So for Share, only username + password authentication with multiple Keycloak realms is supported.
11-08-2022 07:17 AM
Hi,
The way Alfresco's SSO handling works is a bit different then normal username + password authentication. The latter chains over all subsystems, whereas by design, the SSO handling only works for the first SSO-enabled subsystem. Similarily, the RemoteUserMapper which - dependending on subsystem - can extract user names from headers / handle bearer tokens, is also only called for the first subsystem which provides such a component. This is why the alfresco-keycloak module by default also only handles a Bearer token via the first instance. But I have actually run into this kind of problem in a customer project, albeit not with two Keycloak realms but with a custom-built "magic cookie" authentication subsystem. In my alfresco-utility project - which is a dependency for alfresco-keycloak - I provide a chaining RemoteUserMapper implementation. Unfortunately, I have not included a prepared patch that can simply be enabled (which I really should have), and at this time, it would be necessary to manually apply that via a Spring override context XML file, i.e. in alfresco/extension/authentication-services-override-context.xml (the path I used in the customer's project). Such a context file would only need to contain the following bean:
<!-- default proxy has "first active wins" semantic, we want "first successful wins" --> <bean id="RemoteUserMapper" class="de.acosix.alfresco.utility.repo.subsystems.SubsystemChainingRemoteUserMapper"> <property name="applicationContextManager" ref="Authentication" /> <property name="sourceBeanName" value="remoteUserMapper" /> </bean>
I hope this helps in your case. If it does, please get back to me and ideally also raise a new issue in alfresco-keycloak, so that I have a reminder to include that in documentation as well as provide a pre-bundled patch in future versions.
Note that this patch would onyl fix the "two realms" use case for the Repository-tier (ACS), not Share SSO. Share SSO has not been designed at all to support multiple SSO authentication instances, there are no preparations in alfresco-keycloak to support this, and it would take some significant refactoring effort to achieve this within the Share architecture. So for Share, only username + password authentication with multiple Keycloak realms is supported.
Explore our Alfresco products with the links below. Use labels to filter content by product module.