Skip to content

Commit

Permalink
Encrypt totp secret before adding to locally mapped user during JIT p…
Browse files Browse the repository at this point in the history
…rovisioning
  • Loading branch information
ZiyamSanthosh committed Jan 26, 2024
1 parent 3df0421 commit de2969b
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.Config.SEND_MANUALLY_ADDED_LOCAL_ROLES_OF_IDP;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.Config.SEND_ONLY_LOCALLY_MAPPED_ROLES_OF_IDP;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.EMAIL_ADDRESS_CLAIM;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_ENCRYPTING_TOTP_SECRET_KEY;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_GETTING_IDP_BY_NAME;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_GETTING_REALM_IN_POST_AUTHENTICATION;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_TRYING_TO_GET_CLAIMS_WHILE_TRYING_TO_PASSWORD_PROVISION;
Expand Down Expand Up @@ -856,9 +857,21 @@ private void callDefaultProvisioningHandler(String username, AuthenticationConte
If TOTP is enabled for federated users, the initial federated user login will be identified with the following
check and will set the secret key claim for the federated user who is going to be provisioned.
*/
if (context.getProperty(FrameworkConstants.SECRET_KEY_CLAIM_URL) != null) {
localClaimValues.put(FrameworkConstants.SECRET_KEY_CLAIM_URL,
context.getProperty(FrameworkConstants.SECRET_KEY_CLAIM_URL).toString());
String totpSecretKeyClaimUrl = FrameworkConstants.SECRET_KEY_CLAIM_URL;
try {
if (context.getProperty(totpSecretKeyClaimUrl) != null) {
String totpSecretKeyClaimValue = context.getProperty(totpSecretKeyClaimUrl).toString();
/*
The secret key sent through the context will be a decrypted value. Therefore, it is required to encrypt
the secret key before storing it in the user store.
*/
totpSecretKeyClaimValue = FrameworkUtils.getProcessedClaimValue(totpSecretKeyClaimUrl,
totpSecretKeyClaimValue, context.getTenantDomain());
localClaimValues.put(totpSecretKeyClaimUrl, totpSecretKeyClaimValue);
}
} catch (FrameworkException e) {
handleExceptions(String.format(ERROR_WHILE_ENCRYPTING_TOTP_SECRET_KEY.getMessage(), username),
ERROR_WHILE_ENCRYPTING_TOTP_SECRET_KEY.getCode(), e);
}

// Remove role claim from local claims as roles are specifically handled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ public abstract class FrameworkConstants {
public static final String JIT_PROVISIONING_FLOW = "JITProvisioningFlow";
public static final String ALLOW_LOGIN_TO_IDP = "JITProvisioning.AllowLoginToIDP";
public static final String SECRET_KEY_CLAIM_URL = "http://wso2.org/claims/identity/secretkey";
public static final String ENABLE_ENCRYPTION = "EnableEncryption";
public static final String TOTP_KEY = "CryptoService.TotpSecret";
public static final String IDP_RESOURCE_ID = "IDPResourceID";
public static final String ENABLE_JIT_PROVISION_ENHANCE_FEATURE = "JITProvisioning.EnableEnhancedFeature";
public static final String ERROR_CODE_INVALID_ATTRIBUTE_UPDATE = "SUO-10000";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public enum ErrorMessages {
"Authenticated user id is null."),
ERROR_WHILE_TRYING_TO_HANDLE_ROLE_CLAIM_FOR_PROVISIONED_USER("80030", "Error while trying to handle role "
+ "claim for provisioned user."),
ERROR_WHILE_ENCRYPTING_TOTP_SECRET_KEY("80031", "Error while encrypting TOTP secret key for user. %s"),
MISMATCHING_TENANT_DOMAIN("AFW-60001",
"Service Provider tenant domain must be equal to user tenant domain for non-SaaS applications"),
SYSTEM_ERROR_WHILE_AUTHENTICATING("AFW-65001", "System error while authenticating");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@
import org.json.JSONObject;
import org.slf4j.MDC;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.claim.mgt.ClaimManagementException;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.SameSiteCookie;
import org.wso2.carbon.core.util.CryptoException;
import org.wso2.carbon.core.util.CryptoUtil;
import org.wso2.carbon.identity.application.authentication.framework.ApplicationAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticationDataPublisher;
import org.wso2.carbon.identity.application.authentication.framework.AuthenticationFlowHandler;
Expand Down Expand Up @@ -113,6 +116,7 @@
import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils;
import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataHandler;
import org.wso2.carbon.identity.claim.metadata.mgt.exception.ClaimMetadataException;
import org.wso2.carbon.identity.claim.metadata.mgt.model.LocalClaim;
import org.wso2.carbon.identity.configuration.mgt.core.exception.ConfigurationManagementException;
import org.wso2.carbon.identity.configuration.mgt.core.model.Attribute;
import org.wso2.carbon.identity.core.ServiceURLBuilder;
Expand Down Expand Up @@ -3826,4 +3830,78 @@ public static ServiceProvider createSPClone(ServiceProvider serviceProvider) thr
}
return newObject;
}

/**
* Get claim properties of a claim in a given tenant.
*
* @param tenantDomain The tenant domain.
* @param claimURI Claim URI.
* @return Properties of the claim.
*/
private static Map<String, String> getClaimProperties(String tenantDomain, String claimURI) {

try {
List<LocalClaim> localClaims = FrameworkServiceDataHolder.getInstance()
.getClaimMetadataManagementService().getLocalClaims(tenantDomain);
if (localClaims == null) {
if (log.isDebugEnabled()) {
log.debug("Returned claim list from ClaimManagementService is null");
}
return Collections.emptyMap();
}
for (LocalClaim localClaim : localClaims) {
if (StringUtils.equalsIgnoreCase(claimURI, localClaim.getClaimURI())) {
return localClaim.getClaimProperties();
}
}
} catch (ClaimMetadataException e) {
log.error("Error while retrieving local claim meta data.", e);
}
return Collections.emptyMap();
}

/**
* Encrypt the given plain text.
*
* @param plainText The plaintext value to be encrypted and base64 encoded
* @return Base64 encoded string
* @throws CryptoException On error during encryption
*/
public static String encrypt(String plainText) throws CryptoException {

String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
// Get custom key from server configuration.
String customKey = null;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
customKey = ServerConfiguration.getInstance().getFirstProperty(FrameworkConstants.TOTP_KEY);
}
return CryptoUtil.getDefaultCryptoUtil().encryptAndBase64Encode(
plainText.getBytes(StandardCharsets.UTF_8), customKey);
}

/**
* Process the claimValue of the given claimURI and encrypt if required.
*
* @param claimURI Claim URI.
* @param claimValue Claim value.
* @param tenantDomain The tenant domain.
* @return Processed claim value.
* @throws FrameworkException On error during encryption process.
*/
public static String getProcessedClaimValue(String claimURI, String claimValue, String tenantDomain)
throws FrameworkException {

Map<String, String> claimProperties = getClaimProperties(tenantDomain, claimURI);
try {
if (claimProperties.containsKey(FrameworkConstants.ENABLE_ENCRYPTION)) {
return claimValue;
}
if (StringUtils.isBlank(claimValue)) {
return claimValue;
}
return encrypt(claimValue);
} catch (CryptoException e) {
throw new FrameworkException("Error occurred while encrypting claim value of: " + claimURI, e);
}
}
}

0 comments on commit de2969b

Please sign in to comment.