com.wso2telco.openidtokenbuilder.MIFEOpenIDTokenBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.wso2telco.openidtokenbuilder.MIFEOpenIDTokenBuilder.java

Source

/*******************************************************************************
 * Copyright (c) 2015-2016, WSO2.Telco Inc. (http://www.wso2telco.com) 
 *
 * All Rights Reserved. WSO2.Telco Inc. licences 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 com.wso2telco.openidtokenbuilder;

import com.jayway.jsonpath.JsonPath;
import com.nimbusds.jwt.PlainJWT;
import com.wso2telco.core.config.DataHolder;
import com.wso2telco.core.config.model.MobileConnectConfig;
import com.wso2telco.core.config.service.ConfigurationService;
import com.wso2telco.core.config.service.ConfigurationServiceImpl;
import com.wso2telco.core.pcrservice.PCRFactory;
import com.wso2telco.core.pcrservice.PCRGeneratable;
import com.wso2telco.core.pcrservice.Returnable;
import com.wso2telco.core.pcrservice.exception.PCRException;
import com.wso2telco.core.pcrservice.model.RequestDTO;
import com.wso2telco.core.pcrservice.util.SectorUtil;
import com.wso2telco.dao.TransactionDAO;
import com.wso2telco.ids.datapublisher.util.DataPublisherUtil;
import com.wso2telco.internal.OpenIdTokenBuilderDataHolder;
import com.wso2telco.util.AuthenticationHealper;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oltu.openidconnect.as.messages.IDToken;
import org.apache.oltu.openidconnect.as.messages.IDTokenException;
import org.codehaus.jettison.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wso2.carbon.identity.application.common.cache.BaseCache;
import org.wso2.carbon.identity.application.common.model.ClaimMapping;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.oauth.cache.*;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeRespDTO;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.openidconnect.CustomClaimsCallbackHandler;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

// TODO: Auto-generated Javadoc

/**
 * The Class MIFEOpenIDTokenBuilder.
 */
public class MIFEOpenIDTokenBuilder implements org.wso2.carbon.identity.openidconnect.IDTokenBuilder {

    private static MobileConnectConfig mobileConnectConfig = null;

    /**
     * The Configuration service
     */
    private static ConfigurationService configurationService = new ConfigurationServiceImpl();

    static {
        mobileConnectConfig = configurationService.getDataHolder().getMobileConnectConfig();
    }

    /**
     * The Constant ACR_HOST_URI.
     */
    private static final String ACR_HOST_URI = mobileConnectConfig.getMifeOpenIDTokenBuilderConfig()
            .getAcrHostUri();

    /**
     * The Constant RETRIEVE_SERVICE.
     */
    private static final String RETRIEVE_SERVICE = mobileConnectConfig.getMifeOpenIDTokenBuilderConfig()
            .getRetrieveService();

    /**
     * The Constant CREATE_SERVICE.
     */
    private static final String CREATE_SERVICE = mobileConnectConfig.getMifeOpenIDTokenBuilderConfig()
            .getCreateService();

    /**
     * The Constant APP_PROV_SERVICE.
     */
    private static final String APP_PROV_SERVICE = mobileConnectConfig.getMifeOpenIDTokenBuilderConfig()
            .getAppProvService();

    /**
     * The Constant SERVICE_PROVIDER.
     */
    private static final String SERVICE_PROVIDER = mobileConnectConfig.getMifeOpenIDTokenBuilderConfig()
            .getServiceProvider();

    /**
     * The Constant SERVICE_KEY.
     */
    private static final String SERVICE_KEY = mobileConnectConfig.getMifeOpenIDTokenBuilderConfig().getServiceKey();

    /**
     * The Constant ACR_ACCESS_TOKEN.
     */
    private static final String ACR_ACCESS_TOKEN = mobileConnectConfig.getMifeOpenIDTokenBuilderConfig()
            .getAcrAccessToken();

    /**
     * The log.
     */
    private static Log log = LogFactory.getLog(MIFEOpenIDTokenBuilder.class);

    /**
     * The debug.
     */
    private static boolean DEBUG = log.isDebugEnabled();

    /**
     * The http client.
     */
    private HttpClient httpClient;

    /**
     * The acr app id.
     */
    private String acrAppID;

    private static final String SESSIONID = "sessionId";

    /* (non-Javadoc)
     * @see org.wso2.carbon.identity.openidconnect.IDTokenBuilder#buildIDToken(org.wso2.carbon.identity.oauth2.token
     * .OAuthTokenReqMessageContext, org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO)
     */
    public String buildIDToken(OAuthTokenReqMessageContext request, OAuth2AccessTokenRespDTO tokenRespDTO)
            throws IdentityOAuth2Exception {
        if (log.isDebugEnabled()) {
            log.debug("MSISDN : " + request.getAuthorizedUser().getUserName());
            log.debug("Generated access token : [" + tokenRespDTO.getAccessToken() + "]  for Authorization Code :  "
                    + request.getProperty("AuthorizationCode"));
        }

        String responseIDToken;

        if (mobileConnectConfig.isFederatedDeployment() && tokenRespDTO.getIDToken() != null) {
            log.info("Federated Identity ID_Token Info Flow initiated for " + tokenRespDTO.getAccessToken());
            responseIDToken = federatedIDTokenFlow(request, tokenRespDTO);
        } else
            responseIDToken = regularIDTokenFlow(request, tokenRespDTO);
        return responseIDToken;
    }

    private String regularIDTokenFlow(OAuthTokenReqMessageContext request, OAuth2AccessTokenRespDTO tokenRespDTO)
            throws IdentityOAuth2Exception {
        OAuthServerConfiguration config = OAuthServerConfiguration.getInstance();
        String issuer = config.getOpenIDConnectIDTokenIssuerIdentifier();
        int lifetime = Integer.parseInt(config.getOpenIDConnectIDTokenExpiration()) * 1000;
        int curTime = (int) Calendar.getInstance().getTimeInMillis();
        String responseIDToken;
        //String msisdn = request.getAuthorizedUser().replaceAll("@.*", ""); //$NON-NLS-1$ //$NON-NLS-2$
        String msisdn = AuthenticationHealper.getUser(request).replaceAll("@.*", ""); //$NON-NLS-1$ //$NON-NLS-2$

        // Loading respective application data
        OAuthAppDO oAuthAppDO;
        try {
            oAuthAppDO = getAppInformation(request.getOauth2AccessTokenReqDTO());
        } catch (InvalidOAuthClientException e) {
            throw new IdentityOAuth2Exception("Error occured while retrieving application information", e); //$NON-NLS-1$
        }
        String applicationName = oAuthAppDO.getApplicationName();
        String applicationClientId = oAuthAppDO.getOauthConsumerKey();
        String callbackUrl = oAuthAppDO.getCallbackUrl();

        // Get authenticators used
        String amr[] = getValuesFromCache(request, "amr").split(",");

        JSONArray amrArray = new JSONArray(Arrays.asList(amr));

        // Set ACR (PCR) to sub
        String subject = null;

        ConfigurationService configurationService = new ConfigurationServiceImpl();
        DataHolder dataHolder = configurationService.getDataHolder();
        MobileConnectConfig mobileConnectConfig = dataHolder.getMobileConnectConfig();

        try {
            if (mobileConnectConfig.isPcrServiceEnabled()) {
                log.info("Generating UUID based PCR");
                subject = getPCR(msisdn, applicationClientId, callbackUrl);
            } else {
                msisdn = "tel:+".concat(msisdn); //$NON-NLS-1$
                subject = createLocalACR(msisdn, applicationName);
            }
            log.info("PCR : " + subject);
        } catch (InvalidKeyException e) {
            log.error("Error", e);
        } catch (NoSuchAlgorithmException e) {
            log.error("Error", e);
        } catch (PCRException e) {
            log.error("Error", e);
        }

        // Get access token issued time
        String accessTokenIssuedTime = getAccessTokenIssuedTime(tokenRespDTO.getAccessToken(), request);

        // Set base64 encoded value of the access token to atHash
        String atHash = new String(Base64.encodeBase64(tokenRespDTO.getAccessToken().getBytes()));

        // Get LOA used
        String acr = getValuesFromCache(request, "acr");

        String nonce = null;
        try {
            nonce = getValuesFromCache(request, IDToken.NONCE);
        } catch (IdentityOAuth2Exception e) {

            if (DEBUG) {
                log.error("Error", e);
            }

        }

        if (DEBUG) {
            log.debug("Using issuer : " + issuer); //$NON-NLS-1$
            log.debug("Subject : " + subject); //$NON-NLS-1$
            log.debug("ID Token expiration seconds : " + lifetime); //$NON-NLS-1$
            log.debug("Current time : " + curTime); //$NON-NLS-1$
            log.debug("nonce : " + nonce); //$NON-NLS-1$
        }

        try {

            CustomIDTokenBuilder builder = new CustomIDTokenBuilder();
            builder.setIssuer(issuer);
            builder.setSubject(subject);
            builder.setAudience(request.getOauth2AccessTokenReqDTO().getClientId());
            builder.setAuthorizedParty(request.getOauth2AccessTokenReqDTO().getClientId());
            builder.setExpiration(curTime + lifetime);
            builder.setIssuedAt(curTime);
            builder.setAuthTime(accessTokenIssuedTime);
            builder.setAtHash(atHash);
            builder.setClaim("acr", acr);
            builder.setAmr(amrArray);
            builder.setClaim(IDToken.NONCE, nonce); //$NON-NLS-1$ //$NON-NLS-2$
            // setting up custom claims
            CustomClaimsCallbackHandler claimsCallBackHandler = OAuthServerConfiguration.getInstance()
                    .getOpenIDConnectCustomClaimsCallbackHandler();
            //TODO CODE COMMENTED#
            //claimsCallBackHandler.handleCustomClaims(builder, request);

            String plainIDToken = builder.buildIDToken();
            String accessToken = tokenRespDTO.getAccessToken();
            try {
                TransactionDAO.insertTokenScopeLog(accessToken, subject);
            } catch (Exception e) {
                log.error("Error inserting to sub value Scope Log ", e);
            }
            boolean dataPublisherEnabled = DataHolder.getInstance().getMobileConnectConfig().getDataPublisher()
                    .isEnabled();

            if (dataPublisherEnabled) {
                //Publish event
                Map<String, String> tokenMap = new HashMap<String, String>();
                tokenMap.put("Timestamp", String.valueOf(new java.util.Date().getTime()));
                tokenMap.put("AuthenticatedUser", msisdn);
                tokenMap.put("Nonce", nonce);
                tokenMap.put("Amr", amrArray.toString());
                tokenMap.put("AuthenticationCode", request.getOauth2AccessTokenReqDTO().getAuthorizationCode());
                tokenMap.put("AccessToken", accessToken);
                tokenMap.put("ClientId", request.getOauth2AccessTokenReqDTO().getClientId());
                tokenMap.put("RefreshToken", tokenRespDTO.getRefreshToken());
                tokenMap.put(SESSIONID, getValuesFromCache(request, SESSIONID));
                tokenMap.put("State", getValuesFromCache(request, "state"));
                tokenMap.put("TokenClaims", getClaimValues(request));
                tokenMap.put("ContentType", "application/x-www-form-urlencoded");
                tokenMap.put("ReturnedResult", plainIDToken);
                if (accessToken != null) {
                    tokenMap.put("StatusCode", "200");
                } else {
                    tokenMap.put("StatusCode", "400");
                }

                if (DEBUG) {
                    for (Map.Entry<String, String> entry : tokenMap.entrySet()) {
                        log.debug(entry.getKey() + " : " + entry.getValue());
                    }
                }
                DataPublisherUtil.publishTokenEndpointData(tokenMap);
            }
            responseIDToken = new PlainJWT(
                    (com.nimbusds.jwt.JWTClaimsSet) PlainJWT.parse(plainIDToken).getJWTClaimsSet()).serialize();

        } catch (IDTokenException e) {
            throw new IdentityOAuth2Exception("Error occurred while generating the IDToken", e);
        } catch (ParseException e) {
            log.error("Error while parsing the IDToken", e);
            throw new IdentityOAuth2Exception("Error while parsing the IDToken", e);
        } catch (Exception e) {
            log.error("Error while parsing the IDToken", e);
            throw new IdentityOAuth2Exception("Error while parsing the IDToken", e);
        }
        return responseIDToken;
    }

