Skip to content
Merged
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 @@ -24,18 +24,32 @@ public final class OsfInstitutionUtils {

public final static String ORCID_SUFFIX = " (via ORCiD SSO)";

public static boolean validateInstitutionForLogin(final JpaOsfDao jpaOsfDao, final String id) {
final OsfInstitution institution = jpaOsfDao.findOneInstitutionById(id);
/**
* @param institution the OSF institution to verify
* @return whether the given institution is eligible for institution SSO.
*/
public static boolean validateInstitutionForLogin(final OsfInstitution institution) {
return institution != null
&& institution.getDelegationProtocol() != null
&& institution.getSsoAvailability() != SsoAvailability.UNAVAILABLE;
}

public static String getInstitutionSupportEmail(final JpaOsfDao jpaOsfDao, final String id) {
final OsfInstitution institution = jpaOsfDao.findOneInstitutionById(id);
/**
* @param jpaOsfDao the data access object for OSF DB
* @param institutionId the institution ID
* @return the institution's support email if exists
*/
public static String getInstitutionSupportEmail(final JpaOsfDao jpaOsfDao, final String institutionId) {
final OsfInstitution institution = jpaOsfDao.findOneInstitutionById(institutionId);
return institution != null ? institution.getSupportEmail() : null;
}

/**
* @param jpaOsfDao the data access object for OSF DB
* @param target the target query param in shibboleth URL
* @param institutionId the institution ID used in shortcut SSO mode
* @return a map of institution name and login URL
*/
public static Map<String, String> getInstitutionLoginUrlMap(
final JpaOsfDao jpaOsfDao,
final String target,
Expand Down Expand Up @@ -101,6 +115,12 @@ public static Map<String, String> getInstitutionLoginUrlMap(
return institutionLoginUrlMap;
}

/**
* A helper method that sort a map by value instead of key.
*
* @param map the map to sort by value
* @return the sorted map
*/
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(final Map<K, V> map) {
final List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ public abstract class OsfAbstractLoginPreparationAction extends AbstractAuthenti

protected static final String PARAMETER_LOGIN_CONTEXT = "osfCasLoginContext";

protected static final String PARAMETER_SERVICE = "service";

protected static final String PARAMETER_CAMPAIGN = "campaign";

protected static final String PARAMETER_CAMPAIGN_VALUE = "institution";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ protected Event doExecute(RequestContext context) {
loginContext = new OsfCasLoginContext(
institutionLogin,
institutionId,
Boolean.FALSE,
StringUtils.EMPTY,
unsupportedInstitutionLogin,
orcidRedirect,
Expand All @@ -80,6 +81,7 @@ protected Event doExecute(RequestContext context) {
} else {
loginContext.setInstitutionLogin(institutionLogin);
loginContext.setInstitutionId(institutionId);
loginContext.setHiddenSsoAvailability(false);
loginContext.setInstitutionSupportEmail(StringUtils.EMPTY);
loginContext.setUnsupportedInstitutionLogin(unsupportedInstitutionLogin);
loginContext.setOrcidLoginUrl(orcidLoginUrl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.cos.cas.osf.authentication.support.OsfInstitutionUtils;
import io.cos.cas.osf.dao.JpaOsfDao;
import io.cos.cas.osf.model.OsfInstitution;
import io.cos.cas.osf.web.support.OsfCasLoginContext;

import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -76,16 +77,20 @@ protected Event doExecute(RequestContext context) {
-> (OsfCasLoginContext) requestContext.getFlowScope().get(PARAMETER_LOGIN_CONTEXT)).orElse(null);
if (loginContext != null) {
institutionId = loginContext.getInstitutionId();
if (!OsfInstitutionUtils.validateInstitutionForLogin(jpaOsfDao, institutionId)) {
final OsfInstitution institution = jpaOsfDao.findOneInstitutionById(institutionId);
if (!OsfInstitutionUtils.validateInstitutionForLogin(institution)) {
loginContext.setInstitutionId(null);
context.getFlowScope().put(PARAMETER_LOGIN_CONTEXT, loginContext);
institutionId = null;
} else {
final String institutionSupportEmail = OsfInstitutionUtils.getInstitutionSupportEmail(jpaOsfDao, institutionId);
final String institutionSupportEmail = institution.getSupportEmail();
if (institutionSupportEmail != null) {
loginContext.setInstitutionSupportEmail(institutionSupportEmail);
}
if (institution.getSsoAvailability().isHidden()) {
loginContext.setHiddenSsoAvailability(true);
}
}
context.getFlowScope().put(PARAMETER_LOGIN_CONTEXT, loginContext);
}

final Map<String, String> institutionLoginUrlMap
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
import java.io.Serializable;

/**
* This is {@link OsfCasLoginContext}.
*
* Stores OSF-specific information about the current web flow. Extends {@link Serializable} so that it can be put into
* and retrieved from the flow context conveniently.
* This is {@link OsfCasLoginContext}. Stores OSF-specific information about the current web flow.
* Extends {@link Serializable} so that it can be put into and retrieved from the flow context conveniently.
*
* @author Longze Chen
* @since 20.1.0
Expand All @@ -28,8 +26,17 @@ public class OsfCasLoginContext implements Serializable {

private boolean institutionLogin;

/**
* A verified institution ID. Its being present allows web flow to handle shortcut SSO mode.
*/
private String institutionId;

/**
* Indicates whether the institution with {@link this#institutionId} has hidden SSO availability,
* which allows web flow to handle such institutions properly in shortcut SSO mode.
*/
private boolean hiddenSsoAvailability;

private String institutionSupportEmail;

private boolean unsupportedInstitutionLogin;
Expand All @@ -42,7 +49,6 @@ public class OsfCasLoginContext implements Serializable {

/**
* The default service URL that uses OSF login endpoint with OSF home as destination.
*
* e.g. http(s)://[OSF Domain]/login?next=[encoded version of http(s)://[OSF Domain]/]
*/
private String defaultServiceUrl;
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ screen.institutionlogin.message.auto=Your institution has partnered with OSF. Pl
screen.institutionlogin.heading.select=Your institution
screen.institutionlogin.heading.auto=Your institution
screen.institutionlogin.link.select=Not your institution?
screen.institutionlogin.link.hidden=Note: Your institution is currently being set up and may not be available. Please check back at a later date.
screen.institutionlogin.link.unsupported=I can't find my institution
screen.institutionlogin.button.submit=Sign in
screen.institutionlogin.osf=Sign in with email
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/templates/casInstitutionLoginView.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ <h1 th:utext="#{screen.institutionlogin.heading}"></h1>
</select>
</section>

<section class="text-with-mdi text-danger">
<p th:if="${osfCasLoginContext.institutionId != null AND osfCasLoginContext.hiddenSsoAvailability}" th:utext="#{screen.institutionlogin.link.hidden}"></p>
</section>

<section class="text-with-mdi">
<span th:if="${osfCasLoginContext.institutionId}">
<a th:href="@{/login(campaign=institution, institutionId=${institutionId ?: ''}, service=${service?.originalUrl ?: ''})}" th:utext="#{screen.institutionlogin.link.select}"></a>
Expand Down
Loading