mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Resolve Conflicts
This commit is contained in:
commit
92d7f5b61f
@ -25,6 +25,15 @@ public class Certificate {
|
||||
X509Certificate certificate;
|
||||
int tenantId;
|
||||
String tenantDomain;
|
||||
String deviceIdentifier;
|
||||
|
||||
public String getDeviceIdentifier() {
|
||||
return deviceIdentifier;
|
||||
}
|
||||
|
||||
public void setDeviceIdentifier(String deviceIdentifier) {
|
||||
this.deviceIdentifier = deviceIdentifier;
|
||||
}
|
||||
|
||||
public int getTenantId() {
|
||||
return tenantId;
|
||||
|
||||
@ -41,6 +41,17 @@ public interface CertificateDAO {
|
||||
void addCertificate(List<Certificate> certificate)
|
||||
throws CertificateManagementDAOException;
|
||||
|
||||
/**
|
||||
* This can be used to store a certificate in the database, where it will be stored against the serial number
|
||||
* of the certificate.
|
||||
*
|
||||
* @param certificate Holds the certificate and relevant details.
|
||||
* @throws CertificateManagementDAOException
|
||||
*
|
||||
*/
|
||||
void addCertificate(Certificate certificate)
|
||||
throws CertificateManagementDAOException;
|
||||
|
||||
/**
|
||||
* Usage is to obtain a certificate stored in the database by providing the common name.
|
||||
*
|
||||
@ -51,6 +62,16 @@ public interface CertificateDAO {
|
||||
*/
|
||||
CertificateResponse retrieveCertificate(String serialNumber) throws CertificateManagementDAOException;
|
||||
|
||||
/**
|
||||
* Obtain a certificated stored in the database by providing the common name and the tenant ID
|
||||
*
|
||||
* @param serialNumber Serial number (Common name) of the certificate
|
||||
* @param tenantId ID of the certificate owning tenant
|
||||
* @return representation of the certificate.
|
||||
* @throws CertificateManagementDAOException if fails to read the certificate from the database
|
||||
*/
|
||||
CertificateResponse retrieveCertificate(String serialNumber, int tenantId) throws CertificateManagementDAOException;
|
||||
|
||||
/**
|
||||
* Get all the certificates in a paginated manner.
|
||||
*
|
||||
|
||||
@ -81,6 +81,40 @@ public abstract class AbstractCertificateDAOImpl implements CertificateDAO{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCertificate(Certificate certificate)
|
||||
throws CertificateManagementDAOException {
|
||||
Connection conn;
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
conn = this.getConnection();
|
||||
stmt = conn.prepareStatement(
|
||||
"INSERT INTO DM_DEVICE_CERTIFICATE (SERIAL_NUMBER, CERTIFICATE, TENANT_ID," +
|
||||
" USERNAME, DEVICE_IDENTIFIER) VALUES (?,?,?,?,?)");
|
||||
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.
|
||||
getThreadLocalCarbonContext();
|
||||
String username = threadLocalCarbonContext.getUsername();
|
||||
// the serial number of the certificate used for its creation is set as its alias.
|
||||
String serialNumber = certificate.getSerial();
|
||||
if (serialNumber == null || serialNumber.isEmpty()) {
|
||||
serialNumber = String.valueOf(certificate.getCertificate().getSerialNumber());
|
||||
}
|
||||
byte[] bytes = Serializer.serialize(certificate.getCertificate());
|
||||
|
||||
stmt.setString(1, serialNumber);
|
||||
stmt.setBytes(2, bytes);
|
||||
stmt.setInt(3, certificate.getTenantId());
|
||||
stmt.setString(4, username);
|
||||
stmt.setString(5, certificate.getDeviceIdentifier());
|
||||
stmt.executeUpdate();
|
||||
} catch (SQLException | IOException e) {
|
||||
throw new CertificateManagementDAOException("Error occurred while saving the " +
|
||||
"certificate. ", e);
|
||||
} finally {
|
||||
CertificateManagementDAOUtil.cleanupResources(stmt, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CertificateResponse retrieveCertificate(String serialNumber)
|
||||
throws CertificateManagementDAOException {
|
||||
@ -119,6 +153,42 @@ public abstract class AbstractCertificateDAOImpl implements CertificateDAO{
|
||||
return certificateResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CertificateResponse retrieveCertificate(String serialNumber, int tenantId) throws CertificateManagementDAOException {
|
||||
Connection conn;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
CertificateResponse certificateResponse = null;
|
||||
try {
|
||||
conn = this.getConnection();
|
||||
String query =
|
||||
"SELECT CERTIFICATE, SERIAL_NUMBER, TENANT_ID, USERNAME FROM"
|
||||
+ " DM_DEVICE_CERTIFICATE WHERE SERIAL_NUMBER = ? AND TENANT_ID = ? ";
|
||||
stmt = conn.prepareStatement(query);
|
||||
stmt.setString(1, serialNumber);
|
||||
stmt.setInt(2, tenantId);
|
||||
resultSet = stmt.executeQuery();
|
||||
|
||||
if (resultSet.next()) {
|
||||
certificateResponse = new CertificateResponse();
|
||||
byte[] certificateBytes = resultSet.getBytes("CERTIFICATE");
|
||||
certificateResponse.setCertificate(certificateBytes);
|
||||
certificateResponse.setSerialNumber(resultSet.getString("SERIAL_NUMBER"));
|
||||
certificateResponse.setTenantId(resultSet.getInt("TENANT_ID"));
|
||||
certificateResponse.setUsername(resultSet.getString("USERNAME"));
|
||||
CertificateGenerator.extractCertificateDetails(certificateBytes, certificateResponse);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
String errorMsg =
|
||||
"Unable to get the read the certificate with serial" + serialNumber;
|
||||
log.error(errorMsg, e);
|
||||
throw new CertificateManagementDAOException(errorMsg, e);
|
||||
} finally {
|
||||
CertificateManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return certificateResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CertificateResponse> searchCertificate(String serialNumber)
|
||||
throws CertificateManagementDAOException {
|
||||
|
||||
@ -358,15 +358,31 @@ public class CertificateGenerator {
|
||||
CertificateResponse lookUpCertificate = null;
|
||||
KeyStoreReader keyStoreReader = new KeyStoreReader();
|
||||
if (distinguishedName != null && !distinguishedName.isEmpty()) {
|
||||
if (distinguishedName.contains("/CN=")) {
|
||||
String[] dnSplits = distinguishedName.split("/");
|
||||
if (distinguishedName.contains("CN=")) {
|
||||
String[] dnSplits = null;
|
||||
if (distinguishedName.contains("/")) {
|
||||
dnSplits = distinguishedName.split("/");
|
||||
} else if (distinguishedName.contains(",")) {
|
||||
//some older versions of nginx will forward the client certificate subject dn separated with commas
|
||||
dnSplits = distinguishedName.split(",");
|
||||
}
|
||||
String commonNameExtracted = null;
|
||||
int tenantId = 0;
|
||||
if (dnSplits != null && dnSplits.length >= 1) {
|
||||
for (String dnPart : dnSplits) {
|
||||
if (dnPart.contains("CN=")) {
|
||||
String commonNameExtracted = dnPart.replace("CN=", "");
|
||||
lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted);
|
||||
break;
|
||||
commonNameExtracted = dnPart.replace("CN=", "");
|
||||
} else if (dnPart.contains("OU=")) {
|
||||
//the OU of the certificate will be like OU=tenant_<TENANT_ID> ex: OU=tenant_-1234
|
||||
//splitting by underscore to extract the tenant domain
|
||||
String[] orgUnitSplits = dnPart.split("_");
|
||||
tenantId = Integer.parseInt(orgUnitSplits[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted, tenantId);
|
||||
|
||||
} else {
|
||||
LdapName ldapName;
|
||||
try {
|
||||
@ -694,6 +710,30 @@ public class CertificateGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
public void saveCertificate(io.entgra.device.mgt.core.certificate.mgt.core.bean.Certificate
|
||||
certificate) throws KeystoreException {
|
||||
|
||||
if (certificate == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
CertificateDAO certificateDAO = CertificateManagementDAOFactory.getCertificateDAO();
|
||||
CertificateManagementDAOFactory.beginTransaction();
|
||||
certificateDAO.addCertificate(certificate);
|
||||
CertificateManagementDAOFactory.commitTransaction();
|
||||
} catch (CertificateManagementDAOException e) {
|
||||
String errorMsg = "Error occurred when saving the generated certificate in database";
|
||||
log.error(errorMsg);
|
||||
CertificateManagementDAOFactory.rollbackTransaction();
|
||||
throw new KeystoreException(errorMsg, e);
|
||||
} catch (TransactionManagementException e) {
|
||||
String errorMsg = "Error occurred when saving the generated certificate in database";
|
||||
log.error(errorMsg);
|
||||
throw new KeystoreException(errorMsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveCertInKeyStore(List<io.entgra.device.mgt.core.certificate.mgt.core.bean.Certificate> certificate)
|
||||
throws KeystoreException {
|
||||
|
||||
|
||||
@ -275,6 +275,43 @@ public class KeyStoreReader {
|
||||
return raPrivateKey;
|
||||
}
|
||||
|
||||
public CertificateResponse getCertificateBySerial(String serialNumber, int tenantId) throws KeystoreException {
|
||||
CertificateResponse certificateResponse = null;
|
||||
try {
|
||||
CertificateCacheManager cacheManager = CertificateCacheManagerImpl.getInstance();
|
||||
certificateResponse = cacheManager.getCertificateBySerial(serialNumber);
|
||||
if (certificateResponse == null) {
|
||||
try {
|
||||
CertificateManagementDAOFactory.openConnection();
|
||||
certificateResponse = certDao.retrieveCertificate(serialNumber, tenantId);
|
||||
} catch (SQLException e) {
|
||||
String errorMsg = "Error when making a connection to the database.";
|
||||
throw new KeystoreException(errorMsg, e);
|
||||
} finally {
|
||||
CertificateManagementDAOFactory.closeConnection();
|
||||
}
|
||||
if (certificateResponse != null && certificateResponse.getCertificate() != null) {
|
||||
Certificate certificate = (Certificate) Serializer.deserialize(certificateResponse.getCertificate());
|
||||
if (certificate instanceof X509Certificate) {
|
||||
X509Certificate x509cert = (X509Certificate) certificate;
|
||||
String commonName = CertificateGenerator.getCommonName(x509cert);
|
||||
certificateResponse.setCommonName(commonName);
|
||||
cacheManager.addCertificateBySerial(serialNumber, certificateResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CertificateManagementDAOException e) {
|
||||
String errorMsg = "Error when retrieving certificate from the the database for the serial number: " +
|
||||
serialNumber;
|
||||
throw new KeystoreException(errorMsg, e);
|
||||
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
String errorMsg = "Error when de-serializing saved certificate.";
|
||||
throw new KeystoreException(errorMsg, e);
|
||||
}
|
||||
return certificateResponse;
|
||||
}
|
||||
|
||||
public CertificateResponse getCertificateBySerial(String serialNumber) throws KeystoreException {
|
||||
CertificateResponse certificateResponse = null;
|
||||
try {
|
||||
|
||||
@ -134,6 +134,8 @@ public final class DeviceManagementConstants {
|
||||
public static final String LAST_NAME = "last-name";
|
||||
public static final String TENANT_ADMIN_USERNAME = "tenant-admin-username";
|
||||
public static final String TENANT_ADMIN_PASSWORD = "tenant-admin-password";
|
||||
|
||||
public static final int OTP_DEFAULT_EXPIRY_SECONDS = 3600;
|
||||
}
|
||||
|
||||
public static final class EventServices {
|
||||
|
||||
@ -25,6 +25,7 @@ public class QREnrollmentDetails {
|
||||
String username;
|
||||
String enrollmentMode;
|
||||
Map<String, String> customValues;
|
||||
int tokenExpiry;
|
||||
|
||||
public Map<String, String> getCustomValues() {
|
||||
return customValues;
|
||||
@ -45,4 +46,12 @@ public class QREnrollmentDetails {
|
||||
public String getEnrollmentMode() { return enrollmentMode; }
|
||||
|
||||
public void setEnrollmentMode(String enrollmentMode) { this.enrollmentMode = enrollmentMode; }
|
||||
|
||||
public int getTokenExpiry() {
|
||||
return tokenExpiry;
|
||||
}
|
||||
|
||||
public void setTokenExpiry(int tokenExpiry) {
|
||||
this.tokenExpiry = tokenExpiry;
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,5 +19,5 @@
|
||||
package io.entgra.device.mgt.core.device.mgt.common.otp.mgt;
|
||||
|
||||
public enum OTPEmailTypes {
|
||||
USER_VERIFY, DEVICE_ENROLLMENT
|
||||
USER_VERIFY, DEVICE_ENROLLMENT, USER_INVITE, REMOTE_SESSION
|
||||
}
|
||||
|
||||
@ -35,7 +35,8 @@ public interface OTPManagementService {
|
||||
* @throws OTPManagementException if error occurred whle verifying validity of the OPT
|
||||
* @throws BadRequestException if found an null value for OTP
|
||||
*/
|
||||
OneTimePinDTO isValidOTP(String oneTimeToken) throws OTPManagementException, BadRequestException;
|
||||
OneTimePinDTO isValidOTP(String oneTimeToken, boolean requireRenewal) throws
|
||||
OTPManagementException, BadRequestException;
|
||||
|
||||
/**
|
||||
* Invalidate the OTP and send welcome mail
|
||||
@ -59,8 +60,7 @@ public interface OTPManagementService {
|
||||
boolean hasEmailRegistered(String email, String emailDomain) throws OTPManagementException,
|
||||
DeviceManagementException;
|
||||
|
||||
OneTimePinDTO generateOneTimePin(String email, String emailType, String userName, Object metaDataObj,
|
||||
int tenantId, boolean persistPin) throws OTPManagementException;
|
||||
OneTimePinDTO generateOneTimePin(OneTimePinDTO oneTimePinData, boolean persistPin) throws OTPManagementException;
|
||||
|
||||
OneTimePinDTO getRenewedOtpByEmailAndMailType(String email, String emailType) throws OTPManagementException;
|
||||
|
||||
|
||||
@ -156,7 +156,12 @@ public interface DeviceManagementConfigService {
|
||||
value = "The properties list using for query a device",
|
||||
required = true)
|
||||
@QueryParam("properties")
|
||||
String properties);
|
||||
String properties,
|
||||
@ApiParam(
|
||||
name = "withAccessToken",
|
||||
value = "Whether to use access token or otp token for device configuration")
|
||||
@QueryParam("withAccessToken")
|
||||
boolean withAccessToken);
|
||||
|
||||
@PUT
|
||||
@Path("/device/transfer")
|
||||
|
||||
@ -77,7 +77,8 @@ public class DeviceManagementConfigServiceImpl implements DeviceManagementConfig
|
||||
@Path("/configurations")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getConfiguration(@HeaderParam("token") String token,
|
||||
@QueryParam("properties") String properties) {
|
||||
@QueryParam("properties") String properties,
|
||||
@QueryParam("withAccessToken") boolean withAccessToken) {
|
||||
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
|
||||
try {
|
||||
if (token == null || token.isEmpty()) {
|
||||
@ -102,7 +103,8 @@ public class DeviceManagementConfigServiceImpl implements DeviceManagementConfig
|
||||
deviceProps.put("token", token);
|
||||
DeviceConfiguration devicesConfiguration =
|
||||
dms.getDeviceConfiguration(deviceProps);
|
||||
setAccessTokenToDeviceConfigurations(devicesConfiguration);
|
||||
if (withAccessToken) setAccessTokenToDeviceConfigurations(devicesConfiguration);
|
||||
else setOTPTokenToDeviceConfigurations(devicesConfiguration);
|
||||
return Response.status(Response.Status.OK).entity(devicesConfiguration).build();
|
||||
} catch (DeviceManagementException e) {
|
||||
String msg = "Error occurred while retrieving configurations";
|
||||
@ -214,6 +216,33 @@ public class DeviceManagementConfigServiceImpl implements DeviceManagementConfig
|
||||
}
|
||||
}
|
||||
|
||||
private void setOTPTokenToDeviceConfigurations(DeviceConfiguration deviceConfiguration)
|
||||
throws DeviceManagementException {
|
||||
OneTimePinDTO oneTimePinData = new OneTimePinDTO();
|
||||
oneTimePinData.setEmail(OTPEmailTypes.DEVICE_ENROLLMENT.toString());
|
||||
oneTimePinData.setEmailType(OTPEmailTypes.DEVICE_ENROLLMENT.toString());
|
||||
oneTimePinData.setUsername(deviceConfiguration.getDeviceOwner());
|
||||
PrivilegedCarbonContext.startTenantFlow();
|
||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
|
||||
deviceConfiguration.getTenantDomain(), true);
|
||||
oneTimePinData.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
|
||||
PrivilegedCarbonContext.endTenantFlow();
|
||||
OTPManagementService otpManagementService = DeviceMgtAPIUtils.getOtpManagementService();
|
||||
try {
|
||||
OneTimePinDTO oneTimePinDTO = otpManagementService.generateOneTimePin(oneTimePinData, true);
|
||||
if (oneTimePinDTO == null) {
|
||||
String msg = "Null value returned when generating OTP token for " + oneTimePinData.getOtpToken();
|
||||
log.error(msg);
|
||||
throw new DeviceManagementException(msg);
|
||||
}
|
||||
deviceConfiguration.setAccessToken(oneTimePinDTO.getOtpToken());
|
||||
} catch (OTPManagementException ex) {
|
||||
String msg = "Error occurred while generating one time pin: " + ex.getMessage();
|
||||
log.error(msg, ex);
|
||||
throw new DeviceManagementException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Path("/tenants")
|
||||
@GET
|
||||
|
||||
@ -21,6 +21,7 @@ package io.entgra.device.mgt.core.device.mgt.config.api.util;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.spi.OTPManagementService;
|
||||
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
|
||||
import org.wso2.carbon.user.core.service.RealmService;
|
||||
|
||||
@ -34,6 +35,8 @@ public class DeviceMgtAPIUtils {
|
||||
private static DeviceManagementProviderService deviceManagementProviderService = null;
|
||||
private static RealmService realmService = null;
|
||||
|
||||
private static OTPManagementService otpManagementService = null;
|
||||
|
||||
public static DeviceManagementProviderService getDeviceManagementService() {
|
||||
if (deviceManagementProviderService == null) {
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
@ -48,6 +51,19 @@ public class DeviceMgtAPIUtils {
|
||||
return deviceManagementProviderService;
|
||||
}
|
||||
|
||||
public static OTPManagementService getOtpManagementService() {
|
||||
if (otpManagementService == null) {
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
otpManagementService = (OTPManagementService) ctx.getOSGiService(OTPManagementService.class, null);
|
||||
if (otpManagementService == null) {
|
||||
String msg = "OTP Management Service has not initialized.";
|
||||
log.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
}
|
||||
return otpManagementService;
|
||||
}
|
||||
|
||||
public static RealmService getRealmService() {
|
||||
if (realmService == null) {
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
|
||||
@ -56,7 +56,8 @@ public class GenericOTPManagementDAOImpl extends AbstractDAOImpl implements OTPM
|
||||
+ "META_INFO, "
|
||||
+ "CREATED_AT,"
|
||||
+ "TENANT_ID,"
|
||||
+ "USERNAME) VALUES (?, ?, ?, ?, ?, ?, ?)";
|
||||
+ "USERNAME, "
|
||||
+ "EXPIRY_TIME) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
try {
|
||||
Connection conn = this.getDBConnection();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
@ -70,6 +71,8 @@ public class GenericOTPManagementDAOImpl extends AbstractDAOImpl implements OTPM
|
||||
stmt.setTimestamp(5, timestamp);
|
||||
stmt.setInt(6, oneTimePinDTO.getTenantId());
|
||||
stmt.setString(7, oneTimePinDTO.getUsername());
|
||||
stmt.setInt(8, oneTimePinDTO.getExpiryTime() == 0
|
||||
? DeviceManagementConstants.OTPProperties.OTP_DEFAULT_EXPIRY_SECONDS : oneTimePinDTO.getExpiryTime());
|
||||
stmt.addBatch();
|
||||
}
|
||||
stmt.executeBatch();
|
||||
|
||||
@ -127,7 +127,8 @@ public class OTPManagementServiceImpl implements OTPManagementService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public OneTimePinDTO isValidOTP(String oneTimeToken) throws OTPManagementException, BadRequestException {
|
||||
public OneTimePinDTO isValidOTP(String oneTimeToken, boolean requireRenewal) throws OTPManagementException,
|
||||
BadRequestException {
|
||||
if (StringUtils.isBlank(oneTimeToken)){
|
||||
String msg = "Received blank OTP to verify. OTP: " + oneTimeToken;
|
||||
log.error(msg);
|
||||
@ -151,6 +152,7 @@ public class OTPManagementServiceImpl implements OTPManagementService {
|
||||
oneTimePinDTO.getCreatedAt().getTime() + oneTimePinDTO.getExpiryTime() * 1000L);
|
||||
|
||||
if (currentTimestamp.after(expiredTimestamp)) {
|
||||
if (requireRenewal) {
|
||||
String renewedOTP = UUID.randomUUID().toString();
|
||||
renewOTP(oneTimePinDTO, renewedOTP);
|
||||
Gson gson = new Gson();
|
||||
@ -162,6 +164,7 @@ public class OTPManagementServiceImpl implements OTPManagementService {
|
||||
props.setProperty("email", oneTimePinDTO.getEmail());
|
||||
props.setProperty("type", oneTimePinDTO.getEmailType());
|
||||
sendMail(props, oneTimePinDTO.getEmail(), DeviceManagementConstants.EmailAttributes.USER_VERIFY_TEMPLATE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return oneTimePinDTO;
|
||||
@ -244,8 +247,14 @@ public class OTPManagementServiceImpl implements OTPManagementService {
|
||||
for (String username : deviceEnrollmentInvitation.getUsernames()) {
|
||||
String emailAddress = DeviceManagerUtil.getUserClaimValue(
|
||||
username, DeviceManagementConstants.User.CLAIM_EMAIL_ADDRESS);
|
||||
oneTimePinDTO = generateOneTimePin(emailAddress, OTPEmailTypes.DEVICE_ENROLLMENT.toString(), username,
|
||||
null, tenantId, false);
|
||||
|
||||
OneTimePinDTO oneTimePinData = new OneTimePinDTO();
|
||||
oneTimePinData.setEmail(emailAddress);
|
||||
oneTimePinData.setTenantId(tenantId);
|
||||
oneTimePinData.setUsername(username);
|
||||
oneTimePinData.setEmailType(OTPEmailTypes.USER_INVITE.toString());
|
||||
|
||||
oneTimePinDTO = generateOneTimePin(oneTimePinData, false);
|
||||
oneTimePinDTOList.add(oneTimePinDTO);
|
||||
props.setProperty("first-name", DeviceManagerUtil.
|
||||
getUserClaimValue(username, DeviceManagementConstants.User.CLAIM_FIRST_NAME));
|
||||
@ -279,27 +288,17 @@ public class OTPManagementServiceImpl implements OTPManagementService {
|
||||
|
||||
/**
|
||||
* Create One Time Token
|
||||
* @param email email
|
||||
* @param emailType email type
|
||||
* @param userName username
|
||||
* @param metaDataObj meta data object
|
||||
* @param tenantId tenant Id
|
||||
* @param oneTimePinDTO Data related to the one time pin
|
||||
* @return {@link OneTimePinDTO}
|
||||
*/
|
||||
@Override
|
||||
public OneTimePinDTO generateOneTimePin(String email, String emailType, String userName, Object metaDataObj,
|
||||
int tenantId, boolean persistPin) throws OTPManagementException {
|
||||
public OneTimePinDTO generateOneTimePin(OneTimePinDTO oneTimePinDTO, boolean persistPin) throws OTPManagementException {
|
||||
|
||||
String otpValue = UUID.randomUUID().toString();
|
||||
|
||||
Gson gson = new Gson();
|
||||
String metaInfo = gson.toJson(metaDataObj);
|
||||
String metaInfo = gson.toJson(oneTimePinDTO.getMetaInfo());
|
||||
|
||||
OneTimePinDTO oneTimePinDTO = new OneTimePinDTO();
|
||||
oneTimePinDTO.setEmail(email);
|
||||
oneTimePinDTO.setTenantId(tenantId);
|
||||
oneTimePinDTO.setUsername(userName);
|
||||
oneTimePinDTO.setEmailType(emailType);
|
||||
oneTimePinDTO.setMetaInfo(metaInfo);
|
||||
oneTimePinDTO.setOtpToken(otpValue);
|
||||
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
package io.entgra.device.mgt.core.ui.request.interceptor;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.entgra.device.mgt.core.ui.request.interceptor.beans.AuthData;
|
||||
@ -28,12 +27,17 @@ import io.entgra.device.mgt.core.ui.request.interceptor.util.HandlerUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import io.entgra.device.mgt.core.ui.request.interceptor.beans.ProxyResponse;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.DeviceManagementConstants;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.exceptions.OTPManagementException;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.otp.mgt.OTPEmailTypes;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.otp.mgt.dto.OneTimePinDTO;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.spi.OTPManagementService;
|
||||
import org.wso2.carbon.user.api.UserStoreException;
|
||||
import org.wso2.carbon.user.core.service.RealmService;
|
||||
|
||||
import javax.servlet.annotation.MultipartConfig;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
@ -55,71 +59,28 @@ public class DefaultTokenHandler extends HttpServlet {
|
||||
HttpSession httpSession = req.getSession(false);
|
||||
|
||||
if (httpSession != null) {
|
||||
AuthData authData = (AuthData) httpSession.getAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY);
|
||||
if (authData == null) {
|
||||
HandlerUtil.sendUnAuthorizeResponse(resp);
|
||||
return;
|
||||
String userWithDomain = (String) httpSession.getAttribute(HandlerConstants.USERNAME_WITH_DOMAIN);
|
||||
String[] userNameParts = userWithDomain.split("@");
|
||||
|
||||
OneTimePinDTO oneTimePinData = new OneTimePinDTO();
|
||||
oneTimePinData.setEmail(OTPEmailTypes.REMOTE_SESSION.toString());
|
||||
oneTimePinData.setEmailType(OTPEmailTypes.REMOTE_SESSION.toString());
|
||||
oneTimePinData.setUsername(userNameParts[0]);
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
RealmService realmService = (RealmService) ctx.getOSGiService(RealmService.class, null);
|
||||
try {
|
||||
oneTimePinData.setTenantId(realmService.getTenantManager().getTenantId(userNameParts[1]));
|
||||
} catch (UserStoreException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
AuthData defaultAuthData = (AuthData) httpSession
|
||||
.getAttribute(HandlerConstants.SESSION_DEFAULT_AUTH_DATA_KEY);
|
||||
if (defaultAuthData != null) {
|
||||
HandlerUtil.handleSuccess(resp, constructSuccessProxyResponse(defaultAuthData.getAccessToken()));
|
||||
return;
|
||||
}
|
||||
|
||||
String clientId = authData.getClientId();
|
||||
String clientSecret = authData.getClientSecret();
|
||||
|
||||
String queryString = req.getQueryString();
|
||||
String scopeString = "";
|
||||
if (StringUtils.isNotEmpty(queryString)) {
|
||||
scopeString = req.getParameter("scopes");
|
||||
if (scopeString != null) {
|
||||
scopeString = "?scopes=" + scopeString;
|
||||
}
|
||||
}
|
||||
|
||||
String iotsCoreUrl = req.getScheme() + HandlerConstants.SCHEME_SEPARATOR
|
||||
+ System.getProperty(HandlerConstants.IOT_GW_HOST_ENV_VAR)
|
||||
+ HandlerConstants.COLON + HandlerUtil.getGatewayPort(req.getScheme());
|
||||
String tokenUrl = iotsCoreUrl + "/api/device-mgt/v1.0/devices/" + clientId
|
||||
+ "/" + clientSecret + "/default-token" + scopeString;
|
||||
|
||||
HttpGet defaultTokenRequest = new HttpGet(tokenUrl);
|
||||
defaultTokenRequest
|
||||
.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken());
|
||||
defaultTokenRequest
|
||||
.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString());
|
||||
ProxyResponse tokenResultResponse = HandlerUtil.execute(defaultTokenRequest);
|
||||
|
||||
if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
|
||||
log.error("Error occurred while invoking the API to get default token data.");
|
||||
HandlerUtil.handleError(resp, tokenResultResponse);
|
||||
return;
|
||||
}
|
||||
String tokenResult = tokenResultResponse.getData();
|
||||
if (tokenResult == null) {
|
||||
log.error("Invalid default token response is received.");
|
||||
HandlerUtil.handleError(resp, tokenResultResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
JsonParser jsonParser = new JsonParser();
|
||||
JsonElement jTokenResult = jsonParser.parse(tokenResult);
|
||||
if (jTokenResult.isJsonObject()) {
|
||||
JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject();
|
||||
AuthData newDefaultAuthData = new AuthData();
|
||||
newDefaultAuthData.setClientId(clientId);
|
||||
newDefaultAuthData.setClientSecret(clientSecret);
|
||||
|
||||
String defaultToken = jTokenResultAsJsonObject.get("accessToken").getAsString();
|
||||
newDefaultAuthData.setAccessToken(defaultToken);
|
||||
newDefaultAuthData.setRefreshToken(jTokenResultAsJsonObject.get("refreshToken").getAsString());
|
||||
newDefaultAuthData.setScope(jTokenResultAsJsonObject.get("scopes").getAsString());
|
||||
httpSession.setAttribute(HandlerConstants.SESSION_DEFAULT_AUTH_DATA_KEY, newDefaultAuthData);
|
||||
|
||||
HandlerUtil.handleSuccess(resp, constructSuccessProxyResponse(defaultToken));
|
||||
oneTimePinData.setExpiryTime(DeviceManagementConstants.OTPProperties.OTP_DEFAULT_EXPIRY_SECONDS);
|
||||
OTPManagementService otpManagementService = HandlerUtil.getOTPManagementService();
|
||||
try {
|
||||
oneTimePinData = otpManagementService.generateOneTimePin(oneTimePinData, true);
|
||||
HandlerUtil.handleSuccess(resp, constructSuccessProxyResponse(oneTimePinData.getOtpToken()));
|
||||
} catch (OTPManagementException e) {
|
||||
log.error("Failed while generating remote session OTP for user " + userWithDomain, e);
|
||||
HandlerUtil.handleError(resp, HttpStatus.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
} else {
|
||||
HandlerUtil.sendUnAuthorizeResponse(resp);
|
||||
|
||||
@ -120,6 +120,7 @@ public class UserHandler extends HttpServlet {
|
||||
proxyResponse.setData(
|
||||
jTokenResultAsJsonObject.get("username").getAsString().replaceAll("@carbon.super", ""));
|
||||
HandlerUtil.handleSuccess(resp, proxyResponse);
|
||||
httpSession.setAttribute(HandlerConstants.USERNAME_WITH_DOMAIN, jTokenResultAsJsonObject.get("username").getAsString());
|
||||
log.info("Customer login", userLogContextBuilder.setUserName(proxyResponse.getData()).setUserRegistered(true).build());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
@ -106,4 +106,5 @@ public class HandlerConstants {
|
||||
public static final String IOT_REPORTING_WEBAPP_HOST_ENV_VAR = "iot.reporting.webapp.host";
|
||||
public static final String USER_SCOPES = "userScopes";
|
||||
public static final String HUBSPOT_CHAT_URL = "api.hubapi.com";
|
||||
public static final String USERNAME_WITH_DOMAIN = "usernameWithDomain";
|
||||
}
|
||||
|
||||
@ -55,6 +55,8 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.w3c.dom.Document;
|
||||
import io.entgra.device.mgt.core.ui.request.interceptor.beans.ProxyResponse;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.spi.OTPManagementService;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -79,6 +81,8 @@ public class HandlerUtil {
|
||||
private static boolean isLoginCacheInitialized = false;
|
||||
private static AuthData authData;
|
||||
|
||||
private static OTPManagementService otpManagementService;
|
||||
|
||||
/***
|
||||
*
|
||||
* @param httpRequest - httpMethod e.g:- HttpPost, HttpGet
|
||||
@ -751,4 +755,12 @@ public class HandlerUtil {
|
||||
public static boolean isPropertyDefined(String property) {
|
||||
return StringUtils.isEmpty(System.getProperty(property));
|
||||
}
|
||||
|
||||
public static OTPManagementService getOTPManagementService() {
|
||||
if (otpManagementService == null) {
|
||||
otpManagementService = (OTPManagementService) PrivilegedCarbonContext
|
||||
.getThreadLocalCarbonContext().getOSGiService(OTPManagementService.class, null);
|
||||
}
|
||||
return otpManagementService;
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ import io.entgra.device.mgt.core.webapp.authenticator.framework.Utils.Utils;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Base64;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class BasicAuthAuthenticator implements WebappAuthenticator {
|
||||
|
||||
@ -50,16 +51,24 @@ public class BasicAuthAuthenticator implements WebappAuthenticator {
|
||||
@Override
|
||||
public boolean canHandle(Request request) {
|
||||
/*
|
||||
This is done to avoid every endpoint being able to use basic auth. Add the following to
|
||||
the required web.xml of the web app.
|
||||
This is done to avoid every web app being able to use basic auth. Add the following to
|
||||
the required web.xml of the web app. This is a global config for a web app to allow all
|
||||
contexts of the web app to use basic auth
|
||||
<context-param>
|
||||
<param-name>basicAuth</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
Adding the basicAuthAllowList parameter allows to selectively allow some context paths in a
|
||||
web app to use basic auth while all the other context remain unavailable with basic auth.
|
||||
If this parameter is present, any context that requires basic auth must be specially
|
||||
added as comma separated list to the param-value of basicAuthAllowList.
|
||||
*/
|
||||
if (!isAllowListedForBasicAuth(request)) {
|
||||
if (!isAuthenticationSupported(request)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (request.getCoyoteRequest() == null || request.getCoyoteRequest().getMimeHeaders() == null) {
|
||||
return false;
|
||||
}
|
||||
@ -75,6 +84,20 @@ public class BasicAuthAuthenticator implements WebappAuthenticator {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAllowListedForBasicAuth(Request request) {
|
||||
String param = request.getContext().findParameter("basicAuthAllowList");
|
||||
if (param != null && !param.isEmpty()) {
|
||||
//Add the nonSecured end-points to cache
|
||||
String[] basicAuthAllowList = param.split(",");
|
||||
for (String contexPath : basicAuthAllowList) {
|
||||
if (request.getRequestURI().toString().endsWith(contexPath.trim())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationInfo authenticate(Request request, Response response) {
|
||||
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||
|
||||
@ -74,9 +74,17 @@ public class CertificateAuthenticator implements WebappAuthenticator {
|
||||
// When there is a load balancer terminating mutual SSL, it should pass this header along and
|
||||
// as the value of this header, the client certificate subject dn should be passed.
|
||||
if (request.getHeader(PROXY_MUTUAL_AUTH_HEADER) != null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("PROXY_MUTUAL_AUTH_HEADER " + request.getHeader(PROXY_MUTUAL_AUTH_HEADER));
|
||||
}
|
||||
CertificateResponse certificateResponse = AuthenticatorFrameworkDataHolder.getInstance().
|
||||
getCertificateManagementService().verifySubjectDN(request.getHeader(PROXY_MUTUAL_AUTH_HEADER));
|
||||
authenticationInfo = checkCertificateResponse(certificateResponse);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Certificate Serial : " + certificateResponse.getSerialNumber()
|
||||
+ ", CN : " + certificateResponse.getCommonName()
|
||||
+ " , username" + authenticationInfo.getUsername());
|
||||
}
|
||||
}
|
||||
else if (request.getHeader(MUTUAL_AUTH_HEADER) != null) {
|
||||
Object object = request.getAttribute(CLIENT_CERTIFICATE_ATTRIBUTE);
|
||||
@ -89,7 +97,6 @@ public class CertificateAuthenticator implements WebappAuthenticator {
|
||||
CertificateResponse certificateResponse = AuthenticatorFrameworkDataHolder.getInstance().
|
||||
getCertificateManagementService().verifyPEMSignature(clientCertificate[0]);
|
||||
authenticationInfo = checkCertificateResponse(certificateResponse);
|
||||
|
||||
} else {
|
||||
authenticationInfo.setStatus(Status.FAILURE);
|
||||
authenticationInfo.setMessage("No client certificate is present");
|
||||
|
||||
@ -49,8 +49,18 @@ public class OneTimeTokenAuthenticator implements WebappAuthenticator {
|
||||
try {
|
||||
OTPManagementService otpManagementService = AuthenticatorFrameworkDataHolder.getInstance()
|
||||
.getOtpManagementService();
|
||||
OneTimePinDTO validOTP = otpManagementService.isValidOTP(request.getHeader(Constants.HTTPHeaders
|
||||
.ONE_TIME_TOKEN_HEADER));
|
||||
OneTimePinDTO validOTP;
|
||||
if (request.getRequestURI().toString().endsWith("cloud/download-url")
|
||||
|| request.getRequestURI().toString().endsWith("cloud/tenant")) {
|
||||
validOTP = otpManagementService.isValidOTP(request.getHeader(Constants.HTTPHeaders
|
||||
.ONE_TIME_TOKEN_HEADER), true);
|
||||
} else {
|
||||
log.info("Validating OTP for enrollments PIN: " + request.getHeader(Constants
|
||||
.HTTPHeaders.ONE_TIME_TOKEN_HEADER));
|
||||
validOTP = otpManagementService.isValidOTP(request.getHeader(Constants.HTTPHeaders
|
||||
.ONE_TIME_TOKEN_HEADER), false);
|
||||
}
|
||||
|
||||
if (validOTP != null) {
|
||||
authenticationInfo.setStatus(Status.CONTINUE);
|
||||
authenticationInfo.setTenantId(validOTP.getTenantId());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user