    private String federatedIDTokenFlow(OAuthTokenReqMessageContext request, OAuth2AccessTokenRespDTO tokenRespDTO)
            throws IdentityOAuth2Exception {
        String responseIDToken;
        try {
            responseIDToken = initiateFederatedIDTokenProcess(request, tokenRespDTO);
        } catch (IDTokenException e) {
            log.error("Error occurred while generating the Federeated IDToken" + e.getMessage());
            throw new IdentityOAuth2Exception("Error occurred while generating the Federeated IDToken", e);
        } catch (ParseException e) {
            log.error("Error while parsing the generated Federated IDToken" + e.getMessage());
            throw new IdentityOAuth2Exception("Error while parsing the generated Federeated IDToken", e);
        } catch (Exception e) {
            log.error("Error while processing the federated IDToken" + e.getMessage());
            throw new IdentityOAuth2Exception("Error while processing the Federeated IDToken", e);
        }
        return responseIDToken;
    }

    /**
     * Gets the values from cache.
     *
     * @param request the request
     * @param key     the key
     * @return the values from cache
     * @throws IdentityOAuth2Exception the identity o auth2 exception
     */
    private String getValuesFromCache(OAuthTokenReqMessageContext request, String key)
            throws IdentityOAuth2Exception {
        String keyValue = null;
        AuthorizationGrantCacheKey authorizationGrantCacheKey = new AuthorizationGrantCacheKey(
                request.getOauth2AccessTokenReqDTO().getAuthorizationCode());
        AuthorizationGrantCacheEntry authorizationGrantCacheEntry = (AuthorizationGrantCacheEntry) AuthorizationGrantCache
                .getInstance().getValueFromCache(authorizationGrantCacheKey);

        Iterator<ClaimMapping> userAttributes = authorizationGrantCacheEntry.getUserAttributes().keySet()
                .iterator();

        ClaimMapping acrKey = null;
        while (userAttributes.hasNext()) {
            ClaimMapping mapping = userAttributes.next();
            if (mapping.getLocalClaim() != null) {
                if (mapping.getLocalClaim().getClaimUri().equals(key)) {
                    acrKey = mapping;
                }
            }

        }
        //TODO Code Diff
        if (null != acrKey) {
            return authorizationGrantCacheEntry.getUserAttributes().get(acrKey);
        } else {
            throw new IdentityOAuth2Exception("Error occured while retrieving " + key + " from cache");
        }
    }

    private String getClaimValues(OAuthTokenReqMessageContext request) throws IdentityOAuth2Exception {
        AuthorizationGrantCacheKey authorizationGrantCacheKey = new AuthorizationGrantCacheKey(
                request.getOauth2AccessTokenReqDTO().getAuthorizationCode());
        AuthorizationGrantCacheEntry authorizationGrantCacheEntry = AuthorizationGrantCache.getInstance()
                .getValueFromCache(authorizationGrantCacheKey);
        Map<ClaimMapping, String> claimMap = authorizationGrantCacheEntry.getUserAttributes();
        StringBuilder tokenClaims = new StringBuilder("");
        for (Map.Entry<ClaimMapping, String> entry : claimMap.entrySet()) {
            if (!tokenClaims.toString().isEmpty()) {
                tokenClaims.append(", ");
            }
            tokenClaims.append(entry.getValue());
        }
        return tokenClaims.toString();
    }

