Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
alvesfonseca opened this issue Jun 9, 2021 · 14 comments
Open

Comments

@alvesfonseca
Copy link

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
Copy link
Author

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

@AFaust
Copy link
Member

AFaust commented Jun 9, 2021

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).

@ayian2004
Copy link

ayian2004 commented Jun 9, 2021

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?

@alvesfonseca
Copy link
Author

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
Copy link
Author

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?

@AFaust
Copy link
Member

AFaust commented Jun 9, 2021

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.

@alvesfonseca
Copy link
Author

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
Copy link
Author

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.

@AFaust
Copy link
Member

AFaust commented Jun 10, 2021

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).

@alvesfonseca
Copy link
Author

alvesfonseca commented Jun 10, 2021

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

@snaperski
Copy link

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
Copy link

snaperski commented Aug 11, 2022

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.

@giuseppeurso-eu
Copy link

giuseppeurso-eu commented Oct 18, 2022

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

@willisplummer
Copy link

I was running into a similar error screen when attempting to login using email and password. Everything worked fine logging in with username and password, but Share wasn't reconciling that the email address should map to the username in alfresco.

Turned out I had only bothered to configure the alfresco parts and not the share bits. I was wrongly assuming that because authing with username and password worked and I didn't want SSO, I didn't need to setup the share code from this library.

For me, installing the share extensions was the key to getting everything working.

Hopefully someone sees this and finds it helpful in the future!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants