alfresco-keycloak icon indicating copy to clipboard operation
alfresco-keycloak copied to clipboard

Unable to retrieve user from repository (token-exchange turned off)

Open alvesfonseca opened this issue 3 years ago • 13 comments

Probably related to #12

First, I would like to thank you for this awesome addon!

I am experimenting with alfresco-keycloak using docker images (alfresco-content-repository-community:6.2.1-A8) and I managed to use keycloak as an authentication backend.

I made my best effort to follow the alfresco-keycloak documentation, by configuring a realm and different clients for Repo (repo-client) and Share (share-client). (I believe) I didn't miss any step when configuring Repo and Share to allow for alfresco-keycloak extended services.

In a first approach, I decided to turn off token exchange after setting verify-token-audience and perform-token-exchange to false. In this scenario, I didn't configure a authorization policy in realm-management client.

I managed to log in to Repo resources (http://localhost:8080/alfresco/wcs/admin) using keycloak repo-client and I was able to login to Share (http://localhost:8080/share), but, as soon as keycloak share-client checks the user's credentials, I can't get to the user's dashboard. I get the following page.

Captura de tela de 2021-06-08 23-44-27

Share log reports Unable to retrieve user from repository

share_1               | 2021-06-09 02:37:29,207  ERROR [alfresco.web.site] [http-nio-8080-exec-5] org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               |  org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:195)
share_1               | 	at org.alfresco.web.site.SlingshotUserFactory.loadUser(SlingshotUserFactory.java:146)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:183)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:101)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.initialiseUser(RequestContextUtil.java:260)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:183)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:138)
share_1               | 	at de.acosix.alfresco.keycloak.share.web.PopulatingRequestContextInterceptor.preHandle(PopulatingRequestContextInterceptor.java:57)
....
share_1               | Caused by: org.springframework.extensions.surf.exception.UserFactoryException: Unable to create user - failed to retrieve user metadata: 
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:185)
share_1               | 	... 49 more
...

Any debugging suggestion?

Thanks in advance!

alvesfonseca avatar Jun 09 '21 03:06 alvesfonseca

The users I tested were existing ones in Alfresco and in the Keyclock realm (same username and e-mail).

alvesfonseca avatar Jun 09 '21 03:06 alvesfonseca

Can you also check for (and provide) any log messages from the Repository log files (alfresco.log). Typically, the failure of Share to load the user data is based on the authentication / token being rejected at the backend. Just to make sure: Have you disabled verify-token-audience on the Share tier or the Repository tier? Maybe the preliminary documentation needs to be clarified here: If Share does not perform token exchange, the audience verification needs to be disabled in the Repository via the keycloak.adapter.verify-token-audience property. In Share itself it would only be needed to be disabled if a 3rd-party application were to call Share without performing token exchange - which is a far less likely use case, and has definitely not been tested (i.e. I would be surprised if Share could actually perform a token exchange in that scenario even if enabled).

AFaust avatar Jun 09 '21 10:06 AFaust

Hi @AFaust I have the same problem. However, as soon as I assign any role (https://github.com/Acosix/alfresco-keycloak/blob/docs-wip/docs/Simple-Configuration.md#roles--groups) to the user then Share can successfully load the user data. Is this related?

ayian2004 avatar Jun 09 '21 12:06 ayian2004

Hi @AFaust , thank you for the reply!

Can you also check for (and provide) any log messages from the Repository log files (alfresco.log). Typically, the failure of Share to load the user data is based on the authentication / token being rejected at the backend.

I have checked alfresco.log for any failure message, but I was unable to find any.

Apparently, the user succesfully log-in to Share, however the exception shown in the log doesn't allow the user to get to his dashboard. On Keycloak, I can list the active Share session.

Just to make sure: Have you disabled verify-token-audience on the Share tier or the Repository tier?

I disabled verify-token-audience on Repository tier only (keycloak.adapter.verify-token-audience=false).

On Share tier, I set <perform-token-exchange>false</perform-token-exchange>.

Maybe the preliminary documentation needs to be clarified here: If Share does not perform token exchange, the audience verification needs to be disabled in the Repository via the keycloak.adapter.verify-token-audience property. In Share itself it would only be needed to be disabled if a 3rd-party application were to call Share without performing token exchange - which is a far less likely use case, and has definitely not been tested (i.e. I would be surprised if Share could actually perform a token exchange in that scenario even if enabled).

No problem!

It is a complex project and I hope my doubts may help to evolve the project documentation.

I will redo my setup using alfresco-7 docker images.

alvesfonseca avatar Jun 09 '21 21:06 alvesfonseca

Hi @AFaust I have the same problem. However, as soon as I assign any role (https://github.com/Acosix/alfresco-keycloak/blob/docs-wip/docs/Simple-Configuration.md#roles--groups) to the user then Share can successfully load the user data. Is this related?

@ayian2004 , thank you for the suggestion.

I have browsed keycloak UI in order to assign roles, but I wasn't able to find a spot/tab/page where I could to the role configuration.

Could you point me to keycloak docs where I could learn about?

I believe that the suggested configuration should be done on share-client (keycloak). Is this correct?

alvesfonseca avatar Jun 09 '21 21:06 alvesfonseca

The assignment of roles on the Keycloak side of things should not have any impact on the default operation of the module. While my test setup contains a default role "admin", it is only there to test the dedicated role mapping functionality of the Keycloak integration.

AFaust avatar Jun 09 '21 23:06 AFaust

Hi guys!

I tried to repeat the setup using alfresco-content-repository-community:7.0.0 image(s) and Snapshot versions from alfresco-utility and alfresco-keycloak amps I compiled.

My keycloak server is on version 13.0.0.

Keycloak (port 9080) and alfresco's docker images are both running locally.

I configured Repo and Share tiers to talk to Keycloak on the external IP of my machine.

On the Keycloak clients, the root URL's for repo-client and share-client are localhost:8080/alfresco and localhost:8080/share respectively.

On Share tier, I set <perform-token-exchange>false</perform-token-exchange>.

I tested using all the available values for verify-token-audience on Repository tier.

I got the following exception on the Share logs when using verify-token-audience=true

share_1               | 2021-06-10 02:27:23,200  ERROR [share.web.KeycloakAuthenticationFilter] [http-nio-8080-exec-10] Error calling populateRequestContext
share_1               |  org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:195)
share_1               | 	at org.alfresco.web.site.SlingshotUserFactory.loadUser(SlingshotUserFactory.java:141)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:183)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:101)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.initialiseUser(RequestContextUtil.java:260)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:183)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:138)
share_1               | 	at de.acosix.alfresco.keycloak.share.web.KeycloakAuthenticationFilter.completeRequestContext(KeycloakAuthenticationFilter.java:1148)
share_1               | 	at de.acosix.alfresco.keycloak.share.web.KeycloakAuthenticationFilter.doFilter(KeycloakAuthenticationFilter.java:473)
share_1               | 	at org.springframework.extensions.webscripts.servlet.BeanProxyFilter.doFilter(BeanProxyFilter.java:80)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.alfresco.web.site.servlet.AIMSFilter.doFilter(AIMSFilter.java:145)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.alfresco.web.site.servlet.MTAuthenticationFilter.doFilter(MTAuthenticationFilter.java:76)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
share_1               | 	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
share_1               | 	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
share_1               | 	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
share_1               | 	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
share_1               | 	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
share_1               | 	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
share_1               | 	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
share_1               | 	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
share_1               | 	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
share_1               | 	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888)
share_1               | 	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
share_1               | 	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
share_1               | 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
share_1               | 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
share_1               | 	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
share_1               | 	at java.base/java.lang.Thread.run(Thread.java:834)
share_1               | Caused by: org.springframework.extensions.surf.exception.UserFactoryException: Unable to create user - failed to retrieve user metadata: 
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:185)
share_1               | 	... 34 more
share_1               | 2021-06-10 02:27:23,245  ERROR [alfresco.web.site] [http-nio-8080-exec-10] javax.servlet.ServletException: org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               |  org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:195)
share_1               | 	at org.alfresco.web.site.SlingshotUserFactory.loadUser(SlingshotUserFactory.java:141)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:183)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:101)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.initialiseUser(RequestContextUtil.java:260)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:183)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:138)
share_1               | 	at de.acosix.alfresco.keycloak.share.web.KeycloakAuthenticationFilter.completeRequestContext(KeycloakAuthenticationFilter.java:1148)
share_1               | 	at de.acosix.alfresco.keycloak.share.web.KeycloakAuthenticationFilter.doFilter(KeycloakAuthenticationFilter.java:473)
share_1               | 	at org.springframework.extensions.webscripts.servlet.BeanProxyFilter.doFilter(BeanProxyFilter.java:80)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.alfresco.web.site.servlet.AIMSFilter.doFilter(AIMSFilter.java:145)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.alfresco.web.site.servlet.MTAuthenticationFilter.doFilter(MTAuthenticationFilter.java:76)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
share_1               | 	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
share_1               | 	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
share_1               | 	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
share_1               | 	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
share_1               | 	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
share_1               | 	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
share_1               | 	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
share_1               | 	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
share_1               | 	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
share_1               | 	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888)
share_1               | 	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
share_1               | 	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
share_1               | 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
share_1               | 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
share_1               | 	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
share_1               | 	at java.base/java.lang.Thread.run(Thread.java:834)
share_1               | Caused by: org.springframework.extensions.surf.exception.UserFactoryException: Unable to create user - failed to retrieve user metadata: 
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:185)
share_1               | 	... 34 more
proxy_1               | 172.25.0.1 - - [10/Jun/2021:02:27:23 +0000] "GET /share/page/ HTTP/1.1" 500 2894 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
share_1               | 2021-06-10 02:27:23,296  ERROR [alfresco.web.site] [http-nio-8080-exec-4] org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               |  org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:195)
share_1               | 	at org.alfresco.web.site.SlingshotUserFactory.loadUser(SlingshotUserFactory.java:141)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:183)
share_1               | 	at org.springframework.extensions.surf.support.AbstractUserFactory.initialiseUser(AbstractUserFactory.java:101)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.initialiseUser(RequestContextUtil.java:260)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:183)
share_1               | 	at org.springframework.extensions.surf.RequestContextUtil.populateRequestContext(RequestContextUtil.java:138)
share_1               | 	at de.acosix.alfresco.keycloak.share.web.PopulatingRequestContextInterceptor.preHandle(PopulatingRequestContextInterceptor.java:57)
share_1               | 	at org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter.preHandle(WebRequestHandlerInterceptorAdapter.java:57)
share_1               | 	at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:148)
share_1               | 	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055)
share_1               | 	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
share_1               | 	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
share_1               | 	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
share_1               | 	at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
share_1               | 	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
share_1               | 	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712)
share_1               | 	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459)
share_1               | 	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:384)
share_1               | 	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312)
share_1               | 	at org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:213)
share_1               | 	at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:171)
share_1               | 	at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
share_1               | 	at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
share_1               | 	at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:389)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
share_1               | 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
share_1               | 	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
share_1               | 	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
share_1               | 	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
share_1               | 	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
share_1               | 	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
share_1               | 	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
share_1               | 	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
share_1               | 	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
share_1               | 	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
share_1               | 	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
share_1               | 	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888)
share_1               | 	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
share_1               | 	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
share_1               | 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
share_1               | 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
share_1               | 	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
share_1               | 	at java.base/java.lang.Thread.run(Thread.java:834)
share_1               | Caused by: org.springframework.extensions.surf.exception.UserFactoryException: Unable to create user - failed to retrieve user metadata: 
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:185)
share_1               | 	... 49 more
proxy_1               | 172.25.0.1 - - [10/Jun/2021:02:27:23 +0000] "GET /share/res/modules/images/about-bg-vanilla.png HTTP/1.1" 500 2894 "http://localhost:8080/share/page/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"

The error is basically the same, however the exceptions are a bit more informative.

I double checked the configurations on Repo and Share tiers and also on Keycloak.

I got the sessions on Keycloak for Share and Repo tiers, however the admin user still can't get to its dashboard.

No error messages on Keycloak or on Repo tier.

I believe I am missing a detail, but I can't figure out.

alvesfonseca avatar Jun 10 '21 03:06 alvesfonseca

Hi guys,

Just another update.

If I don't configure the connector in Alfresco Connector in the Share tier (share-config-custom.xml without <id>alfrescoCookie</id> and the remaining entries to redirect endpoints to /wcs ), I am able to authenticate to Repo and Share tiers using Keycloak users.

However, I miss the features like Log in via SSO button in the Share login form and forced SSO.

alvesfonseca avatar Jun 10 '21 14:06 alvesfonseca

That is to be expected. The alfrescoCookie connector and /wcs endpoints are essential for SSO handling towards the backend. as the /s endpoint is incapable of handling Keycloak tokens (or anything else other than user + password).

AFaust avatar Jun 10 '21 15:06 AFaust

Hi @AFaust , thanks for replying.

I believe that my Keycloak setup is okay in some sense, because I am able to delegate credentials checking to Keycloak without the connector.

When I turn on the connector (and the remaning entries that redirect to /wcs), I get the modified login Form (or the forced SSO Form). I can verify the user credentials but unable to get to the user's dashboard.

The exception I got was (as above, thrown by share.web.KeycloakAuthenticationFilter on the Share tier):

share_1               | 2021-06-10 02:27:23,200  ERROR [share.web.KeycloakAuthenticationFilter] [http-nio-8080-exec-10] Error calling populateRequestContext
share_1               |  org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository
share_1               | 	at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:195)

I am double checking every setting and I realized that I configured Repo tier using the global file: tomcat/webapps/alfresco/WEB-INF/classes/alfresco/subsystems/Authentication/keycloak/keycloak-authentication.properties instead of creating a specific file as suggested by the docs.

It seems to work because without point the keycloak.adapter.auth-server-url to the right Keycloak URL/URI, the system is unavailable.

Another finding is that, when I use the enhanced login Form (Share tier) and fill in using the credentials I have either on Alfresco or on Keycloak, I fail to log in and I get the following exception:

proxy_1               | 172.25.0.1 - - [10/Jun/2021:18:43:42 +0000] "POST /share/page/dologin HTTP/1.1" 302 0 "http://localhost:8080/share/page/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0"
share_1               |  2021-06-10 18:43:42,466  WARN  [share.web.KeycloakAuthenticationFilter] [http-nio-8080-exec-6] Keycloak authentication failed due to <missing AuthenticationError details in request context>

I if try the Login via SSO, the credentials are verified by Keycloak and a session is created on Keycloak, but the user can't get to its dashboard.

I am using a fresh/empty Alfresco installation.

While digging (and updating this comment), I found a acosix-keycloak Warning message on the Repo tier:

2021-06-10 18:33:55,531 INFO  [de.acosix.alfresco.utility.common.spring.BeanDefinitionFromPropertiesPostProcessor] [main] [acosix-keycloak-dynamicRolesComponentsEmitter] Processing beans defined via properties files using prefix keycloak.roles
2021-06-10 18:33:55,658 WARN  [org.springframework.beans.GenericTypeAwarePropertyDescriptor] [main] Invalid JavaBean property 'authenticationComponent' being accessed! Ambiguous write methods found next to actually used [public void de.acosix.alfresco.keycloak.repo.authentication.KeycloakAuthenticationServiceImpl.setAuthenticationComponent(de.acosix.alfresco.keycloak.repo.authentication.KeycloakAuthenticationComponent)]: [public void org.alfresco.repo.security.authentication.AuthenticationServiceImpl.setAuthenticationComponent(org.alfresco.repo.security.authentication.AuthenticationComponent)]
2021-06-10 18:33:55,776 INFO  [org.alfresco.repo.management.subsystems.ChildApplicationContextFactory] [main] Startup of 'Authentication' subsystem, ID: [Authentication, managed, keycloak1] complete

alvesfonseca avatar Jun 10 '21 18:06 alvesfonseca

Hello!

@AFaust - I have also same issue. Same error message and have checked the configuration and followed this thread. Now I have no ideas left to try. Just in case configuration from relevant sections in share-config-custom:

        <keycloak-auth-config>
            <enhance-login-form>true</enhance-login-form>
            <enable-sso-filter>true</enable-sso-filter>
            <force-keycloak-sso>false</force-keycloak-sso>
            <ssl-redirect-port>8443</ssl-redirect-port>
            <body-buffer-limit>10485760</body-buffer-limit>
            <session-mapper-limit>1000</session-mapper-limit>
            <ignore-default-filter>true</ignore-default-filter>
            <perform-token-exchange>false</perform-token-exchange>
            <alfresco-resource-name>alfresco-repo</alfresco-resource-name>
        </keycloak-auth-config>
        <keycloak-adapter-config>
            <forced-route-url></forced-route-url>
            <!-- by default use the same client as alfresco (not really "clean") -->
            <auth-server-url>https://xxx.xxx.xx/auth</auth-server-url>
            <realm>alfresco</realm>
            <confidential-port>-1</confidential-port>
            <resource>alfresco-share</resource>
            <ssl-required>all</ssl-required>
            <!-- other than content-app / Identity Service, Share must/should be a confidential client to exchange code for access token + refresh -->
            <public-client>false</public-client>
            <verify-token-audience>false</verify-token-audience>
            <always-refresh-token>true</always-refresh-token>
            <register-node-at-startup>false</register-node-at-startup>
            <register-node-period>-1</register-node-period>
            <token-minimum-time-to-live>0</token-minimum-time-to-live>
            <min-time-between-jwks-requests>10</min-time-between-jwks-requests>
            <allow-any-hostname>false</allow-any-hostname>
            <disable-trust-manager>false</disable-trust-manager>
            <public-key-cache-ttl>86400</public-key-cache-ttl>
            <enable-pkce>false</enable-pkce>
            <ignore-oauth-query-parameter>false</ignore-oauth-query-parameter>
            <socket-timeout-millis>5000</socket-timeout-millis>
            <connection-timeout-millis>5000</connection-timeout-millis>
            <connection-ttl-millis>-1</connection-ttl-millis>
            <use-resource-role-mappings>false</use-resource-role-mappings>
            <enable-cors>false</enable-cors>
            <enable-basic-auth>false</enable-basic-auth>
            <expose-token>false</expose-token>
            <bearer-only>false</bearer-only>
            <autodetect-bearer-only>false</autodetect-bearer-only>
            <token-store>session</token-store>
            <realm-public-key>xxx</realm-public-key>
            <credentials>
                <provider>secret</provider>
                <secret>xxx</secret>
            </credentials>
        </keycloak-adapter-config> 