    private String getAccessTokenIssuedTime(String accessToken, OAuthTokenReqMessageContext request)
            throws IdentityOAuth2Exception {

        AccessTokenDO accessTokenDO = null;
        TokenMgtDAO tokenMgtDAO = new TokenMgtDAO();

        OAuthCache oauthCache = OAuthCache.getInstance();
        String authorizedUser = request.getAuthorizedUser().toString();
        boolean isUsernameCaseSensitive = IdentityUtil.isUserStoreInUsernameCaseSensitive(authorizedUser);
        if (!isUsernameCaseSensitive) {
            authorizedUser = authorizedUser.toLowerCase();
        }

        OAuthCacheKey cacheKey = new OAuthCacheKey(request.getOauth2AccessTokenReqDTO().getClientId() + ":"
                + authorizedUser + ":" + OAuth2Util.buildScopeString(request.getScope()));
        CacheEntry result = oauthCache.getValueFromCache(cacheKey);

        // cache hit, do the type check.
        if (result instanceof AccessTokenDO) {
            accessTokenDO = (AccessTokenDO) result;
        }

        // Cache miss, load the access token info from the database.
        if (accessTokenDO == null) {
            accessTokenDO = tokenMgtDAO.retrieveAccessToken(accessToken, false);
        }

        // if the access token or client id is not valid
        if (accessTokenDO == null) {
            throw new IdentityOAuth2Exception(
                    "Access token based information is not available in cache or database");
        }

        return Long.toString(accessTokenDO.getIssuedTime().getTime() / 1000);
    }

    /**
     * Gets the app information.
     *
     * @param tokenReqDTO the token req dto
     * @return the app information
     * @throws IdentityOAuth2Exception     the identity o auth2 exception
     * @throws InvalidOAuthClientException the invalid o auth client exception
     */
    public OAuthAppDO getAppInformation(OAuth2AccessTokenReqDTO tokenReqDTO)
            throws IdentityOAuth2Exception, InvalidOAuthClientException {
        BaseCache<String, OAuthAppDO> appInfoCache = new BaseCache<String, OAuthAppDO>("AppInfoCache"); //$NON-NLS-1$
        if (null != appInfoCache) {
            if (log.isDebugEnabled()) {
                log.debug("Successfully created AppInfoCache under " //$NON-NLS-1$
                        + OAuthConstants.OAUTH_CACHE_MANAGER);
            }
        }

        OAuthAppDO oAuthAppDO = appInfoCache.getValueFromCache(tokenReqDTO.getClientId());
        if (oAuthAppDO == null)
            appInfoCache.addToCache(tokenReqDTO.getClientId(), oAuthAppDO);

        return oAuthAppDO;

    }

