04-20-2021 09:15 AM
Hi all,
I have a Docker setup consisting of an Alfresco Community 6.2 backend, an ADF frontend and Keycloak. Alfresco and the ADF frontend is set up to use Keycloak for authentication and everything is working fine, i.e. the following happens:
So everything works fine, but when a (Keycloak) user logs in, Alfresco creates two user nodes with the same username in Alfresco, i.e. inspection of the sys: people container in the Nodebrowser yields
and the Alfresco log shows this error:
alfresco_1 | 2021-04-20 12:16:16,055 INFO [security.person.PersonServiceImpl] [http-nio-8080-exec-4] Splitting 1 duplicate person objects. alfresco_1 | 2021-04-20 12:16:16,062 ERROR [util.transaction.TransactionSupportUtil] [http-nio-8080-exec-4] After completion (committed) exception alfresco_1 | org.alfresco.repo.security.permissions.AccessDeniedException: 03200099 Only users with ROLE_ADMINISTRATOR are allowed to manage users. alfresco_1 | at org.alfresco.repo.security.authority.AuthorityTypeBehaviour.onUpdateProperties(AuthorityTypeBehaviour.java:89) alfresco_1 | at jdk.internal.reflect.GeneratedMethodAccessor637.invoke(Unknown Source) alfresco_1 | at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) alfresco_1 | at java.base/java.lang.reflect.Method.invoke(Method.java:566) alfresco_1 | at org.alfresco.repo.policy.JavaBehaviour$JavaMethodInvocationHandler.invoke(JavaBehaviour.java:181) alfresco_1 | at com.sun.proxy.$Proxy73.onUpdateProperties(Unknown Source)
I have tried to delete the two users (according to this thread https://hub.alfresco.com/t5/alfresco-content-services-forum/alfresco-acs-6-1-2ga-sso-authentificatio... ), but that does not solve the problem.
Any ideas why this is happening and how to fix it?
Regards,
Andreas
04-21-2021 09:17 AM
I see no substantial changes / fixes in the Repository-tier Identity Service auth subsystem for ACS 7.0. I would chalk the difference up to lucky change in timings, or maybe ADF behaviours differently for some reason.
Did you do a network trace via browser or other tools, or check the access logs to see which concurrent requests happend on the affected ACS version?
Edit: Ah, I see you already answered the second part while I was writing my reply....
Since the difference is 3 seconds (not 0.03) I definitely not suspect the last two calls to be at fault. Since the first two do not use the SSO enabled web script endpoint, that only leaves the ticket call. Can you redo your manual cURL test with that endpoint and check that it is not somehow responsible on its own?
04-22-2021 03:41 AM
Just to follow up on the discussion above. It turns out that your ( @afaust ) assumption is correct, i.e. that the problem is actually due to concurrent calls from the frontend. I found out that even though the Tomcat localhost access log states that the call to the ticket endpoint and the call to the discovery endpoint are 3 seconds apart
172.21.0.7 - - [21/Apr/2021:12:56:08 +0000] "GET /alfresco/api/-default-/public/authentication/versions/1/tickets/-me- HTTP/1.0" 200 66 172.21.0.7 - - [21/Apr/2021:12:56:11 +0000] "GET /alfresco/api/discovery HTTP/1.0" 200 2212
the browser actually sends the requests amost simultaneously (confirmed by inspection the network tab in the browser inspector), i.e. 0.02 seconds apart (I double-checked - it is actually 0.02 seconds this time 🙂 ).
To verify that the concurrent calls to the two endpoints causes the issue described in the first post in this thread, I made a small Python script to simulate the browsers behavior (included below if anyone should be interested). Running this script results in the exact same problem as described above.
So one could argue that this a a core Alfresco issue, i.e. that the Alfresco backend should be able to handle concurrent requests without creating two users with the same username and without throwing errors in the log. Alternatively, one could also argue that the problem is with the ADF library, that makes the two simultaneous calls to the backend.
Thanks for your input @afaust . I will mark your first reply above as the solution.
Python script for anyone interested:
from datetime import datetime from concurrent import futures import json import requests REALM = 'alfresco' TOKEN_URL = f'https://some.domain/auth/realms/{REALM}' \ f'/protocol/openid-connect/token' ALF_BASEURL = 'https://some.domain/alfresco/api'
# Get token payload = { 'client_id': 'alfresco', 'username': 'bruce', 'password': 'bruce', 'grant_type': 'password' } r = requests.post(TOKEN_URL, data=payload, verify=False) print(r.status_code, r.url) token = r.json()['access_token'] headers = { 'Authorization': f'bearer {token}' } def call_alf(url): print(datetime.now(), 'Calling ' + url) r = requests.get(url, headers=headers, verify=False) print(datetime.now(), 'Response from ' + url) return r.status_code, r.url
# Make concurrent requests
with futures.ThreadPoolExecutor(2) as executor: resp_gen = executor.map(call_alf, [ ALF_BASEURL + '/-default-/public/authentication/versions/1/tickets/-me-', ALF_BASEURL + '/discovery' ]) print(list(resp_gen))
04-22-2021 03:41 AM
Just to follow up on the discussion above. It turns out that your ( @afaust ) assumption is correct, i.e. that the problem is actually due to concurrent calls from the frontend. I found out that even though the Tomcat localhost access log states that the call to the ticket endpoint and the call to the discovery endpoint are 3 seconds apart
172.21.0.7 - - [21/Apr/2021:12:56:08 +0000] "GET /alfresco/api/-default-/public/authentication/versions/1/tickets/-me- HTTP/1.0" 200 66 172.21.0.7 - - [21/Apr/2021:12:56:11 +0000] "GET /alfresco/api/discovery HTTP/1.0" 200 2212
the browser actually sends the requests amost simultaneously (confirmed by inspection the network tab in the browser inspector), i.e. 0.02 seconds apart (I double-checked - it is actually 0.02 seconds this time 🙂 ).
To verify that the concurrent calls to the two endpoints causes the issue described in the first post in this thread, I made a small Python script to simulate the browsers behavior (included below if anyone should be interested). Running this script results in the exact same problem as described above.
So one could argue that this a a core Alfresco issue, i.e. that the Alfresco backend should be able to handle concurrent requests without creating two users with the same username and without throwing errors in the log. Alternatively, one could also argue that the problem is with the ADF library, that makes the two simultaneous calls to the backend.
Thanks for your input @afaust . I will mark your first reply above as the solution.
Python script for anyone interested:
from datetime import datetime from concurrent import futures import json import requests REALM = 'alfresco' TOKEN_URL = f'https://some.domain/auth/realms/{REALM}' \ f'/protocol/openid-connect/token' ALF_BASEURL = 'https://some.domain/alfresco/api'
# Get token payload = { 'client_id': 'alfresco', 'username': 'bruce', 'password': 'bruce', 'grant_type': 'password' } r = requests.post(TOKEN_URL, data=payload, verify=False) print(r.status_code, r.url) token = r.json()['access_token'] headers = { 'Authorization': f'bearer {token}' } def call_alf(url): print(datetime.now(), 'Calling ' + url) r = requests.get(url, headers=headers, verify=False) print(datetime.now(), 'Response from ' + url) return r.status_code, r.url
# Make concurrent requests
with futures.ThreadPoolExecutor(2) as executor: resp_gen = executor.map(call_alf, [ ALF_BASEURL + '/-default-/public/authentication/versions/1/tickets/-me-', ALF_BASEURL + '/discovery' ]) print(list(resp_gen))
04-22-2021 07:15 AM
You are also right about Alfresco 7.0.0 - did some more testing, and the same error was found in Alfresco Community 7.0.0
Explore our Alfresco products with the links below. Use labels to filter content by product module.