use of org.keycloak.representations.account.DeviceRepresentation in project keycloak by keycloak.
the class DeviceActivityManager method getDeviceFromUserAgent.
private static DeviceRepresentation getDeviceFromUserAgent(KeycloakSession session) {
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 = UA_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;
}
use of org.keycloak.representations.account.DeviceRepresentation in project keycloak by keycloak.
the class SessionRestServiceTest method testGetDevicesSessions.
@Test
public void testGetDevicesSessions() throws Exception {
ContainerAssume.assumeAuthServerUndertow();
assumeTrue("Browser must be htmlunit. Otherwise we are not able to set desired BrowserHeaders", System.getProperty("browser").equals("htmlUnit"));
WebDriver firstBrowser = oauth.getDriver();
// first browser authenticates from Fedora
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1");
codeGrant("public-client-0");
List<DeviceRepresentation> devices = getDevicesOtherThanOther();
assertEquals("Should have a single device", 1, devices.size());
List<DeviceRepresentation> fedoraDevices = devices.stream().filter(deviceRepresentation -> "Fedora".equals(deviceRepresentation.getOs())).collect(Collectors.toList());
assertEquals("Should have a single Fedora device", 1, fedoraDevices.size());
fedoraDevices.stream().forEach(device -> {
List<SessionRepresentation> sessions = device.getSessions();
assertEquals(1, sessions.size());
assertThat(sessions, Matchers.hasItem(Matchers.hasProperty("browser", Matchers.is("Firefox/15.0.1"))));
});
// second browser authenticates from Windows
oauth.setDriver(secondBrowser);
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Gecko/20100101 Firefox/15.0.1");
codeGrant("public-client-0");
devices = getDevicesOtherThanOther();
// should have two devices
assertEquals("Should have two devices", 2, devices.size());
fedoraDevices = devices.stream().filter(deviceRepresentation -> "Fedora".equals(deviceRepresentation.getOs())).collect(Collectors.toList());
assertEquals(1, fedoraDevices.size());
List<DeviceRepresentation> windowsDevices = devices.stream().filter(deviceRepresentation -> "Windows".equals(deviceRepresentation.getOs())).collect(Collectors.toList());
assertEquals(1, windowsDevices.size());
windowsDevices.stream().forEach(device -> {
List<SessionRepresentation> sessions = device.getSessions();
assertEquals(1, sessions.size());
assertThat(sessions, Matchers.hasItem(Matchers.hasProperty("browser", Matchers.is("Firefox/15.0.1"))));
});
// first browser authenticates from Windows using Edge
oauth.setDriver(firstBrowser);
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (Windows Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0");
codeGrant("public-client-0");
// second browser authenticates from Windows using Firefox
oauth.setDriver(secondBrowser);
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Gecko/20100101 Firefox/15.0.1");
codeGrant("public-client-0");
// third browser authenticates from Windows using Safari
oauth.setDriver(thirdBrowser);
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/11.0 Safari/603.1.30");
oauth.setBrowserHeader("X-Forwarded-For", "192.168.10.3");
OAuthClient.AccessTokenResponse tokenResponse = codeGrant("public-client-0");
devices = getDevicesOtherThanOther(tokenResponse.getAccessToken());
assertEquals("Should have a single device because all browsers (and sessions) are from the same platform (OS + OS version)", 1, devices.size());
windowsDevices = devices.stream().filter(device -> "Windows".equals(device.getOs())).collect(Collectors.toList());
assertEquals(1, windowsDevices.size());
windowsDevices.stream().forEach(device -> {
List<SessionRepresentation> sessions = device.getSessions();
assertEquals(3, sessions.size());
assertEquals(1, sessions.stream().filter(rep -> rep.getIpAddress().equals("127.0.0.1") && rep.getBrowser().equals("Firefox/15.0.1") && rep.getCurrent() == null).count());
assertEquals(1, sessions.stream().filter(rep -> rep.getIpAddress().equals("127.0.0.1") && rep.getBrowser().equals("Edge/12.0") && rep.getCurrent() == null).count());
assertEquals(1, sessions.stream().filter(rep -> rep.getIpAddress().equals("192.168.10.3") && rep.getBrowser().equals("Safari/11.0") && rep.getCurrent()).count());
});
// third browser authenticates from Windows using a different Windows version
oauth.setDriver(thirdBrowser);
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (Windows 7) AppleWebKit/537.36 (KHTML, like Gecko) Version/11.0 Safari/603.1.30");
oauth.setBrowserHeader("X-Forwarded-For", "192.168.10.3");
codeGrant("public-client-0");
devices = getDevicesOtherThanOther();
windowsDevices = devices.stream().filter(device -> "Windows".equals(device.getOs())).collect(Collectors.toList());
assertEquals("Should have two devices for two distinct Windows versions", 2, devices.size());
assertEquals(2, windowsDevices.size());
oauth.setDriver(firstBrowser);
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3");
codeGrant("public-client-0");
oauth.setDriver(secondBrowser);
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1");
codeGrant("public-client-0");
devices = getDevicesOtherThanOther();
assertEquals("Should have 3 devices", 3, devices.size());
windowsDevices = devices.stream().filter(device -> "Windows".equals(device.getOs())).collect(Collectors.toList());
assertEquals(1, windowsDevices.size());
fedoraDevices = devices.stream().filter(deviceRepresentation -> "Fedora".equals(deviceRepresentation.getOs())).collect(Collectors.toList());
assertEquals(1, fedoraDevices.size());
List<DeviceRepresentation> iphoneDevices = devices.stream().filter(device -> "iOS".equals(device.getOs()) && "iPhone".equals(device.getDevice())).collect(Collectors.toList());
assertEquals(1, iphoneDevices.size());
iphoneDevices.stream().forEach(device -> {
assertTrue(device.isMobile());
List<SessionRepresentation> sessions = device.getSessions();
assertEquals(1, sessions.size());
assertEquals(1, sessions.stream().filter(rep -> rep.getBrowser().equals("Mobile Safari/5.1")).count());
});
}
use of org.keycloak.representations.account.DeviceRepresentation in project keycloak by keycloak.
the class SessionRestServiceTest method testGetDevicesResponse.
@Test
@AuthServerContainerExclude(AuthServer.REMOTE)
public void testGetDevicesResponse() throws Exception {
assumeTrue("Browser must be htmlunit. Otherwise we are not able to set desired BrowserHeaders", System.getProperty("browser").equals("htmlUnit"));
oauth.setBrowserHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0) Gecko/20100101 Firefox/15.0.1");
OAuthClient.AccessTokenResponse tokenResponse = codeGrant("public-client-0");
joinSsoSession("public-client-1");
List<DeviceRepresentation> devices = getDevicesOtherThanOther(tokenResponse.getAccessToken());
assertEquals("Should have a single device", 1, devices.size());
DeviceRepresentation device = devices.get(0);
assertTrue(device.getCurrent());
assertEquals("Windows", device.getOs());
assertEquals("10", device.getOsVersion());
assertEquals("Other", device.getDevice());
List<SessionRepresentation> sessions = device.getSessions();
assertEquals(1, sessions.size());
SessionRepresentation session = sessions.get(0);
assertEquals("127.0.0.1", session.getIpAddress());
assertTrue(device.getLastAccess() == session.getLastAccess());
List<ClientRepresentation> clients = session.getClients();
assertEquals(2, clients.size());
assertThat(session.getClients(), Matchers.hasItem(Matchers.hasProperty("clientId", anyOf(Matchers.is("public-client-0"), Matchers.is("public-client-1")))));
assertThat(session.getClients(), Matchers.hasItem(Matchers.hasProperty("clientName", anyOf(Matchers.is("Public Client 0"), Matchers.is("Public Client 1")))));
}
use of org.keycloak.representations.account.DeviceRepresentation in project keycloak by keycloak.
the class SessionRestServiceTest method testNullOrEmptyUserAgent.
@Test
@AuthServerContainerExclude(AuthServer.REMOTE)
public void testNullOrEmptyUserAgent() throws Exception {
assumeTrue("Browser must be htmlunit. Otherwise we are not able to set desired BrowserHeaders", System.getProperty("browser").equals("htmlUnit"));
oauth.setBrowserHeader("User-Agent", null);
OAuthClient.AccessTokenResponse tokenResponse = codeGrant("public-client-0");
List<DeviceRepresentation> devices = queryDevices(tokenResponse.getAccessToken());
assertEquals("Should have a single device", 1, devices.size());
DeviceRepresentation device = devices.get(0);
assertTrue(device.getCurrent());
assertEquals("Other", device.getOs());
assertEquals("Other", device.getDevice());
List<SessionRepresentation> sessions = device.getSessions();
assertEquals(1, sessions.size());
SessionRepresentation session = sessions.get(0);
assertEquals("127.0.0.1", session.getIpAddress());
assertEquals(device.getLastAccess(), session.getLastAccess());
assertEquals(1, session.getClients().size());
}
use of org.keycloak.representations.account.DeviceRepresentation in project keycloak by keycloak.
the class SessionResource method getAttachedDevice.
private DeviceRepresentation getAttachedDevice(UserSessionModel s) {
DeviceRepresentation device = DeviceActivityManager.getCurrentDevice(s);
if (device == null) {
device = DeviceRepresentation.unknown();
device.setIpAddress(s.getIpAddress());
}
return device;
}
Aggregations