org.wso2.carbon.identity.openidconnect.DefaultIDTokenBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.openidconnect.DefaultIDTokenBuilder.java

Source

/*
 * Copyright (c) 2017, 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.openidconnect;

import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.PlainJWT;
import org.apache.axiom.om.OMElement;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.Charsets;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.json.JSONObject;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
import org.wso2.carbon.identity.application.common.model.ClaimConfig;
import org.wso2.carbon.identity.application.common.model.ClaimMapping;
import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig;
import org.wso2.carbon.identity.application.common.model.IdentityProvider;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil;
import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
import org.wso2.carbon.identity.base.IdentityException;
import org.wso2.carbon.identity.core.util.IdentityConfigParser;
import org.wso2.carbon.identity.core.util.IdentityCoreConstants;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheEntry;
import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheKey;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth2.IDTokenValidationFailureException;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeRespDTO;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.idp.mgt.IdentityProviderManagementException;
import org.wso2.carbon.idp.mgt.IdentityProviderManager;
import org.wso2.carbon.user.core.UserCoreConstants;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.core.UserStoreManager;
import org.wso2.carbon.user.core.util.UserCoreUtil;

import javax.xml.namespace.QName;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * This is the IDToken generator for the OpenID Connect Implementation. This
 * IDToken Generator utilizes the Nimbus SDK to build the IDToken.
 */
public class DefaultIDTokenBuilder implements org.wso2.carbon.identity.openidconnect.IDTokenBuilder {
    private static final String SHA384 = "SHA-384";
    private static final String SHA512 = "SHA-512";
    private static final String AUTHORIZATION_CODE = "AuthorizationCode";
    private static final String INBOUND_AUTH2_TYPE = "oauth2";
    private static final String CONFIG_ELEM_OAUTH = "OAuth";
    private static final String OPENID_CONNECT = "OpenIDConnect";
    private static final String OPENID_CONNECT_AUDIENCES = "Audiences";
    private static final String OPENID_CONNECT_AUDIENCE = "Audience";
    private static final String OPENID_IDP_ENTITY_ID = "IdPEntityId";

    private static final Log log = LogFactory.getLog(DefaultIDTokenBuilder.class);
    private static Map<Integer, Key> privateKeys = new ConcurrentHashMap<>();
    private static Map<Integer, Certificate> publicCerts = new ConcurrentHashMap<>();
    private OAuthServerConfiguration config = null;
    private JWSAlgorithm signatureAlgorithm = null;

    private static final String ERROR_GET_RESIDENT_IDP = "Error while getting Resident Identity Provider of '%s' tenant.";

    public DefaultIDTokenBuilder() throws IdentityOAuth2Exception {

        config = OAuthServerConfiguration.getInstance();
        //map signature algorithm from identity.xml to nimbus format, this is a one time configuration
        signatureAlgorithm = OAuth2Util.mapSignatureAlgorithmForJWSAlgorithm(config.getIdTokenSignatureAlgorithm());
    }

