Skip to content

FreeMarkerLoginFormsProvider: handleThemeResources called twice per request due to getMessage() in createCommonAttributes #49718

Description

@maeventer

Before reporting an issue

  • I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.

Area

login/ui

Describe the bug

introduced in version 26.6.2 FreeMarkerLoginFormsProvider.createResponse() calls handleThemeResources(theme, locale)
at line 242 to obtain messagesBundle, then passes it into createCommonAttributes().
However, createCommonAttributes() calls getMessage("loginTitle", ...) at line 506,
which routes through:

getMessage() → formatMessage(FormMessage) → handleThemeResources()  [line 869]

This causes handleThemeResources to execute a second time per render, redundantly:

  • loading and merging the message bundle via theme.getEnhancedMessages(realm, locale)
  • loading theme properties via theme.getProperties()
  • constructing MessageFormatterMethod and AdvancedMessageFormatterMethod

Root Cause

formatMessage(FormMessage) (no-arg bundle variant) is a convenience method that
re-resolves theme and locale from scratch. It should not be used from within
createCommonAttributes, which already has both messagesBundle and locale in scope.

Affected file

services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java

Suggested fix

Replace the getMessage() call in createCommonAttributes() with the direct
formatMessage(message, messagesBundle, locale) overload:

// Before (line 506)
attributes.put("title", getMessage("loginTitle", realmBean.getDisplayName()));

// After
attributes.put("title", formatMessage(new FormMessage(null, "loginTitle", realmBean.getDisplayName()), messagesBundle, locale));

Version

26.6.3

Regression

  • The issue is a regression

Expected behavior

handleThemeResources() called exactly once per render. The already-resolved messagesBundle and locale both available in createCommonAttributes() as parameters should be used directly via formatMessage(message, messagesBundle, locale).

Actual behavior

Every call to createResponse() or createForm() invokes handleThemeResources() twice:

  1. Explicitly at the start of both methods to obtain messagesBundle
  2. Again inside createCommonAttributes() → getMessage() → formatMessage(FormMessage) → handleThemeResources()

How to Reproduce?

  1. Add a breakpoint or log statement at the top of handleThemeResources() in FreeMarkerLoginFormsProvider
  2. Trigger any login page render (e.g. navigate to http://localhost:8080/realms//protocol/openid-connect/auth?client_id=...)
  3. Observe handleThemeResources hit twice per request
    Alternatively: add a counter/stack-trace log and watch it print twice in the server output for a single page load.

Anything else?

No response

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions