org.wso2.carbon.identity.authenticator.mepin.MepinAuthenticator.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.authenticator.mepin.MepinAuthenticator.java

Source

/*
 *  Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *  WSO2 Inc. licenses this file to you under the Apache License,
 *  Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */

package org.wso2.carbon.identity.authenticator.mepin;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.identity.application.authentication.framework.AbstractApplicationAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticatorFlowStatus;
import org.wso2.carbon.identity.application.authentication.framework.FederatedApplicationAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.LocalApplicationAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.config.ConfigurationFacade;
import org.wso2.carbon.identity.application.authentication.framework.config.model.StepConfig;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext;
import org.wso2.carbon.identity.application.authentication.framework.exception.ApplicationAuthenticatorException;
import org.wso2.carbon.identity.application.authentication.framework.exception.AuthenticationFailedException;
import org.wso2.carbon.identity.application.authentication.framework.exception.LogoutFailedException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants;
import org.wso2.carbon.identity.application.common.model.Property;
import org.wso2.carbon.identity.authenticator.mepin.internal.MepinAuthenticatorServiceComponent;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.user.profile.mgt.UserProfileException;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.UserCoreConstants;
import org.wso2.carbon.user.core.UserStoreManager;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Authenticator of MePIN
 */
public class MepinAuthenticator extends AbstractApplicationAuthenticator
        implements FederatedApplicationAuthenticator {

    private static final long serialVersionUID = -8948601002969608129L;
    private static Log log = LogFactory.getLog(MepinAuthenticator.class);
    private Map<String, String> authenticatorProperties;

    /**
     * Check whether the authentication or logout request can be handled by the authenticator
     */
    @Override
    public boolean canHandle(HttpServletRequest request) {
        if (log.isDebugEnabled()) {
            log.debug("Inside MepinAuthenticator.canHandle()");
        }
        return ((!StringUtils.isEmpty(request.getParameter(MepinConstants.MEPIN_ACCESSTOKEN)))
                || (!StringUtils.isEmpty(request.getParameter(MepinConstants.MEPIN_LOGIN))));

    }

    /**
     * initiate the authentication request
     */
    @Override
    protected void initiateAuthenticationRequest(HttpServletRequest request, HttpServletResponse response,
            AuthenticationContext context) throws AuthenticationFailedException {
        authenticatorProperties = context.getAuthenticatorProperties();
        String loginPage = ConfigurationFacade.getInstance().getAuthenticationEndpointURL()
                .replace(MepinConstants.LOGIN_PAGE, MepinConstants.MEPIN_PAGE);
        boolean isSecondStep = false;
        try {
            String authenticatedLocalUsername = getLocalAuthenticatedUser(context).getUserName();
            if (StringUtils.isNotEmpty(authenticatedLocalUsername)) {
                isSecondStep = true;
            }
        } catch (NullPointerException e) {
            log.warn("Username cannot be fetched from previous authentication steps.");
        }

        try {
            String retryParam = "";
            if (context.isRetrying()) {
                retryParam = "&authFailure=true&authFailureMsg=authentication.fail.message";
            }
            response.sendRedirect(response.encodeRedirectURL(loginPage + "?authenticators=" + getName()
                    + "&applicationId=" + authenticatorProperties.get(MepinConstants.MEPIN_APPICATION_ID)
                    + "&callbackUrl=" + authenticatorProperties.get(MepinConstants.MEPIN_CALLBACK_URL) + "&"
                    + FrameworkConstants.SESSION_DATA_KEY + "=" + context.getContextIdentifier() + "&isSecondStep="
                    + isSecondStep + retryParam));
        } catch (IOException e) {
            if (log.isDebugEnabled()) {
                log.debug("Error while redirecting");
            }
            throw new AuthenticationFailedException("Error while redirecting the MePIN");
        }
    }

    /**
     * Get the configuration properties of UI
     */
    @Override
    public List<Property> getConfigurationProperties() {
        List<Property> configProperties = new ArrayList<Property>();

        Property applicationId = new Property();
        applicationId.setName(MepinConstants.MEPIN_APPICATION_ID);
        applicationId.setDisplayName("Application Id");
        applicationId.setRequired(true);
        applicationId.setDescription("Enter MePIN application id value");
        applicationId.setDisplayOrder(1);
        configProperties.add(applicationId);

        Property username = new Property();
        username.setName(MepinConstants.MEPIN_USERNAME);
        username.setDisplayName("Username");
        username.setRequired(true);
        username.setDescription("Enter username");
        username.setDisplayOrder(2);
        configProperties.add(username);

        Property password = new Property();
        password.setName(MepinConstants.MEPIN_PASSWORD);
        password.setDisplayName("Password");
        password.setRequired(true);
        password.setConfidential(true);
        password.setDescription("Enter password");
        password.setDisplayOrder(3);
        configProperties.add(password);

        Property callbackUrl = new Property();
        callbackUrl.setName(MepinConstants.MEPIN_CALLBACK_URL);
        callbackUrl.setDisplayName("Callback URL");
        callbackUrl.setRequired(true);
        callbackUrl.setDescription("Enter value corresponding to callback url");
        callbackUrl.setDisplayOrder(4);
        configProperties.add(callbackUrl);

        Property clientId = new Property();
        clientId.setName(MepinConstants.MEPIN_CLIENT_ID);
        clientId.setDisplayName("Client Id");
        clientId.setRequired(true);
        clientId.setDescription("Enter Client Id");
        clientId.setDisplayOrder(5);
        configProperties.add(clientId);

        Property confirmationPolicy = new Property();
        confirmationPolicy.setName(MepinConstants.MEPIN_CONFIRMATION_POLICY);
        confirmationPolicy.setDisplayName("Confirmation Policy");
        confirmationPolicy.setRequired(true);
        confirmationPolicy.setDescription("Enter Confirmation Policy (tap, pin, swipe, fp)");
        confirmationPolicy.setDisplayOrder(6);
        configProperties.add(confirmationPolicy);

        Property expiryTime = new Property();
        expiryTime.setName(MepinConstants.MEPIN_EXPIRY_TIME);
        expiryTime.setDisplayName("Expiry Time");
        expiryTime.setRequired(true);
        expiryTime.setDescription("Enter Expiry Time (in seconds)");
        expiryTime.setDisplayOrder(7);
        configProperties.add(expiryTime);

        Property header = new Property();
        header.setName(MepinConstants.MEPIN_HEADER);
        header.setDisplayName("Header");
        header.setRequired(true);
        header.setDescription("Enter Header");
        header.setDisplayOrder(8);
        configProperties.add(header);

        Property message = new Property();
        message.setName(MepinConstants.MEPIN_MESSAGE);
        message.setDisplayName("Message");
        message.setRequired(true);
        message.setDescription("Enter Message");
        message.setDisplayOrder(9);
        configProperties.add(message);

        Property shortMessage = new Property();
        shortMessage.setName(MepinConstants.MEPIN_SHORT_MESSAGE);
        shortMessage.setDisplayName("Short Message");
        shortMessage.setRequired(true);
        shortMessage.setDescription("Enter Short Message");
        shortMessage.setDisplayOrder(10);
        configProperties.add(shortMessage);

        return configProperties;
    }

    /**
     * Process the response of the MePIN end-point
     */
    @Override
    protected void processAuthenticationResponse(HttpServletRequest request, HttpServletResponse response,
            AuthenticationContext context) throws AuthenticationFailedException {
        String username;
        String password;
        if ((!StringUtils.isEmpty(request.getParameter(MepinConstants.IS_SECOND_STEP))
                && !StringUtils.isEmpty(request.getParameter(MepinConstants.MEPIN_ACCESSTOKEN)))) {

            if (request.getParameter(MepinConstants.IS_SECOND_STEP).equals(MepinConstants.TRUE)) {
                username = getLocalAuthenticatedUser(context).getUserName();
            } else {
                String authHeader = request.getParameter(MepinConstants.AUTH_HEADER);
                UserStoreManager userStoreManager = null;
                authHeader = new String(Base64.decodeBase64(authHeader.getBytes()));
                int index = authHeader.indexOf(":");
                username = authHeader.substring(0, index);
                password = authHeader.substring(index + 1, authHeader.length());
                int tenantId = IdentityTenantUtil.getTenantIdOfUser(username);
                try {
                    userStoreManager = (UserStoreManager) MepinAuthenticatorServiceComponent.getRealmService()
                            .getTenantUserRealm(tenantId).getUserStoreManager();
                    boolean isAuthenticated = false;
                    isAuthenticated = userStoreManager
                            .authenticate(MultitenantUtils.getTenantAwareUsername(username), password);
                    if (!isAuthenticated) {
                        throw new AuthenticationFailedException(
                                "Authentication Failed: Invalid username or password");
                    }
                } catch (UserStoreException e) {
                    log.error("Unable to get the user store manager: " + e.getMessage(), e);
                    throw new AuthenticationFailedException(
                            "Unable to get the user store manager: " + e.getMessage(), e);
                }
            }

            try {
                String accessToken = request.getParameter(MepinConstants.MEPIN_ACCESSTOKEN);
                String responseString = new MepinTransactions().getUserInformation(
                        authenticatorProperties.get(MepinConstants.MEPIN_USERNAME),
                        authenticatorProperties.get(MepinConstants.MEPIN_PASSWORD), accessToken);
                if (!responseString.equals(MepinConstants.FAILED)) {
                    JsonObject responseJson = new JsonParser().parse(responseString).getAsJsonObject();
                    String mepinId = responseJson.getAsJsonPrimitive(MepinConstants.MEPIN_ID).getAsString();
                    associateFederatedIdToLocalUsername(username, context,
                            getFederateAuthenticatedUser(context, mepinId));
                    context.setSubject(
                            AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(username));
                } else {
                    throw new AuthenticationFailedException("Unable to get the MePIN ID.");
                }
            } catch (ApplicationAuthenticatorException e) {
                log.error("Unable to set the subject: " + e.getMessage(), e);
                throw new AuthenticationFailedException("Unable to set the subject: " + e.getMessage(), e);
            } catch (UserProfileException e) {
                log.error("Unable to associate the user: " + e.getMessage(), e);
                throw new AuthenticationFailedException("Unable to associate the user: " + e.getMessage(), e);
            }

        } else {

            if (request.getParameter(MepinConstants.IS_SECOND_STEP).equals(MepinConstants.TRUE)) {
                username = getLocalAuthenticatedUser(context).getUserName();
            } else {
                username = request.getParameter(MepinConstants.USERNAME);
                password = request.getParameter(MepinConstants.PASSWORD);
                boolean isBasicAuthenticated = false;
                UserStoreManager userStoreManager = null;
                int tenantId = IdentityTenantUtil.getTenantIdOfUser(username);
                try {
                    userStoreManager = (UserStoreManager) MepinAuthenticatorServiceComponent.getRealmService()
                            .getTenantUserRealm(tenantId).getUserStoreManager();
                    isBasicAuthenticated = userStoreManager
                            .authenticate(MultitenantUtils.getTenantAwareUsername(username), password);
                    if (!isBasicAuthenticated) {
                        throw new AuthenticationFailedException(
                                "Authentication Failed: Invalid username or password");
                    }
                } catch (UserStoreException e) {
                    log.error("Unable to get the user store manager: " + e.getMessage(), e);
                    throw new AuthenticationFailedException(
                            "Unable to get the user store manager: " + e.getMessage(), e);
                }

            }
            String allowStatus = "";

            try {

                String idpName = context.getExternalIdP().getIdPName();
                String mePinId = null;
                mePinId = getMepinIdAssociatedWithUsername(idpName, username);
                boolean isAuthenticated = false;
                String transactionResponseString = new MepinTransactions().createTransaction(mePinId,
                        context.getContextIdentifier(), MepinConstants.MEPIN_CREATE_TRANSACTION_URL,
                        authenticatorProperties.get(MepinConstants.MEPIN_USERNAME),
                        authenticatorProperties.get(MepinConstants.MEPIN_PASSWORD),
                        authenticatorProperties.get(MepinConstants.MEPIN_CLIENT_ID),
                        authenticatorProperties.get(MepinConstants.MEPIN_HEADER),
                        authenticatorProperties.get(MepinConstants.MEPIN_MESSAGE),
                        authenticatorProperties.get(MepinConstants.MEPIN_SHORT_MESSAGE),
                        authenticatorProperties.get(MepinConstants.MEPIN_CONFIRMATION_POLICY),
                        authenticatorProperties.get(MepinConstants.MEPIN_CALLBACK_URL),
                        authenticatorProperties.get(MepinConstants.MEPIN_EXPIRY_TIME));
                if (!transactionResponseString.equals(MepinConstants.FAILED)) {
                    JsonObject transactionResponseJson = new JsonParser().parse(transactionResponseString)
                            .getAsJsonObject();
                    String transactionId = transactionResponseJson
                            .getAsJsonPrimitive(MepinConstants.MEPIN_TRANSACTION_ID).getAsString();
                    String status = transactionResponseJson.getAsJsonPrimitive(MepinConstants.MEPIN_STATUS)
                            .getAsString();
                    if (status.equalsIgnoreCase(MepinConstants.MEPIN_OK)) {
                        if (log.isDebugEnabled()) {
                            log.debug("Successfully created the MePIN transaction");
                        }
                        int retry = 0;
                        int retryInterval = 1;
                        int retryCount = Integer.parseInt(
                                authenticatorProperties.get(MepinConstants.MEPIN_EXPIRY_TIME)) / retryInterval;
                        while (retry < retryCount) {
                            String responseString = new MepinTransactions().getTransaction(
                                    MepinConstants.MEPIN_GET_TRANSACTION_URL, transactionId,
                                    authenticatorProperties.get(MepinConstants.MEPIN_CLIENT_ID),
                                    authenticatorProperties.get(MepinConstants.MEPIN_USERNAME),
                                    authenticatorProperties.get(MepinConstants.MEPIN_PASSWORD));
                            if (!responseString.equals(MepinConstants.FAILED)) {
                                JsonObject transactionStatusResponse = new JsonParser().parse(responseString)
                                        .getAsJsonObject();
                                String transactionStatus = transactionStatusResponse
                                        .getAsJsonPrimitive(MepinConstants.MEPIN_TRANSACTION_STATUS).getAsString();
                                JsonPrimitive allowObject = transactionStatusResponse
                                        .getAsJsonPrimitive(MepinConstants.MEPIN_ALLOW);
                                if (log.isDebugEnabled()) {
                                    log.debug("Transaction status :" + transactionStatus);
                                }
                                if (transactionStatus.equals(MepinConstants.MEPIN_COMPLETED)) {
                                    allowStatus = allowObject.getAsString();
                                    if (Boolean.parseBoolean(allowStatus)) {
                                        isAuthenticated = true;
                                        break;
                                    }
                                } else if (transactionStatus.equals(MepinConstants.MEPIN_CANCELED)
                                        || transactionStatus.equals(MepinConstants.MEPIN_EXPIRED)
                                        || transactionStatus.equals(MepinConstants.MEPIN_ERROR)) {
                                    break;
                                }
                            }
                            Thread.sleep(1000);
                            retry++;
                        }
                        if (isAuthenticated) {
                            context.setSubject(
                                    AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(username));
                        } else {
                            throw new AuthenticationFailedException("Unable to confirm the MePIN transaction");
                        }
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("Error while creating the MePIN transaction");
                        }
                        throw new AuthenticationFailedException("Error while creating the MePIN transaction");
                    }
                } else {
                    if (log.isDebugEnabled()) {
                        log.debug("Error while creating the MePIN transaction");
                    }
                    throw new AuthenticationFailedException("Error while creating the MePIN transaction");
                }
            } catch (UserProfileException e) {
                log.error("Unable to get the associated user: " + e.getMessage(), e);
                throw new AuthenticationFailedException("Unable to get the associated user: " + e.getMessage(), e);
            } catch (IOException e) {
                log.error("Unable to create the MePIN transaction: " + e.getMessage(), e);
                throw new AuthenticationFailedException("Unable to create the MePIN transaction: " + e.getMessage(),
                        e);
            } catch (InterruptedException e) {
                log.error("Interruption occurred while getting the MePIN transaction status" + e.getMessage(), e);
                throw new AuthenticationFailedException(
                        "Interruption occurred while getting the MePIN transaction status" + e.getMessage(), e);
            }
        }
    }

    /**
     * Get the friendly name of the Authenticator
     */
    @Override
    public String getFriendlyName() {
        return MepinConstants.AUTHENTICATOR_FRIENDLY_NAME;
    }

    /**
     * Get the name of the Authenticator
     */
    @Override
    public String getName() {
        return MepinConstants.AUTHENTICATOR_NAME;
    }

    @Override
    public AuthenticatorFlowStatus process(HttpServletRequest request, HttpServletResponse response,
            AuthenticationContext context) throws AuthenticationFailedException, LogoutFailedException {
        if (context.isLogoutRequest()) {
            return AuthenticatorFlowStatus.SUCCESS_COMPLETED;
        }
        return super.process(request, response, context);
    }

    /**
     * Get the Context identifier sent with the request.
     */
    public String getContextIdentifier(HttpServletRequest request) {
        return request.getParameter(FrameworkConstants.SESSION_DATA_KEY);
    }

    @Override
    protected boolean retryAuthenticationEnabled() {
        return true;
    }

    private AuthenticatedUser getLocalAuthenticatedUser(AuthenticationContext context) {
        //Getting the last authenticated local user
        AuthenticatedUser authenticatedUser = null;
        for (Integer stepMap : context.getSequenceConfig().getStepMap().keySet()) {
            if (context.getSequenceConfig().getStepMap().get(stepMap).getAuthenticatedUser() != null
                    && context.getSequenceConfig().getStepMap().get(stepMap).getAuthenticatedAutenticator()
                            .getApplicationAuthenticator() instanceof LocalApplicationAuthenticator) {
                authenticatedUser = context.getSequenceConfig().getStepMap().get(stepMap).getAuthenticatedUser();
                break;
            }
        }

        return authenticatedUser;
    }

    private AuthenticatedUser getFederateAuthenticatedUser(AuthenticationContext context,
            String authenticatedUserId) throws ApplicationAuthenticatorException {
        if (StringUtils.isEmpty(authenticatedUserId)) {
            throw new ApplicationAuthenticatorException("Authenticated user identifier is empty");
        }
        AuthenticatedUser authenticatedUser = AuthenticatedUser
                .createFederateAuthenticatedUserFromSubjectIdentifier(authenticatedUserId);
        if (authenticatedUser.getUserStoreDomain() == null) {
            authenticatedUser.setUserStoreDomain(UserCoreConstants.PRIMARY_DEFAULT_DOMAIN_NAME);
        }
        authenticatedUser.setUserName(authenticatedUserId);
        if (log.isDebugEnabled()) {
            log.debug("The authenticated subject identifier :"
                    + authenticatedUser.getAuthenticatedSubjectIdentifier());
        }
        return authenticatedUser;
    }

    private void associateFederatedIdToLocalUsername(String authenticatedLocalUsername,
            AuthenticationContext context, AuthenticatedUser authenticatedUser) throws UserProfileException {
        StepConfig stepConfig = null;

        for (int i = 1; i <= context.getSequenceConfig().getStepMap().size(); i++) {
            stepConfig = context.getSequenceConfig().getStepMap().get(i);
            for (int j = 0; j < stepConfig.getAuthenticatorList().size(); j++) {
                if (stepConfig.getAuthenticatorList().get(j).getName().equals(getName())) {
                    try {
                        String idpName;
                        String originalExternalIdpSubjectValueForThisStep = authenticatedUser
                                .getAuthenticatedSubjectIdentifier();
                        idpName = context.getExternalIdP().getIdPName();
                        stepConfig.setAuthenticatedIdP(idpName);
                        associateID(idpName, originalExternalIdpSubjectValueForThisStep,
                                authenticatedLocalUsername);
                        stepConfig.setAuthenticatedUser(authenticatedUser);
                        context.getSequenceConfig().getStepMap().put(i, stepConfig);
                    } catch (UserProfileException e) {
                        throw new UserProfileException("Unable to continue with the federated ID ("
                                + authenticatedUser.getAuthenticatedSubjectIdentifier() + "): " + e.getMessage(),
                                e);
                    }
                    break;
                }
            }
        }
    }

    private void associateID(String idpID, String associatedID, String userName) throws UserProfileException {
        Connection connection = IdentityDatabaseUtil.getDBConnection();
        PreparedStatement prepStmt = null;
        String sql = null;
        int tenantID = CarbonContext.getThreadLocalCarbonContext().getTenantId();
        String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(userName);
        String domainName = getDomainName(tenantAwareUsername);
        tenantAwareUsername = getUsernameWithoutDomain(tenantAwareUsername);

        try {
            sql = "INSERT INTO IDN_ASSOCIATED_ID (TENANT_ID, IDP_ID, IDP_USER_ID, DOMAIN_NAME, USER_NAME) VALUES "
                    + "(? , (SELECT ID FROM IDP WHERE NAME = ? AND TENANT_ID = ? ), ? , ?, ?)";
            prepStmt = connection.prepareStatement(sql);
            prepStmt.setInt(1, tenantID);
            prepStmt.setString(2, idpID);
            prepStmt.setInt(3, tenantID);
            prepStmt.setString(4, associatedID);
            prepStmt.setString(5, domainName);
            prepStmt.setString(6, tenantAwareUsername);
            prepStmt.execute();
            connection.commit();
        } catch (SQLException e) {
            log.error("Error occurred while persisting the federated user ID", e);
            throw new UserProfileException("Error occurred while persisting the federated user ID", e);
        } finally {
            IdentityDatabaseUtil.closeAllConnections(connection, (ResultSet) null, prepStmt);
        }
    }

    private static String getDomainName(String username) {
        int index = username.indexOf("/");
        return index < 0 ? "PRIMARY" : username.substring(0, index);
    }

    private static String getUsernameWithoutDomain(String username) {
        int index = username.indexOf("/");
        return index < 0 ? username : username.substring(index + 1, username.length());
    }

    public String getMepinIdAssociatedWithUsername(String idpID, String username) throws UserProfileException {

        Connection connection = IdentityDatabaseUtil.getDBConnection();
        PreparedStatement prepStmt = null;
        ResultSet resultSet;
        String sql = null;
        String mepinId = "";
        int tenantID = CarbonContext.getThreadLocalCarbonContext().getTenantId();

        try {
            sql = "SELECT IDP_USER_ID  FROM IDN_ASSOCIATED_ID WHERE TENANT_ID = ? AND IDP_ID = (SELECT ID "
                    + "FROM IDP WHERE NAME = ? AND TENANT_ID = ?) AND USER_NAME = ?";

            prepStmt = connection.prepareStatement(sql);
            prepStmt.setInt(1, tenantID);
            prepStmt.setString(2, idpID);
            prepStmt.setInt(3, tenantID);
            prepStmt.setString(4, username);

            resultSet = prepStmt.executeQuery();
            connection.commit();

            if (resultSet.next()) {
                mepinId = resultSet.getString(1);
                return mepinId;
            }

        } catch (SQLException e) {
            log.error("Error occurred while getting the associated MePIN ID", e);
            throw new UserProfileException("Error occurred while getting the associated MePIN ID", e);
        } finally {
            IdentityDatabaseUtil.closeAllConnections(connection, null, prepStmt);
        }
        return null;
    }
}