    @Override
    public String buildIDToken(OAuthTokenReqMessageContext request, OAuth2AccessTokenRespDTO tokenRespDTO)
            throws IdentityOAuth2Exception {

        String tenantDomain = request.getOauth2AccessTokenReqDTO().getTenantDomain();
        IdentityProvider identityProvider = getResidentIdp(tenantDomain);

        FederatedAuthenticatorConfig[] fedAuthnConfigs = identityProvider.getFederatedAuthenticatorConfigs();

        // Get OIDC authenticator
        FederatedAuthenticatorConfig samlAuthenticatorConfig = IdentityApplicationManagementUtil
                .getFederatedAuthenticator(fedAuthnConfigs, IdentityApplicationConstants.Authenticator.OIDC.NAME);
        String issuer = IdentityApplicationManagementUtil
                .getProperty(samlAuthenticatorConfig.getProperties(), OPENID_IDP_ENTITY_ID).getValue();

        long lifetimeInMillis = Integer.parseInt(config.getOpenIDConnectIDTokenExpiration()) * 1000;
        long curTimeInMillis = Calendar.getInstance().getTimeInMillis();
        // setting subject
        String subject = request.getAuthorizedUser().getAuthenticatedSubjectIdentifier();

        if (!GrantType.AUTHORIZATION_CODE.toString().equals(request.getOauth2AccessTokenReqDTO().getGrantType())
                && !org.wso2.carbon.identity.oauth.common.GrantType.SAML20_BEARER.toString()
                        .equals(request.getOauth2AccessTokenReqDTO().getGrantType())) {

            ApplicationManagementService applicationMgtService = OAuth2ServiceComponentHolder
                    .getApplicationMgtService();
            ServiceProvider serviceProvider = null;

            try {
                String spName = applicationMgtService.getServiceProviderNameByClientId(
                        request.getOauth2AccessTokenReqDTO().getClientId(), INBOUND_AUTH2_TYPE, tenantDomain);
                serviceProvider = applicationMgtService.getApplicationExcludingFileBasedSPs(spName, tenantDomain);
            } catch (IdentityApplicationManagementException e) {
                throw new IdentityOAuth2Exception("Error while getting service provider information.", e);
            }

            if (serviceProvider != null) {
                String subjectClaim = serviceProvider.getLocalAndOutBoundAuthenticationConfig()
                        .getSubjectClaimUri();
                ClaimConfig claimConfig = serviceProvider.getClaimConfig();

                if (claimConfig != null) {
                    boolean isLocalClaimDialect = claimConfig.isLocalClaimDialect();
                    ClaimMapping[] claimMappings = claimConfig.getClaimMappings();

                    if (!isLocalClaimDialect && claimMappings.length > 0) {
                        for (ClaimMapping claimMapping : claimMappings) {
                            if (StringUtils.isNotBlank(subjectClaim) && StringUtils
                                    .equals(claimMapping.getRemoteClaim().getClaimUri(), subjectClaim)) {
                                subjectClaim = claimMapping.getLocalClaim().getClaimUri();
                            }
                        }
                    }
                }

                if (subjectClaim != null) {
                    String username = request.getAuthorizedUser().getUserName();
                    String userStore = request.getAuthorizedUser().getUserStoreDomain();
                    tenantDomain = request.getAuthorizedUser().getTenantDomain();
                    String fqdnUsername = request.getAuthorizedUser().toString();
                    try {
                        UserStoreManager usm = IdentityTenantUtil.getRealm(tenantDomain, fqdnUsername)
                                .getUserStoreManager();
                        subject = usm.getSecondaryUserStoreManager(userStore).getUserClaimValue(username,
                                subjectClaim, null);
                        if (StringUtils.isBlank(subject)) {
                            subject = request.getAuthorizedUser().getAuthenticatedSubjectIdentifier();
                        }
                        boolean useUserstoreDomainInLocalSubjectIdentifier = serviceProvider
                                .getLocalAndOutBoundAuthenticationConfig()
                                .isUseUserstoreDomainInLocalSubjectIdentifier();
                        boolean useTenantDomainInLocalSubjectIdentifier = serviceProvider
                                .getLocalAndOutBoundAuthenticationConfig()
                                .isUseTenantDomainInLocalSubjectIdentifier();
                        if (useTenantDomainInLocalSubjectIdentifier) {
                            subject = UserCoreUtil.addTenantDomainToEntry(subject, tenantDomain);
                        }
                        if (useUserstoreDomainInLocalSubjectIdentifier) {
                            subject = IdentityUtil.addDomainToName(subject, userStore);
                        }
                    } catch (IdentityException e) {
                        String error = "Error occurred while getting user claim for user "
                                + request.getAuthorizedUser().toString() + ", claim " + subjectClaim;
                        throw new IdentityOAuth2Exception(error, e);
                    } catch (UserStoreException e) {
                        if (e.getMessage().contains("UserNotFound")) {
                            if (log.isDebugEnabled()) {
                                log.debug("User " + username + " not found in user store " + userStore
                                        + " in tenant " + tenantDomain);
                            }
                            subject = request.getAuthorizedUser().toString();
                        } else {
                            String error = "Error occurred while getting user claim for user "
                                    + request.getAuthorizedUser().toString() + ", claim " + subjectClaim;
                            throw new IdentityOAuth2Exception(error, e);
                        }

                    }
                }
            }
        }

        String nonceValue = null;
        long authTime = 0;

        LinkedHashSet acrValue = new LinkedHashSet();
        // AuthorizationCode only available for authorization code grant type
        if (request.getProperty(AUTHORIZATION_CODE) != null) {
            AuthorizationGrantCacheEntry authorizationGrantCacheEntry = getAuthorizationGrantCacheEntry(request);
            if (authorizationGrantCacheEntry != null) {
                nonceValue = authorizationGrantCacheEntry.getNonceValue();
                acrValue = authorizationGrantCacheEntry.getAcrValue();
                if (authorizationGrantCacheEntry.getEssentialClaims() != null) {
                    if (OAuth2Util.getEssentialClaims(authorizationGrantCacheEntry.getEssentialClaims(),
                            OAuthConstants.ID_TOKEN).contains(OAuthConstants.OAuth20Params.AUTH_TIME)) {
                        authTime = authorizationGrantCacheEntry.getAuthTime();
                    }
                }
            }
        }

        String atHash = null;
        if (!JWSAlgorithm.NONE.getName().equals(signatureAlgorithm.getName())) {
            String digAlg = OAuth2Util.mapDigestAlgorithm(signatureAlgorithm);
            MessageDigest md;
            try {
                md = MessageDigest.getInstance(digAlg);
            } catch (NoSuchAlgorithmException e) {
                throw new IdentityOAuth2Exception("Invalid Algorithm : " + digAlg);
            }
            md.update(tokenRespDTO.getAccessToken().getBytes(Charsets.UTF_8));
            byte[] digest = md.digest();
            int leftHalfBytes = 16;
            if (SHA384.equals(digAlg)) {
                leftHalfBytes = 24;
            } else if (SHA512.equals(digAlg)) {
                leftHalfBytes = 32;
            }
            byte[] leftmost = new byte[leftHalfBytes];
            for (int i = 0; i < leftHalfBytes; i++) {
                leftmost[i] = digest[i];
            }
            atHash = new String(Base64.encodeBase64URLSafe(leftmost), Charsets.UTF_8);
        }

        if (log.isDebugEnabled()) {
            StringBuilder stringBuilder = (new StringBuilder()).append("Using issuer ").append(issuer).append("\n")
                    .append("Subject ").append(subject).append("\n").append("ID Token life time ")
                    .append(lifetimeInMillis / 1000).append("\n").append("Current time ")
                    .append(curTimeInMillis / 1000).append("\n").append("Nonce Value ").append(nonceValue)
                    .append("\n").append("Signature Algorithm ").append(signatureAlgorithm).append("\n");
            log.debug(stringBuilder.toString());
        }

        ArrayList<String> audience = new ArrayList<String>();
        audience.add(request.getOauth2AccessTokenReqDTO().getClientId());
        if (CollectionUtils.isNotEmpty(getOIDCEndpointUrl())) {
            audience.addAll(getOIDCEndpointUrl());
        }

        JWTClaimsSet jwtClaimsSet = new JWTClaimsSet();
        jwtClaimsSet.setIssuer(issuer);
        jwtClaimsSet.setAudience(audience);
        jwtClaimsSet.setClaim("azp", request.getOauth2AccessTokenReqDTO().getClientId());
        jwtClaimsSet.setExpirationTime(new Date(curTimeInMillis + lifetimeInMillis));
        jwtClaimsSet.setIssueTime(new Date(curTimeInMillis));
        if (authTime != 0) {
            jwtClaimsSet.setClaim("auth_time", authTime / 1000);
        }
        if (atHash != null) {
            jwtClaimsSet.setClaim("at_hash", atHash);
        }
        if (nonceValue != null) {
            jwtClaimsSet.setClaim("nonce", nonceValue);
        }
        if (acrValue != null) {
            jwtClaimsSet.setClaim("acr", "urn:mace:incommon:iap:silver");
        }

        request.addProperty(OAuthConstants.ACCESS_TOKEN, tokenRespDTO.getAccessToken());
        request.addProperty(MultitenantConstants.TENANT_DOMAIN,
                request.getOauth2AccessTokenReqDTO().getTenantDomain());
        CustomClaimsCallbackHandler claimsCallBackHandler = OAuthServerConfiguration.getInstance()
                .getOpenIDConnectCustomClaimsCallbackHandler();
        claimsCallBackHandler.handleCustomClaims(jwtClaimsSet, request);
        jwtClaimsSet.setSubject(subject);
        if (!isValidIdToken(jwtClaimsSet)) {
            throw new IDTokenValidationFailureException("Error while validating JWT token for required claims");
        }
        if (JWSAlgorithm.NONE.getName().equals(signatureAlgorithm.getName())) {
            return new PlainJWT(jwtClaimsSet).serialize();
        }

        boolean isJWTSignedWithSPKey = OAuthServerConfiguration.getInstance().isJWTSignedWithSPKey();
        String signingTenantDomain;
        if (isJWTSignedWithSPKey) {
            signingTenantDomain = (String) request.getProperty(MultitenantConstants.TENANT_DOMAIN);
        } else {
            signingTenantDomain = request.getAuthorizedUser().getTenantDomain();
        }

        return OAuth2Util.signJWT(jwtClaimsSet, signatureAlgorithm, signingTenantDomain).serialize();
    }

