Problem: Self-Service Password Forgotten returns Portal temporarily unavailable

Self-Service Password Forgotten returns Portal temporarily unavailable

Problem

On the login screen, below the credential input form, there is a Self-Service link for Forgot your password (non-SSO login, without Keycloak installed).

The link should be reachable via:

https://fqdn/univention/selfservice/#selfservice/passwordforgotten

When accessing this URL, the following error appears:

Sorry.

The portal is temporarily unavailable. If the problem persists, please contact your system administrator.


Environment

  • UCS 5.2-4
  • System Role: Primary Node
  • self-service and self-service-backend installed
  • Non-SSO login (no Keycloak in use)

Investigation

Interestingly, the module passwordforgotten is reachable via:

https://fqdn/univention/portal/#selfservice/passwordforgotten

This causes confusion, as the functionality itself is working, but not via the intended /selfservice/ path.


Service Status

root@ucs5primary:~# systemctl status univention-portal-server.service 
● univention-portal-server.service - Univention Portal server
     Loaded: loaded (/lib/systemd/system/univention-portal-server.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-02-10 10:02:07 CET; 1 week 1 day ago
   Main PID: 2735 (univention-port)
      Tasks: 2 (limit: 38464)
     Memory: 134.6M
        CPU: 3.648s
     CGroup: /system.slice/univention-portal-server.service
             └─2735 /usr/bin/python3 /usr/sbin/univention-portal-server

Feb 18 17:04:15 ucs5primary univention-portal-server[2735]:                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]:   File "/usr/lib/python3/dist-packages/univention/portal/extensions/portal.py", line 92, in get_visible_content
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]:     announcements = self.portal_cache.get_announcements()
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]:                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]:   File "/usr/lib/python3/dist-packages/univention/portal/extensions/cache.py", line 99, in get_announcements
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]:     return deepcopy(self.get()["announcements"])
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]:                     ~~~~~~~~~~^^^^^^^^^^^^^^^^^
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]: KeyError: 'announcements'
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]: 500 GET /univention/selfservice/portal.json (127.0.0.1) 5.11ms
Feb 18 17:04:15 ucs5primary univention-portal-server[2735]: 404 GET /univention/selfservice/i18n/en.json (127.0.0.1) 0.29ms

syslog Output

Feb 18 17:27:49 ucs5primary postfix/smtpd[2767331]: connect from ucs5replica.univention.intranet[10.100.0.20]
Feb 18 17:27:49 ucs5primary postfix/smtpd[2767331]: NOQUEUE: reject: RCPT from ucs5replica.univention.intranet[10.100.0.20]: 454 4.7.1 <munin@univention.intranet>: Relay access denied; from=<> to=<munin@univention.intranet> proto>
Feb 18 17:27:49 ucs5primary postfix/smtpd[2767331]: disconnect from ucs5replica.univention.intranet[10.100.0.20] ehlo=2 starttls=1 mail=1 rcpt=0/1 data=0/1 rset=1 quit=1 commands=6/8
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: 2767117 user         26-02-18 17:27:55 [   DEBUG]: no user given
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: 2767117 cache        26-02-18 17:27:55 [    INFO]: loading cache file /var/cache/univention-portal/groups.json
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: 2767117 cache        26-02-18 17:27:55 [    INFO]: loading cache file /var/cache/univention-portal/selfservice.json
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: Uncaught exception GET /univention/selfservice/portal.json (127.0.0.1)
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: HTTPServerRequest(protocol='https', host='portal.univention.intranet', method='GET', uri='/univention/selfservice/portal.json', version='HTTP/1.1', remote>
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: Traceback (most recent call last):
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:   File "/usr/lib/python3/dist-packages/tornado/web.py", line 1721, in _execute
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:     result = await result
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:              ^^^^^^^^^^^^
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:   File "/usr/lib/python3/dist-packages/univention/portal/handlers/portal_entries_handler.py", line 31, in get
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:     visible_content = portal.get_visible_content(user, admin_mode)
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:   File "/usr/lib/python3/dist-packages/univention/portal/extensions/portal.py", line 92, in get_visible_content
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:     announcements = self.portal_cache.get_announcements()
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:   File "/usr/lib/python3/dist-packages/univention/portal/extensions/cache.py", line 99, in get_announcements
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:     return deepcopy(self.get()["announcements"])
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]:                     ~~~~~~~~~~^^^^^^^^^^^^^^^^^
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: KeyError: 'announcements'
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: 2767117 server       26-02-18 17:27:55 [   ERROR]: Error during service
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: 500 GET /univention/selfservice/portal.json (127.0.0.1) 55.73ms
Feb 18 17:27:55 ucs5primary univention-portal-server[2767117]: 404 GET /univention/selfservice/i18n/en.json (127.0.0.1) 0.36ms

