From 0d48f9d38c4bb3657d9f3ff124ea8433bb2be7c0 Mon Sep 17 00:00:00 2001 From: "tcdlpds@gmail.com" Date: Thu, 30 Jul 2020 03:06:57 +0530 Subject: [PATCH] Improve One Time Token Authenticator --- .../handlers/AuthenticationHandler.java | 11 +--- .../DeviceManagementConfigServiceImpl.java | 2 - .../src/main/webapp/WEB-INF/web.xml | 2 +- .../mgt/common/spi/OTPManagementService.java | 2 + .../core/otp/mgt/dao/OTPManagementDAO.java | 10 +++ .../dao/impl/GenericOTPManagementDAOImpl.java | 61 +++++++++++++++++++ .../mgt/service/OTPManagementServiceImpl.java | 55 +++++++++++++++++ .../DeviceManagementProviderService.java | 1 - .../OneTimeTokenAuthenticator.java | 16 ++--- .../AuthenticatorFrameworkDataHolder.java | 13 ++-- ...uthenticatorFrameworkServiceComponent.java | 24 ++++---- 11 files changed, 153 insertions(+), 44 deletions(-) diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java index 415ec063049..464dfc248d8 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java @@ -182,15 +182,6 @@ public class AuthenticationHandler extends AbstractHandler { if (log.isDebugEnabled()) { log.debug("Verify response:" + response.getContent()); } - } else if (headers.containsKey(AuthConstants.ONE_TIME_TOKEN_HEADER)) { - String token = headers.get(AuthConstants.ONE_TIME_TOKEN_HEADER); - //TODO: validate token service. Since this is getting validated in the valve, - // this may not even be necessery -// if (log.isDebugEnabled()) { -// log.debug("One time time :" + token + ", status : " + ); -// } - return true; - } else { log.warn("Unauthorized request for api: " + ctxPath); return false; @@ -241,4 +232,4 @@ public class AuthenticationHandler extends AbstractHandler { map.put(CONTENT_TYPE, "application/json"); return map; } -} \ No newline at end of file +} diff --git a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java index bb1a04bba74..25415776983 100644 --- a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java +++ b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java @@ -56,14 +56,12 @@ import org.wso2.carbon.user.api.Tenant; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.service.RealmService; -import javax.validation.constraints.Size; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml index 4d7c9c915f0..d24eeb72b37 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml @@ -49,7 +49,7 @@ nonSecuredEndPoints /api/device-mgt/v1.0/users/validate, - /api/device-mgt/v1.0/users/one-time-pin, + /api/device-mgt/v1.0/users/one-time-pin diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/OTPManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/OTPManagementService.java index a8d57379634..24ec41d2291 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/OTPManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/OTPManagementService.java @@ -31,4 +31,6 @@ public interface OTPManagementService { * @throws BadRequestException if found and incompatible payload to create OTP token. */ String createOTPToken (OTPMailWrapper otpMailWrapper) throws OTPManagementException, BadRequestException; + + boolean isValidOTP(String oneTimeToken) throws OTPManagementException, BadRequestException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAO.java index 5d92d435c84..64288ced22a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAO.java @@ -29,4 +29,14 @@ public interface OTPManagementDAO { * @throws OTPManagementDAOException if error occurred whule storing data */ int addOTPData(OTPMailDTO otpMailDTO) throws OTPManagementDAOException; + + /** + * Get OTP data for requesting One Time Token + * @param oneTimeToken One Time Token + * @return {@link OTPMailDTO} + * @throws OTPManagementDAOException if error ocured while getting OTP data for requesting one time token + */ + OTPMailDTO getOTPDataByToken (String oneTimeToken) throws OTPManagementDAOException; + + void ExpireOneTimeToken (String oneTimeToken); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/GenericOTPManagementDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/GenericOTPManagementDAOImpl.java index 9149a7450b3..b8ec791faf8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/GenericOTPManagementDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/GenericOTPManagementDAOImpl.java @@ -82,4 +82,65 @@ public class GenericOTPManagementDAOImpl extends AbstractDAOImpl implements OTPM throw new OTPManagementDAOException(msg, e); } } + + @Override + public OTPMailDTO getOTPDataByToken (String oneTimeToken) throws OTPManagementDAOException { + + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get an OTP data entry for OTP"); + log.debug("OTP Details : OTP key : " + oneTimeToken ); + } + + String sql = "SELECT " + + "ID, " + + "OTP_TOKEN, " + + "TENANT_DOMAIN," + + "EMAIL, " + + "EMAIL_TYPE, " + + "META_INFO, " + + "CREATED_AT, " + + "EXPIRY_TIME, " + + "IS_EXPIRED, " + + "TENANT_CREATED FROM DM_OTP_DATA " + + "WHERE OTP_TOKEN = ?"; + + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, oneTimeToken); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + OTPMailDTO otpMailDTO = new OTPMailDTO(); + otpMailDTO.setId(rs.getInt("ID")); + otpMailDTO.setOtpToken(rs.getString("OTP_TOKEN")); + otpMailDTO.setTenantDomain(rs.getString("TENANT_DOMAIN")); + otpMailDTO.setEmail(rs.getString("EMAIL")); + otpMailDTO.setEmailType(rs.getString("EMAIL_TYPE")); + otpMailDTO.setMetaInfo(rs.getString("META_INFO")); + otpMailDTO.setCreatedAt(rs.getTimestamp("CREATED_AT")); + otpMailDTO.setExpiryTime(rs.getInt("EXPIRY_TIME")); + otpMailDTO.setExpired(rs.getBoolean("IS_EXPIRED")); + otpMailDTO.setTenantCreated(rs.getBoolean("TENANT_CREATED")); + return otpMailDTO; + } + return null; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get OPT data for given OTP. OTP: " + + oneTimeToken; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to get OTP data for OTP. One time token: " + oneTimeToken; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } + } + + @Override + public void ExpireOneTimeToken (String oneTimeToken) { + + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/service/OTPManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/service/OTPManagementServiceImpl.java index 16c21396a82..464c2da922e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/service/OTPManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/service/OTPManagementServiceImpl.java @@ -32,6 +32,9 @@ import org.wso2.carbon.device.mgt.core.otp.mgt.dao.OTPManagementDAOFactory; import org.wso2.carbon.device.mgt.core.otp.mgt.exception.OTPManagementDAOException; import org.wso2.carbon.device.mgt.core.otp.mgt.util.ConnectionManagerUtil; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; import java.util.UUID; public class OTPManagementServiceImpl implements OTPManagementService { @@ -90,6 +93,58 @@ public class OTPManagementServiceImpl implements OTPManagementService { String msg = "Error occurred while saving the OTP data. Email address: " + otpMailDTO.getEmail(); log.error(msg, e); throw new OTPManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public boolean isValidOTP(String oneTimeToken) throws OTPManagementException, BadRequestException { + OTPMailDTO otpMailDTO = getOTPDataByToken(oneTimeToken); + if (otpMailDTO == null) { + String msg = "Couldn't found OTP data for the requesting OTP " + oneTimeToken + " In the system."; + log.error(msg); + throw new BadRequestException(msg); + } + + if (otpMailDTO.isExpired()) { + return false; + } + + Calendar calendar = Calendar.getInstance(); + Timestamp currentTimestamp = new Timestamp(calendar.getTime().getTime()); + Timestamp expiredTimestamp = new Timestamp( + otpMailDTO.getCreatedAt().getTime() + otpMailDTO.getExpiryTime() * 1000); + + if (currentTimestamp.after(expiredTimestamp)) { + //todo update the DB + return false; + } + + return true; + + } + + /** + * Get OTPData from DB + * @param oneTimeToken One Time Token + * @return {@link OTPMailDTO} + * @throws OTPManagementException if error occurred while getting OTP data for given OTP in DB + */ + private OTPMailDTO getOTPDataByToken ( String oneTimeToken) throws OTPManagementException { + try { + ConnectionManagerUtil.openDBConnection(); + return otpManagementDAO.getOTPDataByToken(oneTimeToken); + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection to validate the given OTP."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (OTPManagementDAOException e) { + String msg = "Error occurred while getting OTP data from DB. OTP: " + oneTimeToken; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index 54c7c04805d..ad677b1bf04 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -89,7 +89,6 @@ import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeVersion; import org.wso2.carbon.device.mgt.core.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate; -import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation; import java.sql.SQLException; import java.util.Date; diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java index 7b207aa034f..636b0052a45 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java @@ -20,21 +20,13 @@ package org.wso2.carbon.webapp.authenticator.framework.authenticator; import org.apache.catalina.connector.Response; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.tomcat.util.buf.ByteChunk; -import org.apache.tomcat.util.buf.MessageBytes; import org.wso2.carbon.device.mgt.common.general.OneTimeTokenDetails; -import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; import org.wso2.carbon.webapp.authenticator.framework.Constants; -import org.wso2.carbon.webapp.authenticator.framework.Utils.Utils; -import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuth2TokenValidator; -import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuthTokenValidationException; -import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuthValidationResponse; +import org.wso2.carbon.webapp.authenticator.framework.internal.AuthenticatorFrameworkDataHolder; import java.util.Properties; -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class OneTimeTokenAuthenticator implements WebappAuthenticator { private static final Log log = LogFactory.getLog(OneTimeTokenAuthenticator.class); @@ -51,6 +43,10 @@ public class OneTimeTokenAuthenticator implements WebappAuthenticator { public AuthenticationInfo authenticate(org.apache.catalina.connector.Request request, Response response) { + OTPManagementService otpManagementService = AuthenticatorFrameworkDataHolder.getInstance() + .getOtpManagementService(); + + String token = request.getHeader(Constants.HTTPHeaders.ONE_TIME_TOKEN_HEADER); // DeviceMgtAPIUtils.getDeviceManagementService();//TODO: call token validate service in core OneTimeTokenDetails tokenDetails = new OneTimeTokenDetails();//TODO: use token details diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java index 0bfbcc8f436..a95b4fadb66 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java @@ -20,7 +20,7 @@ package org.wso2.carbon.webapp.authenticator.framework.internal; import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; -import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; @@ -36,7 +36,7 @@ public class AuthenticatorFrameworkDataHolder { private OAuth2TokenValidationService oAuth2TokenValidationService; private TenantIndexingLoader tenantIndexingLoader; private TenantRegistryLoader tenantRegistryLoader; - private DeviceManagementProviderService deviceManagementService; + private OTPManagementService otpManagementService; private static AuthenticatorFrameworkDataHolder thisInstance = new AuthenticatorFrameworkDataHolder(); @@ -117,12 +117,9 @@ public class AuthenticatorFrameworkDataHolder { return tenantRegistryLoader; } + public OTPManagementService getOtpManagementService() { return otpManagementService; } - public DeviceManagementProviderService getDeviceManagementService() { - return deviceManagementService; - } - - public void setDeviceManagementService(DeviceManagementProviderService deviceManagementService) { - this.deviceManagementService = deviceManagementService; + public void setOtpManagementService(OTPManagementService otpManagementService) { + this.otpManagementService = otpManagementService; } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java index 1fc7ba2bb98..ef71b78718d 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java @@ -25,6 +25,7 @@ import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; @@ -81,13 +82,14 @@ import java.util.Properties; * cardinality="1..1" policy="dynamic" * bind="setTenantRegistryLoader" * unbind="unsetTenantRegistryLoader" - * @scr.reference name="org.wso2.carbon.device.manager" - * interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService" + * @scr.reference name="org.wso2.carbon.otp.manager" + * interface="org.wso2.carbon.device.mgt.common.spi.OTPManagementService" * cardinality="1..1" * policy="dynamic" - * bind="setDeviceManagementService" - * unbind="unsetDeviceManagementService" + * bind="setOTPManagementService" + * unbind="unsetOTPManagementService" */ + public class WebappAuthenticatorFrameworkServiceComponent { private static final Log log = LogFactory.getLog(WebappAuthenticatorFrameworkServiceComponent.class); @@ -219,19 +221,17 @@ public class WebappAuthenticatorFrameworkServiceComponent { AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(null); } - @SuppressWarnings("unused") - protected void setDeviceManagementService(DeviceManagementProviderService deviceManagementProviderService) { + protected void setOTPManagementService(OTPManagementService otpManagementService) { if (log.isDebugEnabled()) { - log.debug("Setting ApplicationDTO Management OSGI Manager"); + log.debug("Setting OTP Management OSGI Service"); } - AuthenticatorFrameworkDataHolder.getInstance().setDeviceManagementService(deviceManagementProviderService); + AuthenticatorFrameworkDataHolder.getInstance().setOtpManagementService(otpManagementService); } - @SuppressWarnings("unused") - protected void unsetDeviceManagementService(DeviceManagementProviderService deviceManagementProviderService) { + protected void unsetOTPManagementService(OTPManagementService otpManagementService) { if (log.isDebugEnabled()) { - log.debug("Removing ApplicationDTO Management OSGI Manager"); + log.debug("Removing OTP Management OSGI Service"); } - AuthenticatorFrameworkDataHolder.getInstance().setDeviceManagementService(null); + AuthenticatorFrameworkDataHolder.getInstance().setOtpManagementService(null); } }