    @Override
    public String buildIDToken(OAuthAuthzReqMessageContext request, OAuth2AuthorizeRespDTO tokenRespDTO)
            throws IdentityOAuth2Exception {

        String tenantDomain = request.getAuthorizationReqDTO().getTenantDomain();
        IdentityProvider identityProvider = getResidentIdp(tenantDomain);

        FederatedAuthenticatorConfig[] fedAuthnConfigs = identityProvider.getFederatedAuthenticatorConfigs();

        // Get OIDC authenticator
        FederatedAuthenticatorConfig samlAuthenticatorConfig = IdentityApplicationManagementUtil
                .getFederatedAuthenticator(fedAuthnConfigs, IdentityApplicationConstants.Authenticator.OIDC.NAME);
        String issuer = IdentityApplicationManagementUtil
                .getProperty(samlAuthenticatorConfig.getProperties(), OPENID_IDP_ENTITY_ID).getValue();

        long lifetimeInMillis = Integer.parseInt(config.getOpenIDConnectIDTokenExpiration()) * 1000;
        long curTimeInMillis = Calendar.getInstance().getTimeInMillis();
        // setting subject
        String subject = request.getAuthorizationReqDTO().getUser().getAuthenticatedSubjectIdentifier();

        String nonceValue = request.getAuthorizationReqDTO().getNonce();
        LinkedHashSet acrValue = request.getAuthorizationReqDTO().getACRValues();

        String atHash = null;
        String responseType = request.getAuthorizationReqDTO().getResponseType();
        //at_hash is generated on access token. Hence the check on response type to be id_token token or code
        if (!JWSAlgorithm.NONE.getName().equals(signatureAlgorithm.getName())
                && !OAuthConstants.ID_TOKEN.equalsIgnoreCase(responseType)
                && !OAuthConstants.NONE.equalsIgnoreCase(responseType)) {
            String digAlg = OAuth2Util.mapDigestAlgorithm(signatureAlgorithm);
            MessageDigest md;
            try {
                md = MessageDigest.getInstance(digAlg);
            } catch (NoSuchAlgorithmException e) {
                throw new IdentityOAuth2Exception("Invalid Algorithm : " + digAlg);
            }
            md.update(tokenRespDTO.getAccessToken().getBytes(Charsets.UTF_8));
            byte[] digest = md.digest();
            int leftHalfBytes = 16;
            if (SHA384.equals(digAlg)) {
                leftHalfBytes = 24;
            } else if (SHA512.equals(digAlg)) {
                leftHalfBytes = 32;
            }
            byte[] leftmost = new byte[leftHalfBytes];
            for (int i = 0; i < leftHalfBytes; i++) {
                leftmost[i] = digest[i];
            }
            atHash = new String(Base64.encodeBase64URLSafe(leftmost), Charsets.UTF_8);
        }

        if (log.isDebugEnabled()) {
            StringBuilder stringBuilder = (new StringBuilder()).append("Using issuer ").append(issuer).append("\n")
                    .append("Subject ").append(subject).append("\n").append("ID Token life time ")
                    .append(lifetimeInMillis / 1000).append("\n").append("Current time ")
                    .append(curTimeInMillis / 1000).append("\n").append("Nonce Value ").append(nonceValue)
                    .append("\n").append("Signature Algorithm ").append(signatureAlgorithm).append("\n");
            if (log.isDebugEnabled()) {
                log.debug(stringBuilder.toString());
            }
        }

        ArrayList<String> audience = new ArrayList<String>();
        audience.add(request.getAuthorizationReqDTO().getConsumerKey());
        if (CollectionUtils.isNotEmpty(getOIDCEndpointUrl())) {
            audience.addAll(getOIDCEndpointUrl());
        }

        JWTClaimsSet jwtClaimsSet = new JWTClaimsSet();
        jwtClaimsSet.setIssuer(issuer);
        jwtClaimsSet.setAudience(audience);
        jwtClaimsSet.setClaim("azp", request.getAuthorizationReqDTO().getConsumerKey());
        jwtClaimsSet.setExpirationTime(new Date(curTimeInMillis + lifetimeInMillis));
        jwtClaimsSet.setIssueTime(new Date(curTimeInMillis));
        if (request.getAuthorizationReqDTO().getAuthTime() != 0) {
            jwtClaimsSet.setClaim("auth_time", request.getAuthorizationReqDTO().getAuthTime() / 1000);
        }
        if (atHash != null) {
            jwtClaimsSet.setClaim("at_hash", atHash);
        }
        if (nonceValue != null) {
            jwtClaimsSet.setClaim("nonce", nonceValue);
        }
        if (acrValue != null) {
            jwtClaimsSet.setClaim("acr", "urn:mace:incommon:iap:silver");
        }

        request.addProperty(OAuthConstants.ACCESS_TOKEN, tokenRespDTO.getAccessToken());
        request.addProperty(MultitenantConstants.TENANT_DOMAIN, request.getAuthorizationReqDTO().getTenantDomain());
        CustomClaimsCallbackHandler claimsCallBackHandler = OAuthServerConfiguration.getInstance()
                .getOpenIDConnectCustomClaimsCallbackHandler();
        claimsCallBackHandler.handleCustomClaims(jwtClaimsSet, request);
        jwtClaimsSet.setSubject(subject);
        if (JWSAlgorithm.NONE.getName().equals(signatureAlgorithm.getName())) {
            return new PlainJWT(jwtClaimsSet).serialize();
        }

        boolean isJWTSignedWithSPKey = OAuthServerConfiguration.getInstance().isJWTSignedWithSPKey();
        String signingTenantDomain;
        if (isJWTSignedWithSPKey) {
            signingTenantDomain = (String) request.getProperty(MultitenantConstants.TENANT_DOMAIN);
        } else {
            signingTenantDomain = request.getAuthorizationReqDTO().getUser().getTenantDomain();
        }

        return OAuth2Util.signJWT(jwtClaimsSet, signatureAlgorithm, signingTenantDomain).serialize();
    }

