DeviceRepresentationProviderImpl.java
package org.keycloak.device;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.representations.account.DeviceRepresentation;
import ua_parser.Client;
import ua_parser.Parser;
import jakarta.ws.rs.core.HttpHeaders;
public class DeviceRepresentationProviderImpl implements DeviceRepresentationProvider {
private static final Logger logger = Logger.getLogger(DeviceActivityManager.class);
private static final int USER_AGENT_MAX_LENGTH = 512;
private final Parser parser;
private final KeycloakSession session;
DeviceRepresentationProviderImpl(KeycloakSession session, Parser parser) {
this.session = session;
this.parser = parser;
}
@Override
public DeviceRepresentation deviceRepresentation() {
KeycloakContext context = session.getContext();
if (context.getRequestHeaders() == null) {
return null;
}
String userAgent = context.getRequestHeaders().getHeaderString(HttpHeaders.USER_AGENT);
if (userAgent == null) {
return null;
}
if (userAgent.length() > USER_AGENT_MAX_LENGTH) {
logger.warn("Ignoring User-Agent header. Length is above the permitted: " + USER_AGENT_MAX_LENGTH);
return null;
}
DeviceRepresentation current;
try {
Client client = parser.parse(userAgent);
current = new DeviceRepresentation();
current.setDevice(client.device.family);
String browserVersion = client.userAgent.major;
if (client.userAgent.minor != null) {
browserVersion += "." + client.userAgent.minor;
}
if (client.userAgent.patch != null) {
browserVersion += "." + client.userAgent.patch;
}
if (browserVersion == null) {
browserVersion = DeviceRepresentation.UNKNOWN;
}
current.setBrowser(client.userAgent.family, browserVersion);
current.setOs(client.os.family);
String osVersion = client.os.major;
if (client.os.minor != null) {
osVersion += "." + client.os.minor;
}
if (client.os.patch != null) {
osVersion += "." + client.os.patch;
}
if (client.os.patchMinor != null) {
osVersion += "." + client.os.patchMinor;
}
current.setOsVersion(osVersion);
current.setIpAddress(context.getConnection().getRemoteAddr());
current.setMobile(userAgent.toLowerCase().contains("mobile"));
} catch (Exception cause) {
logger.error("Failed to create device info from user agent header", cause);
return null;
}
return current;
}
}