RegisterDeviceFlow.java
/*
* Copyright (C) 2020-2024 by Savoir-faire Linux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.jami.jams.server.core.workflows;
import static net.jami.jams.authmodule.UserAuthenticationModule.datastore;
import static net.jami.jams.server.Server.certificateAuthority;
import static net.jami.jams.server.Server.dataStore;
import static net.jami.jams.server.Server.nameServer;
import static net.jami.jams.server.Server.userAuthenticationModule;
import lombok.extern.slf4j.Slf4j;
import net.jami.jams.authmodule.UserAuthenticationModule;
import net.jami.jams.common.authmodule.AuthModuleKey;
import net.jami.jams.common.objects.devices.Device;
import net.jami.jams.common.objects.requests.DeviceRegistrationRequest;
import net.jami.jams.common.objects.responses.DeviceRegistrationResponse;
import net.jami.jams.common.objects.user.User;
import net.jami.jams.common.objects.user.UserProfile;
import net.jami.jams.dht.DeviceReceiptGenerator;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Optional;
@Slf4j
public class RegisterDeviceFlow {
public static DeviceRegistrationResponse registerDevice(
String username, DeviceRegistrationRequest registrationRequest) {
try {
User user = dataStore.getUserDao().getByUsername(username).orElseThrow();
UserProfile userProfile =
userAuthenticationModule
.getAuthSources()
.get(new AuthModuleKey(user.getRealm(), user.getUserType()))
.searchUserProfiles(username, "LOGON_NAME", Optional.empty())
.get(0);
// Renew user certificate if expired with same private key
if (!user.getCertificate().getNotAfter().after(new Date())) {
user = UserAuthenticationModule.certificateAuthority.getRefreshedCertificate(user);
datastore.updateUserCertificate(user);
}
Device device = new Device();
device.setCertificationRequest(registrationRequest.getCsr());
device.setOwner(username);
device.setDisplayName(registrationRequest.getDeviceName());
device = certificateAuthority.getSignedCertificate(user, device);
if (device == null) {
log.error("An error occurred while creating the device certificate.");
return null;
}
device.setDeviceId(DeviceReceiptGenerator.generateDeviceId(device));
dataStore.getDeviceDao().storeObject(device);
DeviceRegistrationResponse response = new DeviceRegistrationResponse();
String policyData = getPolicyData(username);
if (policyData != null) {
response.setPolicyData(policyData);
}
// Device receipt
String[] devReceipt =
DeviceReceiptGenerator.generateReceipt(
user.getPrivateKey(),
user.getCertificate().getPublicKey(),
device.getCertificate().getPublicKey(),
user.getEthAddress());
response.setDeviceReceipt(devReceipt[0]);
response.setReceiptSignature(devReceipt[1]);
response.setDisplayName(userProfile.getFirstName() + " " + userProfile.getLastName());
response.setNameServer(nameServer.getURI());
if (userProfile.getProfilePicture() != null)
response.setUserPhoto(userProfile.getProfilePicture());
// Chain certificate
response.setCertificateChain(
new X509Certificate[] {
certificateAuthority.getCA(), user.getCertificate(), device.getCertificate()
});
return response;
} catch (Exception e) {
log.error("An error occurred while enrolling the device.");
e.printStackTrace();
return null;
}
}
public static String getPolicyData(String username) {
String policy =
dataStore
.getPolicyDao()
.getByUsername(username)
.map(p -> p.getPolicyData())
.orElse(null);
if (policy == null) {
log.warn("No policy available for user - not adding a policy component to response");
}
return policy;
}
}