Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reCaptcha enterprise support #684

Closed
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ public class ReCaptchaPropertiesDTO {


private Boolean reCaptchaEnabled = null;




private Boolean reCaptchaEnterpriseEnabled = null;


private String reCaptchaKey = null;


Expand All @@ -33,7 +36,19 @@ public void setReCaptchaEnabled(Boolean reCaptchaEnabled) {
this.reCaptchaEnabled = reCaptchaEnabled;
}



/**
**/
@ApiModelProperty(value = "")
@JsonProperty("reCaptchaEnterpriseEnabled")
public Boolean getReCaptchaEnterpriseEnabled() {
return reCaptchaEnterpriseEnabled;
}
public void setReCaptchaEnterpriseEnabled(Boolean reCaptchaEnterpriseEnabled) {
this.reCaptchaEnterpriseEnabled = reCaptchaEnterpriseEnabled;
}


/**
**/
@ApiModelProperty(value = "")
Expand All @@ -45,7 +60,7 @@ public void setReCaptchaKey(String reCaptchaKey) {
this.reCaptchaKey = reCaptchaKey;
}


/**
**/
@ApiModelProperty(value = "")
Expand All @@ -57,14 +72,15 @@ public void setReCaptchaAPI(String reCaptchaAPI) {
this.reCaptchaAPI = reCaptchaAPI;
}



@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class ReCaptchaPropertiesDTO {\n");

sb.append(" reCaptchaEnabled: ").append(reCaptchaEnabled).append("\n");
sb.append(" reCaptchaEnterpriseEnabled: ").append(reCaptchaEnterpriseEnabled).append("\n");
sb.append(" reCaptchaKey: ").append(reCaptchaKey).append("\n");
sb.append(" reCaptchaAPI: ").append(reCaptchaAPI).append("\n");
sb.append("}\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
Expand Down Expand Up @@ -453,6 +454,9 @@ private static Properties validateCaptchaConfigs(Properties properties) {

boolean reCaptchaEnabled = Boolean.valueOf(properties.getProperty(CaptchaConstants.RE_CAPTCHA_ENABLED));

boolean reCaptchaEnterpriseEnabled = Boolean.valueOf(properties.getProperty(CaptchaConstants
.RE_CAPTCHA_ENTERPRISE_ENABLED));

if (reCaptchaEnabled && StringUtils.isBlank(properties.getProperty(CaptchaConstants.RE_CAPTCHA_SITE_KEY))) {
RecoveryUtil.handleBadRequest(String.format("%s is not found ", CaptchaConstants.RE_CAPTCHA_SITE_KEY),
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
Expand All @@ -461,14 +465,26 @@ private static Properties validateCaptchaConfigs(Properties properties) {
RecoveryUtil.handleBadRequest(String.format("%s is not found ", CaptchaConstants.RE_CAPTCHA_API_URL),
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
if (reCaptchaEnabled && StringUtils.isBlank(properties.getProperty(CaptchaConstants.RE_CAPTCHA_SECRET_KEY))) {
if (reCaptchaEnabled && !reCaptchaEnterpriseEnabled &&
StringUtils.isBlank(properties.getProperty(CaptchaConstants.RE_CAPTCHA_SECRET_KEY))) {
RecoveryUtil.handleBadRequest(String.format("%s is not found ", CaptchaConstants.RE_CAPTCHA_SECRET_KEY),
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
if (StringUtils.isBlank(properties.getProperty(CaptchaConstants.RE_CAPTCHA_VERIFY_URL))) {
RecoveryUtil.handleBadRequest(String.format("%s is not found ", CaptchaConstants.RE_CAPTCHA_VERIFY_URL),
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}

if (reCaptchaEnabled && reCaptchaEnterpriseEnabled &&
StringUtils.isBlank(properties.getProperty(CaptchaConstants.RE_CAPTCHA_API_KEY))) {
RecoveryUtil.handleBadRequest(String.format("%s is not found ", CaptchaConstants
.RE_CAPTCHA_API_KEY), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
if (reCaptchaEnabled && reCaptchaEnterpriseEnabled &&
StringUtils.isBlank(properties.getProperty(CaptchaConstants.RE_CAPTCHA_PROJECT_ID))) {
RecoveryUtil.handleBadRequest(String.format("%s is not found ", CaptchaConstants
.RE_CAPTCHA_PROJECT_ID), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
return properties;
}

Expand All @@ -483,19 +499,45 @@ public static HttpResponse makeCaptchaVerificationHttpRequest(ReCaptchaResponseT
Properties properties) {

HttpResponse response = null;
String reCaptchaSecretKey = properties.getProperty(CaptchaConstants.RE_CAPTCHA_SECRET_KEY);
String reCaptchaVerifyUrl = properties.getProperty(CaptchaConstants.RE_CAPTCHA_VERIFY_URL);
boolean reCaptchaEnterpriseEnabled =
Boolean.valueOf(properties.getProperty(CaptchaConstants.RE_CAPTCHA_ENTERPRISE_ENABLED));
CloseableHttpClient httpclient = HttpClientBuilder.create().useSystemProperties().build();
HttpPost httppost = new HttpPost(reCaptchaVerifyUrl);
List<BasicNameValuePair> params = Arrays.asList(new BasicNameValuePair("secret", reCaptchaSecretKey),
new BasicNameValuePair("response", reCaptchaResponse.getToken()));
httppost.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8));
HttpPost httppost;
AwesomeNipun marked this conversation as resolved.
Show resolved Hide resolved

try {
response = httpclient.execute(httppost);
} catch (IOException e) {
RecoveryUtil.handleBadRequest(String.format("Unable to get the verification response : %s", e.getMessage()),
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
if (!reCaptchaEnterpriseEnabled){ // for Recaptcha V2 and V3
AwesomeNipun marked this conversation as resolved.
Show resolved Hide resolved
String reCaptchaSecretKey = properties.getProperty(CaptchaConstants.RE_CAPTCHA_SECRET_KEY);

httppost = new HttpPost(reCaptchaVerifyUrl);
List<BasicNameValuePair> params = Arrays.asList(new BasicNameValuePair("secret", reCaptchaSecretKey),
new BasicNameValuePair("response", reCaptchaResponse.getToken()));
httppost.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8));

try {
response = httpclient.execute(httppost);
} catch (IOException e) {
RecoveryUtil.handleBadRequest(String.format("Unable to get the verification response : %s",
e.getMessage()), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}

} else{ // for Recaptcha Enterprise
AwesomeNipun marked this conversation as resolved.
Show resolved Hide resolved
String projectID = properties.getProperty(CaptchaConstants.RE_CAPTCHA_PROJECT_ID);
String APIKey = properties.getProperty(CaptchaConstants.RE_CAPTCHA_API_KEY);
String siteKey = properties.getProperty(CaptchaConstants.RE_CAPTCHA_SITE_KEY);
String verifyUrl = reCaptchaVerifyUrl + "/v1/projects/" + projectID + "/assessments?key=" + APIKey;
httppost = new HttpPost(verifyUrl);
httppost.setHeader("Content-Type", "application/json");
String json = String.format("{ \"event\": { \"token\": \"%s\", \"siteKey\": \"%s\" } }", reCaptchaResponse,
siteKey);
StringEntity entity = new StringEntity(json, StandardCharsets.UTF_8);
httppost.setEntity(entity);

try {
response = httpclient.execute(httppost);
} catch (IOException e) {
RecoveryUtil.handleBadRequest(String.format("Unable to get the verification response : %s",
e.getMessage()), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
}
return response;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
public class CaptchaApiServiceImpl extends CaptchaApiService {

private static final String SUCCESS = "success";
private static final String VALID = "valid";
private static final Log log = LogFactory.getLog(CaptchaApiServiceImpl.class);
private final String RECAPTCHA = "ReCaptcha";

Expand All @@ -55,6 +56,8 @@ public Response getCaptcha(String captchaType, String recoveryType, String tenan

Properties properties = RecoveryUtil.getValidatedCaptchaConfigs();
boolean reCaptchaEnabled = Boolean.valueOf(properties.getProperty(CaptchaConstants.RE_CAPTCHA_ENABLED));
boolean reCaptchaEnterpriseEnabled =
Boolean.valueOf(properties.getProperty(CaptchaConstants.RE_CAPTCHA_ENTERPRISE_ENABLED));
boolean forcefullyEnabledRecaptchaForAllTenants =
Boolean.valueOf(properties.getProperty(CaptchaConstants.FORCEFULLY_ENABLED_RECAPTCHA_FOR_ALL_TENANTS));
ReCaptchaPropertiesDTO reCaptchaPropertiesDTO = new ReCaptchaPropertiesDTO();
Expand All @@ -64,6 +67,7 @@ public Response getCaptcha(String captchaType, String recoveryType, String tenan
reCaptchaPropertiesDTO.setReCaptchaEnabled(true);
reCaptchaPropertiesDTO.setReCaptchaKey(properties.getProperty(CaptchaConstants.RE_CAPTCHA_SITE_KEY));
reCaptchaPropertiesDTO.setReCaptchaAPI(properties.getProperty(CaptchaConstants.RE_CAPTCHA_API_URL));
reCaptchaPropertiesDTO.setReCaptchaEnterpriseEnabled(reCaptchaEnterpriseEnabled);
return Response.ok(reCaptchaPropertiesDTO).build();
} else {
reCaptchaPropertiesDTO.setReCaptchaEnabled(false);
Expand All @@ -80,6 +84,8 @@ public Response verifyCaptcha(ReCaptchaResponseTokenDTO reCaptchaResponse, Strin

Properties properties = RecoveryUtil.getValidatedCaptchaConfigs();
boolean reCaptchaEnabled = Boolean.valueOf(properties.getProperty(CaptchaConstants.RE_CAPTCHA_ENABLED));
boolean reCaptchaEnterpriseEnabled =
Boolean.valueOf(properties.getProperty(CaptchaConstants.RE_CAPTCHA_ENTERPRISE_ENABLED));

if (!reCaptchaEnabled) {
RecoveryUtil.handleBadRequest("ReCaptcha is disabled", Constants.INVALID);
Expand All @@ -89,20 +95,42 @@ public Response verifyCaptcha(ReCaptchaResponseTokenDTO reCaptchaResponse, Strin
HttpEntity entity = response.getEntity();
ReCaptchaVerificationResponseDTO reCaptchaVerificationResponseDTO = new ReCaptchaVerificationResponseDTO();

try {
if (!reCaptchaEnterpriseEnabled) {

try {
if (entity == null) {
RecoveryUtil.handleBadRequest("ReCaptcha verification response is not received.",
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
} else {
AwesomeNipun marked this conversation as resolved.
Show resolved Hide resolved
try (InputStream in = entity.getContent()) {
JsonObject verificationResponse = new JsonParser().parse(IOUtils.toString(in)).getAsJsonObject();
reCaptchaVerificationResponseDTO.setSuccess(verificationResponse.get(SUCCESS).getAsBoolean());
}
}
} catch (IOException e) {
log.error("Unable to read the verification response.", e);
RecoveryUtil.handleBadRequest("Unable to read the verification response.",
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
} else {

if (entity == null) {
RecoveryUtil.handleBadRequest("ReCaptcha verification response is not received.",
RecoveryUtil.handleBadRequest("ReCaptcha Enterprise verification response is not received.",
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
} else {
}

try {
try (InputStream in = entity.getContent()) {
JsonObject verificationResponse = new JsonParser().parse(IOUtils.toString(in)).getAsJsonObject();
reCaptchaVerificationResponseDTO.setSuccess(verificationResponse.get(SUCCESS).getAsBoolean());
JsonObject tokenProperties = verificationResponse.get("tokenProperties").getAsJsonObject();
boolean success = tokenProperties.get(VALID).getAsBoolean();
reCaptchaVerificationResponseDTO.setSuccess(success);
}
} catch (IOException e) {
log.error("Unable to read the verification response.", e);
RecoveryUtil.handleBadRequest("Unable to read the verification response.",
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
} catch (IOException e) {
log.error("Unable to read the verification response.", e);
RecoveryUtil.handleBadRequest("Unable to read the verification response.",
Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT);
}
return Response.ok(reCaptchaVerificationResponseDTO).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,8 @@ definitions:
properties:
reCaptchaEnabled:
type: boolean
reCaptchaEnterpriseEnabled:
type: boolean
reCaptchaKey:
type: string
reCaptchaAPI:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public class CaptchaDataHolder {

private boolean reCaptchaEnabled;

private boolean reCaptchaEnterpriseEnabled;
AwesomeNipun marked this conversation as resolved.
Show resolved Hide resolved

private String reCaptchaAPIUrl;

private String reCaptchaVerifyUrl;
Expand All @@ -45,6 +47,10 @@ public class CaptchaDataHolder {

private String reCaptchaSecretKey;

private String reCaptchaAPIKey;
AwesomeNipun marked this conversation as resolved.
Show resolved Hide resolved

private String reCaptchaProjectID;

private String reCaptchaErrorRedirectUrls;

private String reCaptchaRequestWrapUrls;
Expand Down Expand Up @@ -84,6 +90,36 @@ public void setReCaptchaEnabled(boolean reCaptchaEnabled) {
this.reCaptchaEnabled = reCaptchaEnabled;
}

public boolean isReCaptchaEnterpriseEnabled() {

return reCaptchaEnterpriseEnabled;
}

public void setReCaptchaEnterpriseEnabled(boolean reCaptchaEnterpriseEnabled) {

this.reCaptchaEnterpriseEnabled = reCaptchaEnterpriseEnabled;
}

public String getReCaptchaAPIKey() {

return reCaptchaAPIKey;
}

public void setReCaptchaAPIKey(String reCaptchaAPIKey) {

this.reCaptchaAPIKey = reCaptchaAPIKey;
}

public String getReCaptchaProjectID() {

return reCaptchaProjectID;
}

public void setReCaptchaProjectID(String reCaptchaProjectID) {

this.reCaptchaProjectID = reCaptchaProjectID;
}

public String getReCaptchaAPIUrl() {
return reCaptchaAPIUrl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class CaptchaConstants {

public static final String RE_CAPTCHA_ENABLED = "recaptcha.enabled";

public static final String RE_CAPTCHA_ENTERPRISE_ENABLED = "recaptcha.enterprise.enabled";
AwesomeNipun marked this conversation as resolved.
Show resolved Hide resolved

public static final String FORCEFULLY_ENABLED_RECAPTCHA_FOR_ALL_TENANTS = "recaptcha" +
".forcefullyEnabledForAllTenants";

Expand All @@ -42,6 +44,10 @@ public class CaptchaConstants {

public static final String RE_CAPTCHA_SITE_KEY = "recaptcha.site.key";

public static final String RE_CAPTCHA_API_KEY = "recaptcha.api.key";

public static final String RE_CAPTCHA_PROJECT_ID = "recaptcha.project.id";

public static final String RE_CAPTCHA_SECRET_KEY = "recaptcha.secret.key";

public static final String RE_CAPTCHA_REQUEST_WRAP_URLS = "recaptcha.request.wrap.urls";
Expand Down
Loading