If there ever was a solution to this problem or any thoughts how to fix it, would be highly appreciated. The errors are the same already mentioned here:

  2022-08-09 15:32:21,456 ERROR [de.acosix.alfresco.keycloak.share.web.KeycloakAuthenticationFilter] [https-jsse-nio2-9443-exec-3] Error calling populateRequestContext
org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository

..etc

Regards, Raivo

snaperski avatar Aug 09 '22 14:08 snaperski

I have played now quite a lot with the different parameters and the error is the same, but now I have also tcpdumped the communication happening and I see:

/alfresco/wcs/webframework/content/metadata?user=xxx HTTP/1.1
authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgO.......

... and the response is 401 page with following error.

<div style="padding: 8px; margin: 8px; border: 1px dashed #D7D7D7;">
   <div style="font-weight: bold; font-size: 116%">
      <div style="padding: 2px">An error has occured in the API: /alfresco/wcs/webframework/content/metadata.</div>
      <div style="padding: 2px">It responded with a status of 401 - Unauthorized.</div>
   </div>
   <div style="padding-top:8px;">
      <div style="padding: 2px"><b>Error Code Information:</b> 401 - The request requires HTTP authentication.</div>
      <div style="padding: 2px"><b>Error Message:</b> 07110010 Authorization &#39;Bearer&#39; not supported.</div>
      <div style="padding: 2px"><b>Server:</b> Alfresco Enterprise v7.1.1 (rb6059065-b4589) schema 15,100</div>
      <div style="padding: 2px"><b>Time:</b> Aug 11, 2022, 2:49:05 PM</div>
   </div>

However, did not found any way how to solve this "Authorization Bearer not supported" error on Alfresco side.

snaperski avatar Aug 11 '22 12:08 snaperski

Same issue here after setting:
keycloak.adapter.verify-token-audience=false (Repo tier)
<perform-token-exchange>false</perform-token-exchange> (Share tier)

User is correctly authenticated on Keycloak side (you can see the active user session on Keycloak admin panel). But it seems AlfrescoUserFactory.loadUser() on Share tier fails to retrieve user properties via buildUserMetadataRestUrl()

org.springframework.extensions.surf.exception.UserFactoryException: Unable to retrieve user from repository at org.springframework.extensions.surf.support.AlfrescoUserFactory.loadUser(AlfrescoUserFactory.java:195) After a bit of debugging I found the involved code:

           // build the REST URL to retrieve requested user details
            String uri = buildUserMetadataRestUrl(context, requestedUserId, endpointId);
            
            // invoke and check for OK response
            Response response = connector.call(uri);
            if (Status.STATUS_OK != response.getStatus().getCode())
            {
                throw new UserFactoryException("Unable to create user - failed to retrieve user metadata: " + 
                        response.getStatus().getMessage(), (Exception)response.getStatus().getException());
            }

The endpoint for user properties is: uri=/webframework/content/metadata?user=usernameXX_here Response status: HTTP Status 404 – Not Found Assuming the above uri maps an Alfresco webscript, I'm just wondering if that stil works on Alfresco 7.1

giuseppeurso-eu avatar Oct 18 '22 17:10 giuseppeurso-eu