Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -580,38 +580,73 @@ protected PrincipalAuthenticationResult notifyRemotePrincipalAuthenticated(
throw new InstitutionLoginFailedAttributesMissingException("Missing user's names");
}

// Call Login Availability API
final String email = user.optString("email").trim();
final String o = user.optString("o").trim();
final String ou = user.optString("ou").trim();
final String eduPersonAffiliation = user.optString("eduPersonAffiliation").trim();
final String entitlement = user.optString("entitlement").trim();
if (!StringUtils.isEmpty(entitlement)) {
// send post method to RDM API
final JSONObject bodyObj = new JSONObject();
final String normalizeEntitlement = entitlement.replace("\\;", ";");
bodyObj.put("institution_id", institutionId);
bodyObj.put("entitlements", getEntitlements(normalizeEntitlement));
user.put("entitlement", normalizeEntitlement); // normalize entitlement in payload

HttpResponse httpResponse;
try {
httpResponse = callLoginAvailabilityAPI(bodyObj);
final BufferedReader bf = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
String bodyData = "";
final StringBuilder builder = new StringBuilder();
while ((bodyData = bf.readLine()) != null) {
builder.append(bodyData);
}
final JSONObject json = new JSONObject(builder.toString());
final boolean isLoginAvailability = (Boolean) json.get("login_availability");
if (!isLoginAvailability) {
throw new InstitutionLoginAvailabilityException();
}
} catch (final IOException e) {
logger.error(
"[OSF API] Notify Remote Principal Authenticated Failed: Communication Error - {}",
e.getMessage()
);
throw new InstitutionLoginFailedOsfApiException("Communication Error between OSF CAS and OSF API");
final String eduPersonScopedAffiliation = user.optString("eduPersonScopedAffiliation").trim();
final String eduPersonTargetedID = user.optString("eduPersonTargetedID").trim();
final String eduPersonAssurance = user.optString("eduPersonAssurance").trim();
final String eduPersonUniqueId = user.optString("eduPersonUniqueId").trim();
final String eduPersonOrcid = user.optString("eduPersonOrcid").trim();
final String isMemberOf = user.optString("isMemberOf").trim();
final String jasn = user.optString("jasn").trim();
final String jaGivenName = user.optString("jaGivenName").trim();
final String jaDisplayName = user.optString("jaDisplayName").trim();
final String jao = user.optString("jao").trim();
final String jaou = user.optString("jaou").trim();
final String gakuninScopedPersonalUniqueCode = user.optString("gakuninScopedPersonalUniqueCode").trim();

// Call Login Availability API
final JSONObject bodyObj = new JSONObject();
bodyObj.put("institution_id", institutionId);
bodyObj.put("mail", email);
bodyObj.put("sn", familyName);
bodyObj.put("o", getStringList(o));
bodyObj.put("ou", ou);
bodyObj.put("givenName", givenName);
bodyObj.put("displayName", fullname);
bodyObj.put("eduPersonAffiliation", getStringList(eduPersonAffiliation));
bodyObj.put("eduPersonPrincipalName", username);
bodyObj.put("eduPersonEntitlement", getStringList(entitlement));
bodyObj.put("eduPersonScopedAffiliation", getStringList(eduPersonScopedAffiliation));
bodyObj.put("eduPersonTargetedID", getStringList(eduPersonTargetedID));
bodyObj.put("eduPersonAssurance", getStringList(eduPersonAssurance));
bodyObj.put("eduPersonUniqueId", eduPersonUniqueId);
bodyObj.put("eduPersonOrcid", getStringList(eduPersonOrcid));
bodyObj.put("isMemberOf", getStringList(isMemberOf));
bodyObj.put("jasn", jasn);
bodyObj.put("jaGivenName", jaGivenName);
bodyObj.put("jaDisplayName", jaDisplayName);
bodyObj.put("jao", getStringList(jao));
bodyObj.put("jaou", jaou);
bodyObj.put("gakuninScopedPersonalUniqueCode", getStringList(gakuninScopedPersonalUniqueCode));

// send post method to RDM API
HttpResponse httpResponse;
try {
httpResponse = callLoginAvailabilityAPI(bodyObj);
final int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_FORBIDDEN) {
throw new InstitutionLoginAvailabilityException();
}

final BufferedReader bf = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
String bodyData = "";
final StringBuilder builder = new StringBuilder();
while ((bodyData = bf.readLine()) != null) {
builder.append(bodyData);
}
final JSONObject json = new JSONObject(builder.toString());
final String loginAvailability = (String) json.get("login_availability");
user.put("login_availability", loginAvailability);
} catch (final IOException e) {
logger.error(
"[OSF API] Notify Remote Principal Authenticated Failed: Communication Error - {}",
e.getMessage()
);
throw new InstitutionLoginFailedOsfApiException("Communication Error between OSF CAS and OSF API");
}

final String payload = normalizedPayload.toString();
Expand Down Expand Up @@ -652,7 +687,7 @@ protected PrincipalAuthenticationResult notifyRemotePrincipalAuthenticated(

// Step 4 - Make the OSF API request with the encrypted payload.
try {
final HttpResponse httpResponse = Request.Post(this.institutionsAuthUrl)
httpResponse = Request.Post(this.institutionsAuthUrl)
.addHeader(new BasicHeader("Content-Type", "text/plain"))
.bodyString(jweString, ContentType.APPLICATION_JSON)
.execute()
Expand Down Expand Up @@ -701,20 +736,21 @@ protected HttpResponse callLoginAvailabilityAPI(final JSONObject bodyObj) throws
}

/**
* Gets the entitlements.
* Get list of string.
*
* @param entitlement the entitlement
* @return the entitlements
* @param value value
* @return list of string
*/
protected List<String> getEntitlements(final String entitlement) {
final List<String> entitlements = new ArrayList<String>();
if (!StringUtils.isEmpty(entitlement)) {
final String[] arr = entitlement.split(";");
protected List<String> getStringList(final String value) {
final String normalizedValue = value.replace("\\;", ";");
final List<String> values = new ArrayList<String>();
if (!StringUtils.isEmpty(normalizedValue)) {
final String[] arr = normalizedValue.split(";");
for (final String str : arr) {
entitlements.add(str.trim());
values.add(str.trim());
}
}
return entitlements;
return values;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public void handleInstitutionValidRemotePrincipal() throws Exception {
final OpenScienceFrameworkCredential osfCredential = new OpenScienceFrameworkCredential();
osfCredential.setUsername(AbstractTestUtils.CONST_MAIL);
osfCredential.setInstitutionId(AbstractTestUtils.CONST_INSTITUTION_ID);
osfRemoteAuthenticate
.setInstitutionsLoginAvailabilityUrl(AbstractTestUtils.CONST_INSTITUTION_LOGIN_AVAILABILITY_URL);
try {
osfRemoteAuthenticate.notifyRemotePrincipalAuthenticated(osfCredential);
} catch (final AccountException e) {
Expand Down Expand Up @@ -254,7 +256,7 @@ public void verifyLoginAvailabilityGetEntitlementFlow() throws Exception {
List<String> entitlementList = new ArrayList<String>();

// Verify in case single entitlement
entitlementList = osfRemoteAuthenticate.getEntitlements(AbstractTestUtils.CONST_SINGLE_ENTITLEMENT_INPUT);
entitlementList = osfRemoteAuthenticate.getStringList(AbstractTestUtils.CONST_SINGLE_ENTITLEMENT_INPUT);
assertEquals(entitlementList.size(), AbstractTestUtils.CONST_SINGLE_ENTITLEMENTS_OUTPUT.length);
}

Expand All @@ -272,7 +274,7 @@ public void verifyLoginAvailabilitySingleEntitlementFlow() throws Exception {
osfCredential.setUsername(AbstractTestUtils.CONST_MAIL);

osfRemoteAuthenticate.setSingleEntitlement(true);
osfRemoteAuthenticate.setLoginAvailability(true);
osfRemoteAuthenticate.setLoginAvailability("can login");
osfRemoteAuthenticate
.setInstitutionsLoginAvailabilityUrl(AbstractTestUtils.CONST_INSTITUTION_LOGIN_AVAILABILITY_URL);

Expand All @@ -296,7 +298,6 @@ public void verifyLoginAvailabilityExceptionFlow() throws Exception {
osfCredential.setUsername(AbstractTestUtils.CONST_MAIL);

osfRemoteAuthenticate.setSingleEntitlement(true);
osfRemoteAuthenticate.setLoginAvailability(false);
osfRemoteAuthenticate
.setInstitutionsLoginAvailabilityUrl(AbstractTestUtils.CONST_INSTITUTION_LOGIN_AVAILABILITY_URL);
osfRemoteAuthenticate.notifyRemotePrincipalAuthenticated(osfCredential);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;

import org.apache.http.HttpStatus;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.entity.BasicHttpEntity;
import org.jasig.cas.CentralAuthenticationService;
import org.json.JSONObject;
import org.mockito.Mockito;
import org.springframework.util.StringUtils;

import io.cos.cas.AbstractTestUtils;
import io.cos.cas.authentication.OpenScienceFrameworkCredential;
Expand All @@ -21,12 +24,12 @@
public class MockNormalizeRemotePrincipalWithEntitlement extends MockNormalizeRemotePrincipal {

private boolean isSingleEntitlement;
private boolean isLoginAvailability;
private String loginAvailability;

public MockNormalizeRemotePrincipalWithEntitlement(final CentralAuthenticationService centralAuthenticationService) {
super(centralAuthenticationService);
this.isSingleEntitlement = false;
this.isLoginAvailability = false;
this.loginAvailability = "";
}

@Override
Expand All @@ -38,7 +41,7 @@ protected JSONObject normalizeRemotePrincipal(final OpenScienceFrameworkCredenti
user.put("fullname", AbstractTestUtils.CONST_DISPLAY_NAME);

if (isSingleEntitlement) {
user.put("entitlement", AbstractTestUtils.CONST_SINGLE_ENTITLEMENT_INPUT);
user.put("eduPersonEntitlement", AbstractTestUtils.CONST_SINGLE_ENTITLEMENT_INPUT);
}

provider.put("id", credential.getInstitutionId());
Expand All @@ -49,13 +52,18 @@ protected JSONObject normalizeRemotePrincipal(final OpenScienceFrameworkCredenti

protected HttpResponse callLoginAvailabilityAPI(final JSONObject bodyObj) throws IOException, ClientProtocolException {
final HttpResponse mockedResponse = Mockito.mock(HttpResponse.class);
final StatusLine statusLine = Mockito.mock(StatusLine.class);
final BasicHttpEntity entity = new BasicHttpEntity();
String bodyResponse = "{\"login_availability\":false,\"meta\":{\"version\":\"2.0\"}}";
if (this.isLoginAvailability) {
bodyResponse = "{\"login_availability\":true,\"meta\":{\"version\":\"2.0\"}}";
String bodyResponse = "{\"meta\":{\"version\":\"2.0\"}}";
if (StringUtils.hasText(this.loginAvailability)) {
bodyResponse = "{\"login_availability\":\"" + this.loginAvailability + "\",\"meta\":{\"version\":\"2.0\"}}";
Mockito.when(statusLine.getStatusCode()).thenReturn(HttpStatus.SC_OK);
} else {
Mockito.when(statusLine.getStatusCode()).thenReturn(HttpStatus.SC_FORBIDDEN);
}

entity.setContent(new ByteArrayInputStream(bodyResponse.getBytes()));
Mockito.when(mockedResponse.getStatusLine()).thenReturn(statusLine);
Mockito.when(mockedResponse.getEntity()).thenReturn(entity);
return mockedResponse;
}
Expand All @@ -64,8 +72,8 @@ public void setSingleEntitlement(final boolean isSingleEntitlement) {
this.isSingleEntitlement = isSingleEntitlement;
}

public void setLoginAvailability(final boolean isLoginAvailability) {
this.isLoginAvailability = isLoginAvailability;
public void setLoginAvailability(final String loginAvailability) {
this.loginAvailability = loginAvailability;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,9 @@

--%>

<%-- Login availability failed page --%>
<%-- Login availability failed redirect page --%>

<jsp:directive.include file="includes/top.jsp"/>

<div id="msg" class="errors">
<h2><spring:message code="screen.login.availability.heading"/></h2>
<p><spring:message code="screen.login.availability.message"/></p>
</div>

<spring:message code="screen.osf.login.message.error" var="errorDescription"/>
<script>
description = document.getElementById("description");
if (description != null) {
description.innerHTML = "<br><br>${errorDescription}";
}
</script>

<c:set var="linkSignIn" value="false"/>
<c:set var="linkSignOut" value="false"/>
<c:set var="linkCreateAccount" value="false"/>
<c:set var="linkBackToOsf" value="true"/>

<jsp:directive.include file="includes/bottom.jsp"/>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<spring:eval var="osfUrl" expression="@casProperties.getProperty('osf.url')"/>
<c:redirect url="${osfUrl}?login_not_available=true"/>