Skip to content

Commit

Permalink
fix(casa): SG Extension and FIDO2 extension #764
Browse files Browse the repository at this point in the history
  • Loading branch information
maduvena committed Feb 24, 2023
1 parent d77296a commit 6f1b942
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package org.gluu.casa.core.model;

import io.jans.as.model.fido.u2f.protocol.DeviceData;
import io.jans.orm.annotation.AttributeName;
import io.jans.orm.annotation.DataEntry;
import io.jans.orm.annotation.ObjectClass;
Expand All @@ -21,11 +21,28 @@ public class Fido2RegistrationEntry extends Entry {

@AttributeName(name = "jansId")
private String id;

@AttributeName(name = "jansApp")
private String application;

@JsonObject
@AttributeName(name = "jansRegistrationData" , ignoreDuringUpdate = true)
private Fido2RegistrationData registrationData;

@AttributeName(name = "jansCounter", ignoreDuringUpdate = true)
private int counter;

@JsonObject
@AttributeName(name = "jansDeviceData", ignoreDuringUpdate = true)
private DeviceData deviceData;


@JsonObject
@AttributeName(name = "jansStatus" , ignoreDuringUpdate = true)
private String registrationStatus;



public String getDisplayName() {
return displayName;
}
Expand Down Expand Up @@ -58,4 +75,38 @@ public void setRegistrationData(Fido2RegistrationData registrationData) {
this.registrationData = registrationData;
}

public int getCounter() {
return counter;
}

public void setCounter(int counter) {
this.counter = counter;
}

public String getRegistrationStatus() {
return registrationStatus;
}

public void setRegistrationStatus(String registrationStatus) {
this.registrationStatus = registrationStatus;
}

public DeviceData getDeviceData() {
return deviceData;
}

public void setDeviceData(DeviceData deviceData) {
this.deviceData = deviceData;
}

public String getApplication() {
return application;
}

public void setApplication(String application) {
this.application = application;
}



}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.gluu.casa.core.pojo;

import java.util.Date;

import io.jans.as.model.fido.u2f.protocol.DeviceData;
import org.gluu.casa.core.model.Fido2RegistrationEntry;

/**
* Represents a registered credential corresponding to a supergluu device
Expand All @@ -9,6 +12,17 @@ public class SuperGluuDevice extends FidoDevice {

private DeviceData deviceData;

public SuperGluuDevice(Fido2RegistrationEntry entry) {

super.setId( entry.getId());
super.setCounter( entry.getCounter());
super.setCreationDate( entry.getCreationDate());
//this.lastAccessTime = entry.get;
super.setStatus ( entry.getRegistrationStatus());
super.setApplication ( entry.getApplication());
deviceData = entry.getDeviceData();
}

public SuperGluuDevice() { }

public DeviceData getDeviceData() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public String getPageUrl() {
public List<BasicCredential> getEnrolledCreds(String id) {

try {
return fido2Service.getDevices(id, true).stream()
return fido2Service.getDevices(id, new java.net.URI(fido2Service.getScriptPropertyValue("fido2_server_uri")).getHost() , true).stream()
.map(dev -> new BasicCredential(dev.getNickName(), dev.getCreationDate().getTime())).collect(Collectors.toList());
} catch (Exception e) {
logger.error(e.getMessage(), e);
Expand All @@ -65,7 +65,13 @@ public List<BasicCredential> getEnrolledCreds(String id) {
}

public int getTotalUserCreds(String id) {
return fido2Service.getDevicesTotal(id, true);
try {
return fido2Service.getDevicesTotal(id,
new java.net.URI(fido2Service.getScriptPropertyValue("fido2_server_uri")).getHost(), true);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return 0;
}
}

public boolean mayBe2faActivationRequisite() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,22 @@

import net.jodah.expiringmap.ExpiringMap;

import org.gluu.casa.core.ConfigurationHandler;
import org.gluu.casa.core.PersistenceService;
import org.gluu.casa.core.UserService;
import org.gluu.casa.core.model.Person;
import org.gluu.casa.core.pojo.FidoDevice;
import org.gluu.casa.core.pojo.SuperGluuDevice;
import org.gluu.casa.misc.Utils;
import org.gluu.casa.misc.WebUtils;
import org.gluu.casa.plugins.authnmethod.SuperGluuExtension;
import org.gluu.casa.plugins.authnmethod.rs.status.sg.ComputeRequestCode;
import org.gluu.casa.plugins.authnmethod.rs.status.sg.EnrollmentStatusCode;
import org.gluu.casa.plugins.authnmethod.rs.status.u2f.FinishCode;
import org.gluu.casa.plugins.authnmethod.service.SGService;
import org.gluu.casa.rest.ProtectedApi;
import org.slf4j.Logger;
import java.util.UUID;

/**
* @author jgomer
Expand Down Expand Up @@ -79,9 +82,9 @@ public Response computeRequest(@QueryParam("remoteIP") String remoteIP,
result = ComputeRequestCode.UNKNOWN_USER_ID;
} else {
String userName = person.getUid();
String code = userService.generateRandEnrollmentCode(userId);
String code = WebUtils.getValueFromCookie("session_id");//userService.generateRandEnrollmentCode(userId);
usersWithRandEnrollmentCodes.put(userId, null);

String state = UUID.randomUUID().toString();
//key serves an identifier for clients to poll status afterwards
String key = UUID.randomUUID().toString();

Expand Down Expand Up @@ -121,7 +124,7 @@ public Response enrollmentReady(@QueryParam("key") String key) {
status = EnrollmentStatusCode.FAILED;
} else {

newDevice = sgService.getLatestSuperGluuDevice(userId, System.currentTimeMillis());
newDevice = sgService.getLatestSuperGluuDevice(userId, persistenceService.getCustScriptConfigProperties(ConfigurationHandler.DEFAULT_ACR).get("supergluu_app_id"));
if (newDevice == null) {
//Not ready yet (probably due to delayed push or user delayed to approve)
cacheProvider.put(MIN_CLIENT_POLL_PERIOD, BANNED_KEYS_PREFIX + queryParamKey, "");
Expand All @@ -136,7 +139,7 @@ public Response enrollmentReady(@QueryParam("key") String key) {
status = EnrollmentStatusCode.SUCCESS;
cacheProvider.put(EXPIRATION, RECENT_DEVICES_PREFIX + newDevice.getId(), userId);
} else {
sgService.removeDevice(newDevice);
sgService.removeDevice(newDevice, userId);
logger.info("Duplicated SuperGluu device {} has been removed", newDevice.getDeviceData().getUuid());
status = EnrollmentStatusCode.DUPLICATED;
}
Expand Down Expand Up @@ -179,7 +182,7 @@ public Response nameEnrollment(NamedCredential credential,
FidoDevice dev = getDeviceWithID(deviceId);
dev.setNickName(nickName);

if (sgService.updateDevice(dev)) {
if (sgService.updateDevice(dev, userId)) {
result = FinishCode.SUCCESS;
cacheProvider.remove(RECENT_DEVICES_PREFIX + deviceId);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,20 @@ public void reloadConfiguration() {

}

public int getDevicesTotal(String userId, boolean active) {
return getDevices(userId, active).size();
public int getDevicesTotal(String userId, String appId, boolean active) {
return getDevices(userId, appId, active).size();
}

public List<FidoDevice> getDevices(String userId, boolean active) {
public List<FidoDevice> getDevices(String userId, String appId, boolean active) {

//In CB the ou=fido2_register branch does not exist (not a hierarchical DB)
String state = active ? Fido2RegistrationStatus.registered.getValue() : Fido2RegistrationStatus.pending.getValue();
logger.trace("Finding Fido 2 devices with state={} for user={}", state, userId);
Filter filter = Filter.createANDFilter(
Filter.createEqualityFilter("jansStatus", state),
Filter.createEqualityFilter("personInum", userId));

Filter.createEqualityFilter("personInum", userId),
Filter.createEqualityFilter("jansApp", appId));

List<FidoDevice> devices = new ArrayList<>();
try {
List<Fido2RegistrationEntry> list = persistenceService.find(Fido2RegistrationEntry.class,
Expand All @@ -88,8 +89,10 @@ public List<FidoDevice> getDevices(String userId, boolean active) {
if (Optional.ofNullable(entry.getRegistrationData().getAttenstationRequest())
.map(ar -> ar.contains("platform")).orElse(false)) {
device = new PlatformAuthenticator();

} else {
device = new SecurityKey();

}
device.setId(entry.getId());
device.setCreationDate(entry.getCreationDate());
Expand Down Expand Up @@ -140,7 +143,7 @@ private Fido2RegistrationEntry getDeviceRegistrationFor(FidoDevice device) {
if (list.size() == 1) {
return list.get(0);
} else {
logger.warn("Search for fido 2 device registration with oxId {} returned {} results!", id, list.size());
logger.warn("Search for fido 2 device registration with jansId {} returned {} results!", id, list.size());
return null;
}

Expand Down Expand Up @@ -179,7 +182,7 @@ public FidoDevice getLatestSecurityKey(String userId, long time) {

FidoDevice sk = null;
try {
List<FidoDevice> list = getDevices(userId, true);
List<FidoDevice> list = getDevices(userId, getScriptPropertyValue("fido2_server_uri"), true);
sk = FidoService.getRecentlyCreatedDevice(list, time);
if (sk != null && sk.getNickName() != null) {
sk = null; //should have no name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import org.gluu.casa.conf.MainSettings;
import org.gluu.casa.core.model.DeviceRegistration;
import org.gluu.casa.core.model.Fido2RegistrationEntry;
import org.gluu.casa.core.pojo.FidoDevice;
import org.gluu.casa.core.pojo.SuperGluuDevice;
import org.slf4j.Logger;
Expand All @@ -29,12 +30,12 @@ public class FidoService extends BaseService {
@Inject
MainSettings settings;

private static final String U2F_OU = "fido";
private static final String U2F_OU = "fido2_register";

public boolean updateDevice(FidoDevice device) {
public boolean updateDevice(FidoDevice device, String userInum) {

boolean success = false;
DeviceRegistration deviceRegistration = getDeviceRegistrationFor(device);
Fido2RegistrationEntry deviceRegistration = getDeviceRegistrationFor(device, userInum);
if (deviceRegistration != null) {
deviceRegistration.setDisplayName(device.getNickName());
success = persistenceService.modify(deviceRegistration);
Expand All @@ -43,10 +44,10 @@ public boolean updateDevice(FidoDevice device) {

}

public boolean removeDevice(FidoDevice device) {
public boolean removeDevice(FidoDevice device, String userId) {

boolean success = false;
DeviceRegistration deviceRegistration = getDeviceRegistrationFor(device);
Fido2RegistrationEntry deviceRegistration = getDeviceRegistrationFor(device, userId);
if (deviceRegistration != null) {
success = persistenceService.delete(deviceRegistration);
}
Expand All @@ -64,29 +65,30 @@ public <T extends FidoDevice> T getLatestFidoDevice(String userId, long time, St
return getRecentlyCreatedDevice(list, time);
}

private DeviceRegistration getDeviceRegistrationFor(FidoDevice device) {
private Fido2RegistrationEntry getDeviceRegistrationFor(FidoDevice device, String userId) {

String id = device.getId();
DeviceRegistration deviceRegistration = new DeviceRegistration();
deviceRegistration.setBaseDn(persistenceService.getPeopleDn());
deviceRegistration.setJansId(id);

List<DeviceRegistration> list = persistenceService.find(deviceRegistration);
String parentDn = String.format("ou=%s,%s", U2F_OU, persistenceService.getPersonDn(userId));
Fido2RegistrationEntry deviceRegistration = new Fido2RegistrationEntry();
deviceRegistration.setBaseDn(parentDn);
deviceRegistration.setId(id);

List<Fido2RegistrationEntry> list = persistenceService.find(deviceRegistration);
if (list.size() == 1) {
return list.get(0);
} else {
logger.warn("Search for fido device registration with oxId {} returned {} results!", id, list.size());
logger.warn("Search for fido 2 device registration with jansId {} returned {} results!", id, list.size());
return null;
}

}

private List<DeviceRegistration> getRegistrations(String appId, String userId, boolean active) {
private List<Fido2RegistrationEntry> getRegistrations(String appId, String userId, boolean active) {

String parentDn = String.format("ou=%s,%s", U2F_OU, persistenceService.getPersonDn(userId));
logger.trace("Finding {}active U2F devices for user={}", active ? "" : "in", userId);

Filter statusFilter = Filter.createEqualityFilter("jansStatus", DeviceRegistrationStatus.ACTIVE.getValue());
//Filter statusFilter = Filter.createEqualityFilter("jansStatus", "");

//This filters allows to account old enrollments that don't have personInum set (they are LDAP-based)
Filter personInumFilter = Filter.createORFilter(
Expand All @@ -98,12 +100,12 @@ private List<DeviceRegistration> getRegistrations(String appId, String userId, b
//Starting with 4.1 in CB the ou=fido branch does not exist
//See https://github.com/GluuFederation/oxAuth/commit/7e5606e0ef51dfbea3a17ff3a2516f9e97f9b35a
Filter filter = Filter.createANDFilter(
active ? statusFilter : Filter.createNOTFilter(statusFilter),
// active ? statusFilter : Filter.createNOTFilter(statusFilter),
Filter.createEqualityFilter("jansApp", appId),
personInumFilter);

try {
return persistenceService.find(DeviceRegistration.class, parentDn, filter);
return persistenceService.find(Fido2RegistrationEntry.class, parentDn, filter);
} catch (Exception e) {
logger.warn(e.getMessage());
return Collections.emptyList();
Expand All @@ -123,22 +125,22 @@ private List<DeviceRegistration> getRegistrations(String appId, String userId, b
private <T extends FidoDevice> List<T> getDevices(String userId, boolean active, String oxApplication, Class<T> clazz) throws Exception {

List<T> devices = new ArrayList<>();
List<DeviceRegistration> list = getRegistrations(oxApplication, userId, active);
List<Fido2RegistrationEntry> list = getRegistrations(oxApplication, userId, active);

for (DeviceRegistration deviceRegistration : list) {
for (Fido2RegistrationEntry deviceRegistration : list) {
T device = clazz.getConstructor().newInstance();

if (clazz.equals(SuperGluuDevice.class)) {
DeviceData data = mapper.readValue(deviceRegistration.getDeviceData(), DeviceData.class);
((SuperGluuDevice) device).setDeviceData(data);
((SuperGluuDevice) device).setDeviceData(deviceRegistration.getDeviceData());
}
device.setApplication(deviceRegistration.getJansApp());
device.setApplication(deviceRegistration.getApplication());
device.setNickName(deviceRegistration.getDisplayName());
device.setStatus(deviceRegistration.getJansStatus());
device.setId(deviceRegistration.getJansId());
device.setStatus(deviceRegistration.getRegistrationStatus());
device.setId(deviceRegistration.getId());
device.setCreationDate(deviceRegistration.getCreationDate());
device.setCounter(deviceRegistration.getJansCounter());
device.setLastAccessTime(deviceRegistration.getLastAccessTime());
device.setCounter(deviceRegistration.getCounter());

//device.setLastAccessTime(deviceRegistration.getLastAccessTime());

devices.add(device);
}
Expand Down
Loading

0 comments on commit 6f1b942

Please sign in to comment.