    /**
     * sign JWT token from RSA algorithm
     *
     * @param jwtClaimsSet contains JWT body
     * @param request
     * @return signed JWT token
     * @throws IdentityOAuth2Exception
     */
    @Deprecated
    protected String signJWTWithRSA(JWTClaimsSet jwtClaimsSet, OAuthTokenReqMessageContext request)
            throws IdentityOAuth2Exception {
        String tenantDomain = null;
        boolean isJWTSignedWithSPKey = OAuthServerConfiguration.getInstance().isJWTSignedWithSPKey();
        if (isJWTSignedWithSPKey) {
            tenantDomain = (String) request.getProperty(MultitenantConstants.TENANT_DOMAIN);
        } else {
            tenantDomain = request.getAuthorizedUser().getTenantDomain();
        }
        return OAuth2Util.signJWTWithRSA(jwtClaimsSet, signatureAlgorithm, tenantDomain).serialize();
    }

    /**
     * sign JWT token from RSA algorithm
     *
     * @param jwtClaimsSet contains JWT body
     * @param request
     * @return signed JWT token
     * @throws IdentityOAuth2Exception
     */
    @Deprecated
    protected String signJWTWithRSA(JWTClaimsSet jwtClaimsSet, OAuthAuthzReqMessageContext request)
            throws IdentityOAuth2Exception {
        String tenantDomain = null;
        boolean isJWTSignedWithSPKey = OAuthServerConfiguration.getInstance().isJWTSignedWithSPKey();
        if (isJWTSignedWithSPKey) {
            tenantDomain = (String) request.getProperty(MultitenantConstants.TENANT_DOMAIN);
        } else {
            tenantDomain = request.getAuthorizationReqDTO().getUser().getTenantDomain();
        }
        return OAuth2Util.signJWTWithRSA(jwtClaimsSet, signatureAlgorithm, tenantDomain).serialize();
    }

