8000 Resolve realm display name localization placeholders in TOTP issuer name by mabagoury · Pull Request #48700 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public TotpBean(KeycloakSession session, RealmModel realm, UserModel user, UriBu
this.totpSecret = secret;
}
this.totpSecretEncoded = TotpUtils.encode(totpSecret);
this.totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
this.totpSecretQrCode = TotpUtils.qrCode(session, totpSecret, realm, user);

OTPPolicy otpPolicy = realm.getOTPPolicy();
this.supportedApplications = session.getAllProviders(OTPApplicationProvider.class).stream()
Expand Down
48 changes: 47 additions & 1 deletion services/src/main/java/org/keycloak/utils/TotpUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,26 @@

package org.keycloak.utils;

import java.io.IOException;
import java.util.Locale;
import java.util.Properties;

import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.Base32;
import org.keycloak.theme.TemplatingUtil;
import org.keycloak.theme.Theme;

import org.jboss.logging.Logger;

/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class TotpUtils {

private static final Logger logger = Logger.getLogger(TotpUtils.class);

public static String encode(String totpSecret) {
String encoded = Base32.encode(totpSecret.getBytes());
StringBuilder sb = new StringBuilder();
Expand All @@ -38,9 +49,28 @@ public static String encode(String totpSecret) {
return sb.toString();
}

/**
* Generates a QR code using the realm name as issuer. Use when no session is available.
*
* @deprecated Use {@link #qrCode(KeycloakSession, String, RealmModel, UserModel)} instead to get locale-aware issuer names.
*/
@Deprecated(since = "26.7.0")
public static String qrCode(String totpSecret, RealmModel realm, UserModel user) {
return qrCode(null, totpSecret, realm, user);
}

/**
* Generates a QR code using a locale-aware realm display name as issuer. Preferred when a session is available.
*/
public static String qrCode(KeycloakSession session, String totpSecret, RealmModel realm, UserModel user) {
Comment thread
mabagoury marked this conversation as resolved.
Resolved
try {
String keyUri = realm.getOTPPolicy().getKeyURI(realm, user, totpSecret);
String keyUri;
if (session != null) {
String issuerName = getIssuerName(session, realm, user);
keyUri = realm.getOTPPolicy().getKeyURI(issuerName, user.getUsername(), totpSecret);
} else {
keyUri = realm.getOTPPolicy().getKeyURI(realm, user, totpSecret);
}

int width = 246;
int height = 246;
Expand All @@ -51,4 +81,20 @@ public static String qrCode(String totpSecret, RealmModel realm, UserModel user)
}
}

private static String getIssuerName(KeycloakSession session, RealmModel realm, UserModel user) {
String displayName = realm.getDisplayName();
if (StringUtil.isNullOrEmpty(displayName)) {
return realm.getName();
}

try {
Locale locale = session.getContext().resolveLocale(user);
Properties messages = session.theme().getTheme(Theme.Type.LOGIN).getEnhancedMessages(realm, locale);
return TemplatingUtil.resolveVariables(displayName, messages);
} catch (IOException e) {
logger.warn("Failed to load messages to resolve realm display name", e);
return displayName;
}
}

}
Loading
0