    /**
     * Gets the ACR app id.
     *
     * @param applicationName the application name
     * @return the ACR app id
     * @throws IdentityOAuth2Exception the identity o auth2 exception
     */
    public String getACRAppID(String applicationName) throws IdentityOAuth2Exception {
        StringBuilder requestURLBuilder = new StringBuilder();
        requestURLBuilder.append(ACR_HOST_URI);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(APP_PROV_SERVICE);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(SERVICE_PROVIDER);
        String requestURL = requestURLBuilder.toString();

        JSONObject requestBody = new JSONObject();
        JSONObject createRequest = null;

        try {
            requestBody.put("appName", applicationName); //$NON-NLS-1$
            requestBody.put("serviceProviderAppId", applicationName); //$NON-NLS-1$
            requestBody.put("description", applicationName + " description"); //$NON-NLS-1$ //$NON-NLS-2$
            createRequest = new JSONObject().put("provisionAppRequest", requestBody); //$NON-NLS-1$
            StringRequestEntity requestEntity = new StringRequestEntity(createRequest.toString(),
                    "application/json", "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
            PostMethod postMethod = new PostMethod(requestURL);
            postMethod.addRequestHeader("Authorization-ACR", "ServiceKey " + SERVICE_KEY); //$NON-NLS-1$ //$NON-NLS-2$
            postMethod.addRequestHeader("Authorization", "Bearer " + ACR_ACCESS_TOKEN); //$NON-NLS-1$ //$NON-NLS-2$
            postMethod.setRequestEntity(requestEntity);

            if (DEBUG) {
                log.debug("Connecting to ACR engine @ " + ACR_HOST_URI); //$NON-NLS-1$
                log.debug("Service name : " + APP_PROV_SERVICE); //$NON-NLS-1$
                log.debug("Service provider : " + SERVICE_PROVIDER); //$NON-NLS-1$
                log.debug("Request - ACR app : " + requestEntity.getContent()); //$NON-NLS-1$
            }

            httpClient = new HttpClient();
            httpClient.executeMethod(postMethod);

            String responseACRApp = new String(postMethod.getResponseBody(), "UTF-8"); //$NON-NLS-1$
            String strACR = ""; //$NON-NLS-1$
            if (null != responseACRApp && !"".equals(responseACRApp)) { //$NON-NLS-1$
                try {
                    if (DEBUG) {
                        log.debug("Response - ACR app : " + responseACRApp); //$NON-NLS-1$
                    }
                    strACR = JsonPath.read(responseACRApp, "$.provisionAppResponse.appID"); //$NON-NLS-1$
                } catch (Exception e) {
                    log.error("Provisioning of ACR app failed", e); //$NON-NLS-1$
                    throw new IdentityOAuth2Exception("Provisioning of ACR app failed", e); //$NON-NLS-1$
                }
            }

            return strACR; //$NON-NLS-1$;

        } catch (UnsupportedEncodingException e) {
            log.error("Error occured while creating request", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating request", e); //$NON-NLS-1$
        } catch (JSONException e) {
            log.error("Error occured while creating request", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating request", e); //$NON-NLS-1$
        } catch (HttpException e) {
            log.error("Error occured while creating ACR app", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating ACR app", e); //$NON-NLS-1$
        } catch (IOException e) {
            log.error("Error occured while creating ACR app", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating ACR app", e); //$NON-NLS-1$
        }
    }

    /**
     * Gets the access token issued time.
     *
     * @param accessToken the access token
     * @return the access token issued time
     * @throws IdentityOAuth2Exception the identity o auth2 exception
     */
    /*public String getAccessTokenIssuedTime(String accessToken) throws IdentityOAuth2Exception {
    AccessTokenDO accessTokenDO = null;
      TokenMgtDAO tokenMgtDAO = new TokenMgtDAO();
      OAuthCache oauthCache = OAuthCache.getInstance();
      CacheKey cacheKey = new OAuthCacheKey(accessToken);
      //TODO CODE COMMENTED#
      //CacheEntry result = oauthCache.getValueFromCache(cacheKey);
      // cache hit, do the type check.
      //TODO CODE COMMENTED#
      //if (result instanceof AccessTokenDO) {
     //accessTokenDO = (AccessTokenDO) result;
      //}
      // Cache miss, load the access token info from the database.
      if (null == accessTokenDO) {
     //TODO CODE COMMENTED#
     accessTokenDO = tokenMgtDAO.retrieveAccessToken(accessToken);
      }
      // if the access token or client id is not valid
      if (null == accessTokenDO) {
     log.error("Error occured while getting access token based information"); //$NON-NLS-1$
     throw new IdentityOAuth2Exception(
           "Error occured while getting access token based information"); //$NON-NLS-1$
      }
      long timeIndMilliSeconds = accessTokenDO.getIssuedTime().getTime();
      return Long.toString(timeIndMilliSeconds / 1000);
    }*/

    /**
     * Gets the AMR from acr.
     *
     * @param acr the acr
     * @return the AMR from acr
     * @throws IdentityOAuth2Exception the identity o auth2 exception
     */
    public String getAMRFromACR(String acr) throws IdentityOAuth2Exception {
        //TODO CODE COMMENTED#
        //List<Authenticator> authenticatorsList = null;

        //TODO CODE COMMENTED#
        //LOAConfig config = ConfigLoader.getInstance().getLoaConfig();
        if (null != acr && !"".equals(acr) && !" ".equals(acr)) { //$NON-NLS-1$ //$NON-NLS-2$
            //TODO CODE COMMENTED#
            //authenticatorsList = config.getLOA(acr).getAuthentication().getAuthenticatorList()
            //TODO CODE COMMENTED#
            //.get(0).getAuthenticators();
        }
        //TODO CODE COMMENTED#

        return null;
    }

    /**
     * Gets the acr.
     *
     * @param msisdn the msisdn
     * @return the acr
     * @throws IdentityOAuth2Exception the identity o auth2 exception
     */
    public String getACR(String msisdn) throws IdentityOAuth2Exception {

        String strACR = ""; //$NON-NLS-1$
        boolean isRetrievedACR = false;

        // First check if an ACR already exists
        String responseACR = retrieveACR(msisdn);
        if (null != responseACR && !"".equals(responseACR)) { //$NON-NLS-1$
            try {
                if (DEBUG) {
                    log.debug("Response - retrieve ACR : " + responseACR); //$NON-NLS-1$
                }
                strACR = JsonPath.read(responseACR, "$.retriveAcrResponse.acr"); //$NON-NLS-1$
                isRetrievedACR = true;
            } catch (Exception e) {
                log.debug("No existing ACR found."); //$NON-NLS-1$
            }
        }

        // If ACR is not retrieved, create a new one
        if (!isRetrievedACR) {
            String responseNewACR = createACR(msisdn);
            if (null != responseNewACR && !"".equals(responseNewACR)) { //$NON-NLS-1$
                try {
                    if (DEBUG) {
                        log.debug("Response - create ACR : " + responseNewACR); //$NON-NLS-1$
                    }
                    strACR = JsonPath.read(responseNewACR, "$.createAcrResponse.acrInfo[0].acr"); //$NON-NLS-1$
                } catch (Exception e) {
                    log.error("Retrieving/creating processes of ACR failed", e); //$NON-NLS-1$
                    throw new IdentityOAuth2Exception("Retrieving/creating processes of ACR failed", e); //$NON-NLS-1$
                }
            }
        }

        return strACR;
    }

    private String getPCR(String msisdn, String applicationClientId, String callbackUrl) throws PCRException {

        log.info("Generating PCR");
        PCRFactory pcrFactory = new PCRFactory();
        //String userUUID = MsisdnUtil.getUuidFromMsisdn(msisdn);
        String sectorId = SectorUtil.getSectorIdFromUrl(callbackUrl);
        RequestDTO requestDTO = new RequestDTO(msisdn, applicationClientId, sectorId);
        PCRGeneratable pcrGeneratable = OpenIdTokenBuilderDataHolder.getInstance().getPcrGeneratable();

        Returnable pcr = pcrGeneratable.getPCR(requestDTO);
        return pcr.getID();
    }

    private String createLocalACR(String msisdn, String serviceProvider)
            throws InvalidKeyException, NoSuchAlgorithmException {
        String acr = null;
        String keyText = "cY4L3dBf@mifenew";

        byte[] keyValue = keyText.getBytes();

        SecretKey key = new SecretKeySpec(keyValue, "AES");
        String encryptedText = "";
        Cipher cipher = null;

        try {
            cipher = Cipher.getInstance("AES");
        } catch (NoSuchPaddingException ex) {
            Logger.getLogger(MIFEOpenIDTokenBuilder.class.getName()).log(Level.SEVERE, null, ex);
        }

        if (serviceProvider != null) {
            byte[] plainTextByte = (serviceProvider + msisdn).getBytes();
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptedByte = null;
            try {
                encryptedByte = cipher.doFinal(plainTextByte);
            } catch (IllegalBlockSizeException ex) {
                Logger.getLogger(MIFEOpenIDTokenBuilder.class.getName()).log(Level.SEVERE, null, ex);
            } catch (BadPaddingException ex) {
                Logger.getLogger(MIFEOpenIDTokenBuilder.class.getName()).log(Level.SEVERE, null, ex);
            }
            encryptedText = Base64.encodeBase64String(encryptedByte);
        } else {
            ///nop
        }

        if (log.isDebugEnabled()) {
            log.info("Encrypted Text : " + encryptedText);
        }
        String encryptedPcr = encryptedText.replaceAll("\r", "").replaceAll("\n", "");

        return encryptedPcr;

    }

    /**
     * Retrieve acr.
     *
     * @param msisdn the msisdn
     * @return the string
     * @throws IdentityOAuth2Exception the identity o auth2 exception
     */
    public String retrieveACR(String msisdn) throws IdentityOAuth2Exception {

        StringBuilder requestURLBuilder = new StringBuilder();
        requestURLBuilder.append(ACR_HOST_URI);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(RETRIEVE_SERVICE);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(SERVICE_PROVIDER);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(acrAppID);
        String requestURL = requestURLBuilder.toString();

        JSONObject requestBody = new JSONObject();
        JSONObject retrieveRequest = null;

        try {
            requestBody.put("MSISDN", msisdn); //$NON-NLS-1$
            retrieveRequest = new JSONObject().put("retriveAcrRequest", requestBody); //$NON-NLS-1$
            StringRequestEntity requestEntity = new StringRequestEntity(retrieveRequest.toString(),
                    "application/json", "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
            PostMethod postMethod = new PostMethod(requestURL);
            postMethod.addRequestHeader(new Header("Authorization-ACR", "ServiceKey " + SERVICE_KEY)); //$NON-NLS-1$
            // $NON-NLS-2$
            postMethod.addRequestHeader("Authorization", "Bearer " + ACR_ACCESS_TOKEN); //$NON-NLS-1$ //$NON-NLS-2$
            postMethod.setRequestEntity(requestEntity);

            if (DEBUG) {
                log.debug("Connecting to ACR engine @ " + ACR_HOST_URI); //$NON-NLS-1$
                log.debug("Service name : " + RETRIEVE_SERVICE); //$NON-NLS-1$
                log.debug("Service provider : " + SERVICE_PROVIDER); //$NON-NLS-1$
                log.debug("App key : " + acrAppID); //$NON-NLS-1$
                log.debug("Request - retrieve ACR : " + requestEntity.getContent()); //$NON-NLS-1$
            }

            httpClient = new HttpClient();
            httpClient.executeMethod(postMethod);

            return new String(postMethod.getResponseBody(), "UTF-8"); //$NON-NLS-1$

        } catch (UnsupportedEncodingException e) {
            log.error("Error occured while creating request", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating request", e); //$NON-NLS-1$
        } catch (JSONException e) {
            log.error("Error occured while creating request", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating request", e); //$NON-NLS-1$
        } catch (HttpException e) {
            log.error("Error occured while retrieving ACR", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while retrieving ACR", e); //$NON-NLS-1$
        } catch (IOException e) {
            log.error("Error occured while retrieving ACR", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while retrieving ACR", e); //$NON-NLS-1$
        }
    }

    /**
     * Creates the acr.
     *
     * @param msisdn the msisdn
     * @return the string
     * @throws IdentityOAuth2Exception the identity o auth2 exception
     */
    public String createACR(String msisdn) throws IdentityOAuth2Exception {

        StringBuilder requestURLBuilder = new StringBuilder();
        requestURLBuilder.append(ACR_HOST_URI);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(CREATE_SERVICE);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(SERVICE_PROVIDER);
        requestURLBuilder.append("/"); //$NON-NLS-1$
        requestURLBuilder.append(acrAppID);
        String requestURL = requestURLBuilder.toString();

        JSONObject requestBody = new JSONObject();
        JSONObject createRequest = null;

        try {
            requestBody.put("MSISDN", (Object) new JSONArray().put(msisdn)); //$NON-NLS-1$
            createRequest = new JSONObject().put("createAcrRequest", requestBody); //$NON-NLS-1$
            StringRequestEntity requestEntity = new StringRequestEntity(createRequest.toString(),
                    "application/json", "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
            PostMethod postMethod = new PostMethod(requestURL);
            postMethod.addRequestHeader("Authorization-ACR", "ServiceKey " + SERVICE_KEY); //$NON-NLS-1$ //$NON-NLS-2$
            postMethod.addRequestHeader("Authorization", "Bearer " + ACR_ACCESS_TOKEN); //$NON-NLS-1$ //$NON-NLS-2$
            postMethod.setRequestEntity(requestEntity);

            if (DEBUG) {
                log.debug("Connecting to ACR engine @ " + ACR_HOST_URI); //$NON-NLS-1$
                log.debug("Service name : " + CREATE_SERVICE); //$NON-NLS-1$
                log.debug("Service provider : " + SERVICE_PROVIDER); //$NON-NLS-1$
                log.debug("App key : " + acrAppID); //$NON-NLS-1$
                log.debug("Request - create ACR : " + requestEntity.getContent()); //$NON-NLS-1$
            }

            httpClient = new HttpClient();
            httpClient.executeMethod(postMethod);

            return new String(postMethod.getResponseBody(), "UTF-8"); //$NON-NLS-1$

        } catch (UnsupportedEncodingException e) {
            log.error("Error occured while creating request", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating request", e); //$NON-NLS-1$
        } catch (JSONException e) {
            log.error("Error occured while creating request", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating request", e); //$NON-NLS-1$
        } catch (HttpException e) {
            log.error("Error occured while creating ACR", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating ACR", e); //$NON-NLS-1$
        } catch (IOException e) {
            log.error("Error occured while creating ACR", e); //$NON-NLS-1$
            throw new IdentityOAuth2Exception("Error occured while creating ACR", e); //$NON-NLS-1$
        }
    }

    /* (non-Javadoc)
     * @see org.wso2.carbon.identity.openidconnect.IDTokenBuilder#buildIDToken(org.wso2.carbon.identity.oauth2.authz
     * .OAuthAuthzReqMessageContext, org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeRespDTO)
     */
    public String buildIDToken(OAuthAuthzReqMessageContext tokReqMsgCtx, OAuth2AuthorizeRespDTO tokenRespDTO)
            throws IdentityOAuth2Exception {
        // TODO Auto-generated method stub
        return null;
    }

    private String initiateFederatedIDTokenProcess(OAuthTokenReqMessageContext request,
            OAuth2AccessTokenRespDTO tokenRespDTO) throws Exception {
        String[] jwttoken = tokenRespDTO.getIDToken().split("\\.");
        byte[] decoded = Base64.decodeBase64(jwttoken[1]);
        String jwtbody = new String(decoded);
        org.codehaus.jettison.json.JSONObject jwtobj = null;
        CustomIDTokenBuilder builder = new CustomIDTokenBuilder();

        jwtobj = new org.codehaus.jettison.json.JSONObject(jwtbody);
        builder = prepareGeneralTokenBuilder(request, tokenRespDTO, builder);
        builder = prepareFederatedTokenBuilder(jwtobj, builder);

        String plainIDToken = builder.buildIDToken();
        if (mobileConnectConfig.getDataPublisher().isEnabled()) {

            Map<String, String> tokenMap = prepareGeneralFederatedTokenObject(request, tokenRespDTO);
            tokenMap = prepareFederatedTokenObject(plainIDToken, jwtobj, tokenMap);
            if (DEBUG) {
                for (Map.Entry<String, String> entry : tokenMap.entrySet()) {
                    log.debug(entry.getKey() + " : " + entry.getValue());
                }
            }
            DataPublisherUtil.publishTokenEndpointData(tokenMap);
        }

        return new PlainJWT((com.nimbusds.jwt.JWTClaimsSet) PlainJWT.parse(plainIDToken).getJWTClaimsSet())
                .serialize();

    }

    private Map<String, String> prepareGeneralFederatedTokenObject(OAuthTokenReqMessageContext request,
            OAuth2AccessTokenRespDTO tokenRespDTO) throws IdentityOAuth2Exception {
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("Timestamp", String.valueOf(new java.util.Date().getTime()));
        tokenMap.put("AuthenticatedUser", request.getAuthorizedUser().toString());
        tokenMap.put("AuthenticationCode", request.getOauth2AccessTokenReqDTO().getAuthorizationCode());
        tokenMap.put("AccessToken", tokenRespDTO.getAccessToken());
        tokenMap.put("ClientId", request.getOauth2AccessTokenReqDTO().getClientId());
        tokenMap.put("RefreshToken", tokenRespDTO.getRefreshToken());
        tokenMap.put(SESSIONID, getValuesFromCacheForFederatedIDP(request, SESSIONID));
        tokenMap.put("State", getValuesFromCacheForFederatedIDP(request, "state"));
        tokenMap.put("TokenClaims", getClaimValues(request));
        if (tokenRespDTO.getAccessToken() != null) {
            tokenMap.put("StatusCode", "200");
        } else {
            tokenMap.put("StatusCode", "400");
        }
        return tokenMap;
    }

    private String getValuesFromCacheForFederatedIDP(OAuthTokenReqMessageContext request, String key)
            throws IdentityOAuth2Exception {

        AuthorizationGrantCacheKey authorizationGrantCacheKey = new AuthorizationGrantCacheKey(
                request.getOauth2AccessTokenReqDTO().getAuthorizationCode());
        AuthorizationGrantCacheEntry authorizationGrantCacheEntry = AuthorizationGrantCache.getInstance()
                .getValueFromCache(authorizationGrantCacheKey);

        ClaimMapping acrKey = getValueFromCacheClaims(authorizationGrantCacheEntry, key);

        if (acrKey == null)
            throw new IdentityOAuth2Exception("Error occured while retrieving " + key + " from cache");

        return authorizationGrantCacheEntry.getUserAttributes().get(acrKey);

    }

    private ClaimMapping getValueFromCacheClaims(AuthorizationGrantCacheEntry authorizationGrantCacheEntry,
            String key) {
        Map<ClaimMapping, String> userAttributes = authorizationGrantCacheEntry.getUserAttributes();
        ClaimMapping acrKey = null;
        for (Map.Entry<ClaimMapping, String> entry : userAttributes.entrySet()) {
            ClaimMapping mapping = entry.getKey();
            if (mapping.getLocalClaim() != null && mapping.getLocalClaim().getClaimUri().equals(key))
                acrKey = mapping;
        }
        return acrKey;
    }

    private Map<String, String> prepareFederatedTokenObject(String plainIDToken,
            org.codehaus.jettison.json.JSONObject jwtobj, Map<String, String> tokenMap)
            throws org.codehaus.jettison.json.JSONException {

        tokenMap.put("Nonce", jwtobj.get(IDToken.NONCE).toString());
        tokenMap.put("Amr", jwtobj.getJSONArray("amr").toString());
        tokenMap.put("Content-Type", "application/x-www-form-urlencoded");
        tokenMap.put("ReturnedResult", plainIDToken);

        return tokenMap;
    }

    private CustomIDTokenBuilder prepareFederatedTokenBuilder(org.codehaus.jettison.json.JSONObject jwtobj,
            CustomIDTokenBuilder builder) throws org.codehaus.jettison.json.JSONException {

        builder.setSubject(jwtobj.get(IDToken.SUB).toString());
        builder.setClaim(IDToken.ACR, jwtobj.get(IDToken.ACR).toString());
        builder.setAmr((jwtobj.getJSONArray("amr")));
        builder.setClaim(IDToken.NONCE, jwtobj.get(IDToken.NONCE).toString());

        return builder;
    }

    private CustomIDTokenBuilder prepareGeneralTokenBuilder(OAuthTokenReqMessageContext request,
            OAuth2AccessTokenRespDTO tokenRespDTO, CustomIDTokenBuilder builder) throws IdentityOAuth2Exception {

        String accessTokenIssuedTime = getAccessTokenIssuedTime(tokenRespDTO.getAccessToken(), request);
        String atHash = new String(Base64.encodeBase64(tokenRespDTO.getAccessToken().getBytes()));
        int curTime = (int) Calendar.getInstance().getTimeInMillis();
        OAuthServerConfiguration config = OAuthServerConfiguration.getInstance();
        int lifetime = Integer.parseInt(config.getOpenIDConnectIDTokenExpiration()) * 1000;

        builder.setIssuer(config.getOpenIDConnectIDTokenIssuerIdentifier());
        builder.setAudience(request.getOauth2AccessTokenReqDTO().getClientId());
        builder.setAuthorizedParty(request.getOauth2AccessTokenReqDTO().getClientId());
        builder.setExpiration(curTime + lifetime);
        builder.setIssuedAt(curTime);
        builder.setAtHash(atHash);
        builder.setAuthTime(accessTokenIssuedTime);

        return builder;
    }

    public String getMSISDNbyPcr(String callbackUrl, String pcr) throws PCRException {
        String msisdn = null;

        try {
            if (mobileConnectConfig.isPcrServiceEnabled()) {
                log.info("Retreiving MSISDN by using PCR");
                String sectorId = SectorUtil.getSectorIdFromUrl(callbackUrl);
                PCRGeneratable pcrGeneratable = OpenIdTokenBuilderDataHolder.getInstance().getPcrGeneratable();

                Returnable msisdnByPcr = pcrGeneratable.getMsisdnByPcr(sectorId, pcr);
                msisdn = msisdnByPcr.getID();
            }
            log.info("MSISDN  : " + msisdn);
        } catch (PCRException e) {
            log.error("Error", e);
        }

        return msisdn;
    }

}