    /**
     * @param request
     * @return AuthorizationGrantCacheEntry contains user attributes and nonce value
     */
    private AuthorizationGrantCacheEntry getAuthorizationGrantCacheEntry(OAuthTokenReqMessageContext request) {

        String authorizationCode = (String) request.getProperty(AUTHORIZATION_CODE);
        AuthorizationGrantCacheKey authorizationGrantCacheKey = new AuthorizationGrantCacheKey(authorizationCode);
        AuthorizationGrantCacheEntry authorizationGrantCacheEntry = (AuthorizationGrantCacheEntry) AuthorizationGrantCache
                .getInstance().getValueFromCacheByCode(authorizationGrantCacheKey);
        return authorizationGrantCacheEntry;
    }

    /**
     * Generic Signing function
     *
     * @param jwtClaimsSet contains JWT body
     * @param request
     * @return signed JWT token
     * @throws IdentityOAuth2Exception
     */
    @Deprecated
    protected String signJWT(JWTClaimsSet jwtClaimsSet, OAuthTokenReqMessageContext request)
            throws IdentityOAuth2Exception {

        if (JWSAlgorithm.RS256.equals(signatureAlgorithm) || JWSAlgorithm.RS384.equals(signatureAlgorithm)
                || JWSAlgorithm.RS512.equals(signatureAlgorithm)) {
            return signJWTWithRSA(jwtClaimsSet, request);
        } else if (JWSAlgorithm.HS256.equals(signatureAlgorithm) || JWSAlgorithm.HS384.equals(signatureAlgorithm)
                || JWSAlgorithm.HS512.equals(signatureAlgorithm)) {
            // return signWithHMAC(jwtClaimsSet,jwsAlgorithm,request); implementation need to be done
            return null;
        } else {
            // return signWithEC(jwtClaimsSet,jwsAlgorithm,request); implementation need to be done
            return null;
        }
    }

    /**
     * Generic Signing function
     *
     * @param jwtClaimsSet contains JWT body
     * @param request
     * @return signed JWT token
     * @throws IdentityOAuth2Exception
     */
    @Deprecated
    protected String signJWT(JWTClaimsSet jwtClaimsSet, OAuthAuthzReqMessageContext request)
            throws IdentityOAuth2Exception {

        if (JWSAlgorithm.RS256.equals(signatureAlgorithm) || JWSAlgorithm.RS384.equals(signatureAlgorithm)
                || JWSAlgorithm.RS512.equals(signatureAlgorithm)) {
            return signJWTWithRSA(jwtClaimsSet, request);
        } else if (JWSAlgorithm.HS256.equals(signatureAlgorithm) || JWSAlgorithm.HS384.equals(signatureAlgorithm)
                || JWSAlgorithm.HS512.equals(signatureAlgorithm)) {
            // return signWithHMAC(jwtClaimsSet,jwsAlgorithm,request); implementation need to be done
            return null;
        } else {
            // return signWithEC(jwtClaimsSet,jwsAlgorithm,request); implementation need to be done
            return null;
        }
    }

    /**
     * This method map signature algorithm define in identity.xml to nimbus
     * signature algorithm
     * format, Strings are defined inline hence there are not being used any
     * where
     *
     * @param signatureAlgorithm signature algorithm
     * @return mapped JWSAlgorithm
     * @throws IdentityOAuth2Exception
     */
    @Deprecated
    protected JWSAlgorithm mapSignatureAlgorithm(String signatureAlgorithm) throws IdentityOAuth2Exception {
        return OAuth2Util.mapSignatureAlgorithmForJWSAlgorithm(signatureAlgorithm);
    }

    /**
     * This method maps signature algorithm define in identity.xml to digest algorithms to generate the at_hash
     *
     * @param signatureAlgorithm signature algorithm
     * @return mapped digest algorithm
     * @throws IdentityOAuth2Exception
     */
    @Deprecated
    protected String mapDigestAlgorithm(Algorithm signatureAlgorithm) throws IdentityOAuth2Exception {
        return OAuth2Util.mapDigestAlgorithm(signatureAlgorithm);
    }

    private List<String> getOIDCEndpointUrl() {
        List<String> OIDCEntityId = getOIDCAudiences();
        return OIDCEntityId;
    }

    private List<String> getOIDCAudiences() {
        List<String> audiences = new ArrayList<String>();
        IdentityConfigParser configParser = IdentityConfigParser.getInstance();
        OMElement oauthElem = configParser.getConfigElement(CONFIG_ELEM_OAUTH);

        if (oauthElem == null) {
            warnOnFaultyConfiguration("OAuth element is not available.");
            return Collections.EMPTY_LIST;
        }
        OMElement configOpenIDConnect = oauthElem.getFirstChildWithName(getQNameWithIdentityNS(OPENID_CONNECT));

        if (configOpenIDConnect == null) {
            warnOnFaultyConfiguration("OpenID element is not available.");
            return Collections.EMPTY_LIST;
        }
        OMElement configAudience = configOpenIDConnect
                .getFirstChildWithName(getQNameWithIdentityNS(OPENID_CONNECT_AUDIENCES));

        if (configAudience == null) {
            return Collections.EMPTY_LIST;
        }

        Iterator<OMElement> iterator = configAudience
                .getChildrenWithName(getQNameWithIdentityNS(OPENID_CONNECT_AUDIENCE));
        while (iterator.hasNext()) {
            OMElement supportedAudience = iterator.next();
            String supportedAudienceName = null;

            if (supportedAudience != null) {
                supportedAudienceName = IdentityUtil.fillURLPlaceholders(supportedAudience.getText());
            }
            if (StringUtils.isNotBlank(supportedAudienceName)) {
                audiences.add(supportedAudienceName);
            }
        }
        return audiences;
    }

    private void warnOnFaultyConfiguration(String logMsg) {
        log.warn("Error in OAuth Configuration. " + logMsg);
    }

    private QName getQNameWithIdentityNS(String localPart) {
        return new QName(IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, localPart);
    }

    private IdentityProvider getResidentIdp(String tenantDomain) throws IdentityOAuth2Exception {
        try {
            return IdentityProviderManager.getInstance().getResidentIdP(tenantDomain);
        } catch (IdentityProviderManagementException e) {
            String errorMsg = String.format(ERROR_GET_RESIDENT_IDP, tenantDomain);
            throw new IdentityOAuth2Exception(errorMsg, e);
        }
    }

    /**
     * Method to check whether id token contains the required claims(iss,sub,aud,exp,iat) defined by the oidc spec
     *
     * @param jwtClaimsSet jwt claim set
     * @return true or false(whether id token contains the required claims)
     */
    private boolean isValidIdToken(JWTClaimsSet jwtClaimsSet) {

        boolean isValidIdToken = true;
        if (StringUtils.isBlank(jwtClaimsSet.getIssuer())) {
            log.error("ID token does not have required issuer claim");
            isValidIdToken = false;
        }
        if (StringUtils.isBlank(jwtClaimsSet.getSubject())) {
            log.error("ID token does not have required subject claim");
            isValidIdToken = false;
        }
        if (jwtClaimsSet.getAudience() == null) {
            log.error("ID token does not have required audience claim");
            isValidIdToken = false;
        }
        if (jwtClaimsSet.getExpirationTime() == null) {
            log.error("ID token does not have required expiration time claim");
            isValidIdToken = false;
        }
        if (jwtClaimsSet.getIssueTime() == null) {
            log.error("ID token does not have required issued time claim");
            isValidIdToken = false;
        }
        return isValidIdToken;
    }
}