Analysis

The logs clearly indicate a cache problem:

KeyError: 'announcements'

The portal server attempts to load:

/var/cache/univention-portal/selfservice.json

The JSON files in /var/cache/univention-portal/ define how the portal is rendered.

Normally, the cache can be rebuilt using:

univention-portal update

However, in this case the cache was not updated:

root@ucs5primary:~# univention-portal update
Updating default
Portal data updated in 1.67s
Updating selfservice
Portal data untouched
Updating umc
Portal data untouched

File timestamp:

root@ucs5primary:~/univention-support# ls -lah /var/cache/univention-portal/selfservice.json 
-rw------- 1 root nogroup 527K 18. Apr 2023  /var/cache/univention-portal/selfservice.json

Root Cause

The reason why selfservice.json is not updated is that the Self-Service portal object is missing in LDAP.

Verification:

root@ucs5primary:~/univention-support# univention-ldapsearch -b cn=portal,cn=portals,cn=univention,$(ucr get ldap/base) | grep cn=self-service

No output.

root@ucs5primary:~/univention-support# udm portals/portal list --filter cn=self-service | less
cn=self-service

Example of a correct object:

root@ucs5primary:~# udm portals/portal list --filter cn=self-service
cn=self-service
DN: cn=self-service,cn=portal,cn=portals,cn=univention,dc=miro,dc=intranet
  background: None  
  categories: cn=self-service-profile,cn=category,cn=portals,cn=univention,dc=miro,dc=intranet
  categories: cn=self-service-password,cn=category,cn=portals,cn=univention,dc=miro,dc=intranet
  categories: cn=self-service-new-account,cn=category,cn=portals,cn=univention,dc=miro,dc=intranet
  defaultLinkTarget: samewindow
  displayName: en_US: Self Service
  ensureLogin: FALSE
  logo: None
  name: self-service
  showUmc: FALSE
  univentionObjectIdentifier: b41dbe72-2d1d-435e-be1d-a5d7259b5294

Because the portal object does not exist, univention-portal update cannot rebuild /var/cache/univention-portal/selfservice.json.


Solution

1. Create the Self-Service portal object via UDM

udm portals/portal create --position "cn=portal,cn=portals,cn=univention,$(ucr get ldap/base)" \
--set name=self-service \
--set background=None \
--set categories="cn=self-service-profile,cn=category,cn=portals,cn=univention,$(ucr get ldap/base)" \
--set categories="cn=self-service-password,cn=category,cn=portals,cn=univention,$(ucr get ldap/base)" \
--set categories="cn=self-service-new-account,cn=category,cn=portals,cn=univention,$(ucr get ldap/base)" \
--set defaultLinkTarget=samewindow \
--set displayName='"en_US" "Self Service"' \
--set ensureLogin=FALSE \
--set logo=None \
--set showUmc=FALSE

Output:

WARNING: multiple values for categories given via --set. Use --append instead!
Object created: cn=self-service,cn=portal,cn=portals,cn=univention,dc=univention,dc=intranet

Verification:

udm portals/portal list --filter cn=self-service

cn=self-service
DN: cn=self-service,cn=portal,cn=portals,cn=univention,dc=miro,dc=intranet
  background: None
  categories: cn=self-service-profile,cn=category,cn=portals,cn=univention,dc=miro,dc=intranet
  categories: cn=self-service-password,cn=category,cn=portals,cn=univention,dc=miro,dc=intranet
  categories: cn=self-service-new-account,cn=category,cn=portals,cn=univention,dc=miro,dc=intranet
  defaultLinkTarget: samewindow
  displayName: en_US: Self Service
  ensureLogin: FALSE
  logo: None
  name: self-service
  showUmc: FALSE
  univentionObjectIdentifier: bb3c63c0-1045-464d-bbbd-82df14d0d76b

2. Rebuild /var/cache/univention-portal/selfservice.json

univention-portal update

Output:

Updating default
Portal data updated in 4.25s
Updating selfservice
Portal data updated in 3.09s
Updating umc
Portal data untouched

Verification:

ls -lah /var/cache/univention-portal/selfservice.json
-rw------- 1 root nogroup 503K 19. Feb 11:28 /var/cache/univention-portal/selfservice.json

3. Restart the portal server

systemctl restart univention-portal-server.service

Result

After recreating the missing Self-Service portal object, rebuilding the portal cache, and restarting the portal service, the URL:

https://fqdn/univention/selfservice/#selfservice/passwordforgotten

is accessible again: