From 120ca78ac71b355efcaa46923592a3504ee9c287 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 5 Nov 2020 23:40:24 -0500 Subject: [PATCH 01/71] Implement OSF institution model and dao --- .../io/cos/cas/osf/dao/AbstractOsfDao.java | 7 +++ .../java/io/cos/cas/osf/dao/JpaOsfDao.java | 31 +++++++++++ .../io/cos/cas/osf/model/OsfInstitution.java | 53 +++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/main/java/io/cos/cas/osf/model/OsfInstitution.java diff --git a/src/main/java/io/cos/cas/osf/dao/AbstractOsfDao.java b/src/main/java/io/cos/cas/osf/dao/AbstractOsfDao.java index e95f9efa..555e46c2 100644 --- a/src/main/java/io/cos/cas/osf/dao/AbstractOsfDao.java +++ b/src/main/java/io/cos/cas/osf/dao/AbstractOsfDao.java @@ -2,9 +2,12 @@ import io.cos.cas.osf.model.OsfEmail; import io.cos.cas.osf.model.OsfGuid; +import io.cos.cas.osf.model.OsfInstitution; import io.cos.cas.osf.model.OsfTotp; import io.cos.cas.osf.model.OsfUser; +import java.util.List; + /** * This is {@link AbstractOsfDao}. * @@ -31,4 +34,8 @@ public OsfUser findOneUserByEmail(final String address) { protected abstract OsfEmail findOneEmailByAddress(String emailAddress); protected abstract OsfTotp findOneTotpByOwnerId(final Integer ownerId); + + protected abstract OsfInstitution findOneInstitutionById(final String id); + + protected abstract List findAllInstitutions(); } diff --git a/src/main/java/io/cos/cas/osf/dao/JpaOsfDao.java b/src/main/java/io/cos/cas/osf/dao/JpaOsfDao.java index 77375948..0b4aa4fd 100644 --- a/src/main/java/io/cos/cas/osf/dao/JpaOsfDao.java +++ b/src/main/java/io/cos/cas/osf/dao/JpaOsfDao.java @@ -2,6 +2,7 @@ import io.cos.cas.osf.model.OsfEmail; import io.cos.cas.osf.model.OsfGuid; +import io.cos.cas.osf.model.OsfInstitution; import io.cos.cas.osf.model.OsfTotp; import io.cos.cas.osf.model.OsfUser; @@ -14,6 +15,7 @@ import javax.persistence.PersistenceException; import javax.persistence.TypedQuery; import javax.validation.constraints.NotNull; +import java.util.List; /** * This is {@link JpaOsfDao}. @@ -89,4 +91,33 @@ public OsfTotp findOneTotpByOwnerId(final Integer ownerId) { return null; } } + + @Override + public OsfInstitution findOneInstitutionById(final String id) { + try { + final TypedQuery query = entityManager.createQuery( + "select i from OsfInstitution i where i.institutionId = :id", + OsfInstitution.class + ); + query.setParameter("id", id); + return query.getSingleResult(); + } catch (final PersistenceException e) { + return null; + } + + } + + @Override + public List findAllInstitutions() { + try { + final TypedQuery query = entityManager.createQuery( + "select i from OsfInstitution i " + + "where (not i.delegationProtocol = '') and i.deleted = false", + OsfInstitution.class + ); + return query.getResultList(); + } catch (final PersistenceException e) { + return null; + } + } } diff --git a/src/main/java/io/cos/cas/osf/model/OsfInstitution.java b/src/main/java/io/cos/cas/osf/model/OsfInstitution.java new file mode 100644 index 00000000..e18b70e7 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/model/OsfInstitution.java @@ -0,0 +1,53 @@ +package io.cos.cas.osf.model; + +import io.cos.cas.osf.authentication.support.DelegationProtocol; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * This is {@link OsfInstitution}. + * + * @author Longze Chen + * @since 20.1.0 + */ +@Entity +@Table(name = "osf_institution") +@NoArgsConstructor +@Getter +@ToString +public class OsfInstitution extends AbstractOsfModel { + + private static final long serialVersionUID = -1186000864052788250L; + + @Column(name = "_id") + private String institutionId; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "login_url") + private String loginUrl; + + @Column(name = "logout_url") + private String logoutUrl; + + @Column(name = "delegation_protocol") + private String delegationProtocol; + + @Column(name = "is_deleted") + private Boolean deleted; + + public DelegationProtocol getDelegationProtocol() { + try { + return DelegationProtocol.getType(delegationProtocol); + } catch (final IllegalArgumentException e) { + return null; + } + } +} From d555f607ef2ce96e48cbfc9cbb6613b1fac1373a Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Wed, 11 Nov 2020 23:23:26 -0500 Subject: [PATCH 02/71] Expand instn check action to prepare the instn login context --- .../support/OsfInstitutionUtils.java | 75 +++++++++++++++++++ .../OsfCasSupportActionsConfiguration.java | 7 +- .../OsfInstitutionLoginPreparationAction.java | 55 +++++++++++++- 3 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java diff --git a/src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java b/src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java new file mode 100644 index 00000000..82058a31 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java @@ -0,0 +1,75 @@ +package io.cos.cas.osf.authentication.support; + +import io.cos.cas.osf.dao.JpaOsfDao; +import io.cos.cas.osf.model.OsfInstitution; + +import lombok.extern.slf4j.Slf4j; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * This is {@link OsfInstitutionUtils}. + * + * @author Longze Chen + * @since 20.1.0 + */ +@Slf4j +public final class OsfInstitutionUtils { + + public static boolean validateInstitutionForLogin(final JpaOsfDao jpaOsfDao, final String id) { + final OsfInstitution institution = jpaOsfDao.findOneInstitutionById(id); + return institution != null && institution.getDelegationProtocol() != null; + } + + public static Map getInstitutionLoginUrlMap( + final JpaOsfDao jpaOsfDao, + final String target, + final String id + ) { + List institutionList = new LinkedList<>(); + if (id == null || id.isEmpty()) { + institutionList = jpaOsfDao.findAllInstitutions(); + } else { + final OsfInstitution institution = jpaOsfDao.findOneInstitutionById(id); + if (institution != null) { + institutionList.add(institution); + } else { + institutionList = jpaOsfDao.findAllInstitutions(); + } + } + final Map institutionLoginUrlMap = new HashMap<>(); + for (final OsfInstitution institution: institutionList) { + final DelegationProtocol delegationProtocol = institution.getDelegationProtocol(); + if (DelegationProtocol.SAML_SHIB.equals(delegationProtocol)) { + institutionLoginUrlMap.put( + institution.getLoginUrl() + "&target=" + target + '#' + institution.getId(), + institution.getName() + ); + } else if (DelegationProtocol.CAS_PAC4J.equals(delegationProtocol)) { + institutionLoginUrlMap.put(institution.getInstitutionId(), institution.getName()); + } + } + return institutionLoginUrlMap; + } + + public static > Map sortByValue(final Map map) { + final List> list = new LinkedList<>(map.entrySet()); + Collections.sort(list, new Comparator>() { + @Override + public int compare(final Map.Entry e1, final Map.Entry e2) { + return (e1.getValue()).compareTo(e2.getValue()); + } + }); + final Map result = new LinkedHashMap<>(); + for (final Map.Entry entry : list) { + result.put(entry.getKey(), entry.getValue()); + } + return result; + } +} diff --git a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java index da287d8f..c42b9003 100644 --- a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java +++ b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java @@ -1,5 +1,6 @@ package io.cos.cas.osf.web.config; +import io.cos.cas.osf.dao.JpaOsfDao; import io.cos.cas.osf.web.flow.login.OsfDefaultLoginPreparationAction; import io.cos.cas.osf.web.flow.login.OsfInstitutionLoginPreparationAction; import io.cos.cas.osf.web.flow.login.OsfPrincipalFromNonInteractiveCredentialsAction; @@ -55,6 +56,9 @@ public class OsfCasSupportActionsConfiguration extends CasSupportActionsConfigur @Qualifier("centralAuthenticationService") private ObjectProvider centralAuthenticationService; + @Autowired + private ObjectProvider jpaOsfDao; + /** * Bean configuration for {@link OsfPrincipalFromNonInteractiveCredentialsAction}. * @@ -104,7 +108,8 @@ public Action osfInstitutionLoginCheckAction() { return new OsfInstitutionLoginPreparationAction( initialAuthenticationAttemptWebflowEventResolver.getObject(), serviceTicketRequestWebflowEventResolver.getObject(), - adaptiveAuthenticationPolicy.getObject() + adaptiveAuthenticationPolicy.getObject(), + jpaOsfDao.getObject() ); } } diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfInstitutionLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfInstitutionLoginPreparationAction.java index f068f577..adc80825 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfInstitutionLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfInstitutionLoginPreparationAction.java @@ -1,5 +1,11 @@ package io.cos.cas.osf.web.flow.login; +import io.cos.cas.osf.authentication.support.OsfInstitutionUtils; +import io.cos.cas.osf.dao.JpaOsfDao; +import io.cos.cas.osf.web.support.OsfCasLoginContext; + +import lombok.extern.slf4j.Slf4j; + import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy; import org.apereo.cas.web.flow.resolver.CasDelegatingWebflowEventResolver; import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver; @@ -7,6 +13,12 @@ import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; +import javax.validation.constraints.NotNull; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Optional; + /** * This is {@link OsfInstitutionLoginPreparationAction}. * @@ -15,22 +27,61 @@ * @author Longze Chen * @since 20.0.0 */ +@Slf4j public class OsfInstitutionLoginPreparationAction extends OsfAbstractLoginPreparationAction { + @NotNull + private final JpaOsfDao jpaOsfDao; + public OsfInstitutionLoginPreparationAction( final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver, final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, - final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy + final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy, + final JpaOsfDao jpaOsfDao ) { super( initialAuthenticationAttemptWebflowEventResolver, serviceTicketRequestWebflowEventResolver, adaptiveAuthenticationPolicy ); + this.jpaOsfDao = jpaOsfDao; } @Override protected Event doExecute(RequestContext context) { - return error(); + + String target; + String service = context.getRequestParameters().get("service"); + if (service != null) { + service = URLEncoder.encode(service, StandardCharsets.UTF_8); + target = URLEncoder.encode(String.format("/login?service=%s", service), StandardCharsets.UTF_8); + } else { + target = URLEncoder.encode("/login", StandardCharsets.UTF_8); + } + + String institutionId = null; + OsfCasLoginContext loginContext; + loginContext = Optional.of(context).map(requestContext + -> (OsfCasLoginContext) requestContext.getFlowScope().get(PARAMETER_LOGIN_CONTEXT)).orElse(null); + if (loginContext != null) { + institutionId = loginContext.getInstitutionId(); + if (!OsfInstitutionUtils.validateInstitutionForLogin(jpaOsfDao, institutionId)) { + loginContext.setInstitutionId(null); + context.getFlowScope().put(PARAMETER_LOGIN_CONTEXT, loginContext); + institutionId = null; + } + } + + final Map institutionLoginUrlMap + = OsfInstitutionUtils.getInstitutionLoginUrlMap(jpaOsfDao, target, institutionId); + final Map institutionLoginUrlMapSorted; + if (institutionId != null) { + institutionLoginUrlMapSorted = institutionLoginUrlMap; + } else { + institutionLoginUrlMap.put("", " -- select an institution -- "); + institutionLoginUrlMapSorted = OsfInstitutionUtils.sortByValue(institutionLoginUrlMap); + } + context.getFlowScope().put("institutions", institutionLoginUrlMapSorted); + return success(); } } From 530056571e0b6ee4efb7a185d6ca01e71a155b5f Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Wed, 11 Nov 2020 23:31:47 -0500 Subject: [PATCH 03/71] Update web flow and implement institution login page --- .../OsfCasLoginWebflowConfigurer.java | 20 +++ .../flow/support/OsfCasWebflowConstants.java | 2 + src/main/resources/messages.properties | 17 +++ src/main/resources/static/css/cas.css | 20 +++ .../templates/casInstitutionLoginView.html | 140 ++++++++++++++++++ .../fragments/osfinstitutionbannerui.html | 24 +++ 6 files changed, 223 insertions(+) create mode 100644 src/main/resources/templates/casInstitutionLoginView.html create mode 100644 src/main/resources/templates/fragments/osfinstitutionbannerui.html diff --git a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java index bb9f9e86..c533b128 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java +++ b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java @@ -71,6 +71,7 @@ protected void createDefaultViewStates(final Flow flow) { super.createDefaultViewStates(flow); // Create OSF customized view states createTwoFactorLoginFormView(flow); + createInstitutionLoginView(flow); createOrcidLoginAutoRedirectView(flow); createOsfCasAuthenticationExceptionViewStates(flow); } @@ -338,6 +339,11 @@ private void createOsfInstitutionLoginCheckAction(final Flow flow) { CasWebflowConstants.TRANSITION_ID_ERROR, OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_NOT_IMPLEMENTED ); + createTransitionForState( + action, + CasWebflowConstants.TRANSITION_ID_SUCCESS, + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_INIT + ); } /** @@ -419,4 +425,18 @@ protected void createOrcidLoginAutoRedirectView(final Flow flow) { OsfCasWebflowConstants.VIEW_ID_ORCID_LOGIN_AUTO_REDIRECT ); } + + /** + * Create the institution SSO init view state to support the OSF feature "sign-in via institutions". + * + * @param flow the flow + */ + protected void createInstitutionLoginView(final Flow flow) { + createViewState( + flow, + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_INIT, + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_INIT + ); + } + } diff --git a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java index ea6f8775..e1e25498 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java +++ b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java @@ -40,5 +40,7 @@ public interface OsfCasWebflowConstants { String VIEW_ID_ONE_TIME_PASSWORD_REQUIRED = "casTwoFactorLoginView"; + String VIEW_ID_INSTITUTION_SSO_INIT = "casInstitutionLoginView"; + String VIEW_ID_INSTITUTION_SSO_NOT_IMPLEMENTED = "casInstitutionSsoNotImplementedView"; } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 2a9ad090..181f2a99 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -556,6 +556,23 @@ screen.twofactor.button.verify=Verify screen.twofactor.button.verifywip=One moment please... screen.twofactor.button.cancel=Cancel screen.twofactor.instructions.bottom=Open the two-factor authentication app on your device to view your authentication code and verify your identity. +# +# Institution login page +# +screen.institutionlogin.pagetitle=Institution SSO +screen.institutionlgoin.bannertitle=OSF Institutions +screen.institutionlogin.heading=Sign in through institution +screen.institutionlogin.message=If your institution has partnered with OSF, please select its name below and sign in with your institutional credentials. If you do not currently have an OSF account, this will create one for you. +screen.institutionlogin.select=Select your institution +screen.institutionlogin.select.auto=Your institution +screen.institutionlogin.select.all=Not your institution? +screen.institutionlogin.select.errormessage=You must select an institution. +screen.institutionlogin.button.submit=Sign in +screen.institutionlogin.osf=Sign in with OSF +screen.institutionlogin.backtoosf=Exit and go back to OSF +screen.institutionlogin.consent.checkbox=I have read and agree to the Terms of Use and Privacy Policy. +screen.institutionlogin.consent.errormessage=You must read and agree to the Terms of Use and Privacy Policy. + # # Generic login and logout success page # diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index 5e6609dc..c5cc0b9a 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -863,6 +863,26 @@ body { max-width: 48rem; } +.login-instn-card .card-message { + padding: 0.25rem 0; +} + +.login-instn-card .instn-select select { + width: 100%; + height: 3rem; + font-size: 1.25rem; + padding: 0 1rem; + margin: 0.5rem 0; +} + +.login-instn-card .instn-consent { + padding: 1rem 0; +} + +.login-instn-card .instn-consent input { + margin-right: 0.5rem; +} + @media all and (min-width: 639.99px) { .w-card-narrow { width: 50%; diff --git a/src/main/resources/templates/casInstitutionLoginView.html b/src/main/resources/templates/casInstitutionLoginView.html new file mode 100644 index 00000000..2a8abe12 --- /dev/null +++ b/src/main/resources/templates/casInstitutionLoginView.html @@ -0,0 +1,140 @@ + + + + + + + + + + + + +
+ +
+ + + +
+
+ + + diff --git a/src/main/resources/templates/fragments/osfinstitutionbannerui.html b/src/main/resources/templates/fragments/osfinstitutionbannerui.html new file mode 100644 index 00000000..dd26672c --- /dev/null +++ b/src/main/resources/templates/fragments/osfinstitutionbannerui.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + +
+
+ +
+

+
+
+
+ + + From 1173ed9e40a5f928b1a5bf2d9a8ba392c8ac475a Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Wed, 11 Nov 2020 23:32:27 -0500 Subject: [PATCH 04/71] Fix login request param institutionId --- .../osf/web/flow/login/OsfDefaultLoginPreparationAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java index 157bc5f7..7c875651 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java @@ -97,7 +97,7 @@ private boolean isInstitutionLogin(final RequestContext context) { private String getInstitutionIdFromRequestContext(final RequestContext context) { final String institutionId = context.getRequestParameters().get(PARAMETER_INSTITUTION_ID); - return StringUtils.isNotBlank(institutionId) ? null : institutionId; + return StringUtils.isNotBlank(institutionId) ? institutionId : null; } private boolean isOrcidLoginAutoRedirect(final RequestContext context) { From 5b1f64998dc3563f6cf5398c79a45cf7f28efdf7 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 12 Nov 2020 02:00:56 -0500 Subject: [PATCH 05/71] Implement OSF API instn authn prop Created a dedicated OSF API institution authentication properties and integrated them into the non-interactive authentication action to support authentication communication between OSF CAS and OSF API for institution SSO. --- etc/cas/config/cas.properties | 17 ++++++++ etc/cas/config/local/cas-local.properties | 17 ++++++++ .../model/OsfApiAuthenticationProperties.java | 41 +++++++++++++++++++ .../OsfCasSupportActionsConfiguration.java | 1 + ...alFromNonInteractiveCredentialsAction.java | 18 ++++++++ .../AuthenticationProperties.java | 7 ++++ 6 files changed, 101 insertions(+) create mode 100644 src/main/java/io/cos/cas/osf/configuration/model/OsfApiAuthenticationProperties.java diff --git a/etc/cas/config/cas.properties b/etc/cas/config/cas.properties index c014f20a..1ef4f7f2 100644 --- a/etc/cas/config/cas.properties +++ b/etc/cas/config/cas.properties @@ -64,6 +64,23 @@ cas.logout.confirm-logout=false cas.logout.remove-descendant-tickets=false ######################################################################################################################## +######################################################################################################################## +# OSF API Settings for Institution Authentication +######################################################################################################################## +# Authentication Endpoint +# +cas.authn.osf-api.instn-authn-endpoint=https://{{ .Values.apiDomain }}/v2/institutions/auth/ +# +# JWT / JWE secrets for signing and encrypting authentication request payload +# +cas.authn.osf-api.instn-authn-jwt-secret=${OSF_JWT_SECRET} +cas.authn.osf-api.instn-authn-jwe-secret=${OSF_JWE_SECRET} +# +# Path of the XSL file for parsing and transforming XML authentication responses +# +cas.authn.osf-api.instn-authn-xsl-location=file:etc/config/instn-authn.xsl +######################################################################################################################## + ######################################################################################################################## # OSF PostgreSQL Authentication # See: https://apereo.github.io/cas/6.2.x/installation/Configuring-Custom-Authentication.html diff --git a/etc/cas/config/local/cas-local.properties b/etc/cas/config/local/cas-local.properties index 3e3cc6d8..0e32cbd9 100644 --- a/etc/cas/config/local/cas-local.properties +++ b/etc/cas/config/local/cas-local.properties @@ -65,6 +65,23 @@ cas.logout.confirm-logout=false cas.logout.remove-descendant-tickets=false ######################################################################################################################## +######################################################################################################################## +# OSF API Settings for Institution Authentication +######################################################################################################################## +# Authentication Endpoint +# +cas.authn.osf-api.instn-authn-endpoint=http://localhost:8000/v2/institutions/auth/ +# +# JWT / JWE secrets for signing and encrypting authentication request payload +# +cas.authn.osf-api.instn-authn-jwt-secret=osf_api_cas_login_jwt_secret_32b +cas.authn.osf-api.instn-authn-jwe-secret=osf_api_cas_login_jwe_secret_32b +# +# Path of the XSL file for parsing and transforming XML authentication responses +# +cas.authn.osf-api.instn-authn-xsl-location=file:etc/config/instn-authn.xsl +######################################################################################################################## + ######################################################################################################################## # OSF PostgreSQL Authentication # See: https://apereo.github.io/cas/6.2.x/installation/Configuring-Custom-Authentication.html diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfApiAuthenticationProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfApiAuthenticationProperties.java new file mode 100644 index 00000000..fd18eec1 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfApiAuthenticationProperties.java @@ -0,0 +1,41 @@ +package io.cos.cas.osf.configuration.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * This is {@link OsfApiAuthenticationProperties}. + * + * @author Longze Chen + * @since 20.1.0 + */ +@Getter +@Setter +@Accessors(chain = true) +public class OsfApiAuthenticationProperties implements Serializable { + + private static final long serialVersionUID = 427830234394415772L; + + /** + * The institution authentication endpoint of OSF API. + */ + private String instnAuthnEndpoint; + + /** + * The secret that is used for signing the JWT claim. + */ + private String instnAuthnJwtSecret; + + /** + * The secret that is used for encrpyting the signed JWT claim. + */ + private String instnAuthnJweSecret; + + /** + * The location of the XSL file that is used for transforming XML authentication responses. + */ + private String instnAuthnXslLocation; +} diff --git a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java index c42b9003..e0d6fb3c 100644 --- a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java +++ b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java @@ -80,6 +80,7 @@ public Action osfNonInteractiveAuthenticationCheckAction() { serviceTicketRequestWebflowEventResolver.getObject(), adaptiveAuthenticationPolicy.getObject(), centralAuthenticationService.getObject(), + casProperties.getAuthn().getOsfApi(), authnDelegationClients ); } diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java index 519b93a1..f26b0ac7 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java @@ -2,6 +2,7 @@ import io.cos.cas.osf.authentication.credential.OsfPostgresCredential; import io.cos.cas.osf.authentication.support.DelegationProtocol; +import io.cos.cas.osf.configuration.model.OsfApiAuthenticationProperties; import lombok.Getter; import lombok.Setter; @@ -57,6 +58,18 @@ public class OsfPrincipalFromNonInteractiveCredentialsAction extends AbstractNon @NotNull private CentralAuthenticationService centralAuthenticationService; + @NotNull + private String osfApiInstnAuthnEndpoint; + + @NotNull + private String osfApiInstnAuthnJwtSecret; + + @NotNull + private String osfApiInstnAuthnJweSecret; + + @NotNull + private String osfApiInstnAuthnXslLocation; + private Map> authnDelegationClients; public OsfPrincipalFromNonInteractiveCredentialsAction( @@ -64,6 +77,7 @@ public OsfPrincipalFromNonInteractiveCredentialsAction( final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy, final CentralAuthenticationService centralAuthenticationService, + final OsfApiAuthenticationProperties osfApiAuthenticationProperties, final Map> authnDelegationClients ) { super( @@ -73,6 +87,10 @@ public OsfPrincipalFromNonInteractiveCredentialsAction( ); this.centralAuthenticationService = centralAuthenticationService; this.authnDelegationClients = authnDelegationClients; + this.osfApiInstnAuthnEndpoint = osfApiAuthenticationProperties.getInstnAuthnEndpoint(); + this.osfApiInstnAuthnJwtSecret = osfApiAuthenticationProperties.getInstnAuthnJwtSecret(); + this.osfApiInstnAuthnJweSecret = osfApiAuthenticationProperties.getInstnAuthnJweSecret(); + this.osfApiInstnAuthnXslLocation = osfApiAuthenticationProperties.getInstnAuthnXslLocation(); } @SneakyThrows diff --git a/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java b/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java index 82295f6e..ca0b2c7c 100644 --- a/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java +++ b/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java @@ -1,5 +1,6 @@ package org.apereo.cas.configuration.model.core.authentication; +import io.cos.cas.osf.configuration.model.OsfApiAuthenticationProperties; import io.cos.cas.osf.configuration.model.OsfPostgresAuthenticationProperties; import lombok.Getter; @@ -99,6 +100,12 @@ public class AuthenticationProperties implements Serializable { @NestedConfigurationProperty private JsonResourceAuthenticationProperties json = new JsonResourceAuthenticationProperties(); + /** + * OSF API authentication settings. + */ + @NestedConfigurationProperty + private OsfApiAuthenticationProperties osfApi = new OsfApiAuthenticationProperties(); + /** * OSF Postgres authentication settings. */ From 1f8bedc376d1d574f5f4fd2db1c0e43666b88635 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 12 Nov 2020 12:28:52 -0500 Subject: [PATCH 06/71] Add instn-authn.xsl; update Dockerfile-local and docker-reload.sh --- Dockerfile-local | 11 +- docker-reload.sh | 21 +- etc/cas/config/instn-authn.xsl | 982 +++++++++++++++++++++ etc/cas/config/local/instn-authn-local.xsl | 65 ++ 4 files changed, 1073 insertions(+), 6 deletions(-) create mode 100644 etc/cas/config/instn-authn.xsl create mode 100644 etc/cas/config/local/instn-authn-local.xsl diff --git a/Dockerfile-local b/Dockerfile-local index 52fb2238..b9df6ca7 100644 --- a/Dockerfile-local +++ b/Dockerfile-local @@ -13,12 +13,13 @@ RUN mkdir -p ~/.gradle \ && ./gradlew --version; RUN cd cas-overlay && ./gradlew clean build --parallel --no-daemon; -# The build process above in docker may takes a long time depending on your local resources. This OK if you only use +# The build process above in docker may take a long time depending on your local resources. This OK if you only use # CAS by building it once. For local development, building in local shell or with your IDE such as IntelliJ is much -# faster. Afterwards, simply comment out the above "RUN" command and enable the following "COPY" one. In fact, this -# stage can be skipped if you have the WAR built locally. Just need run the second stage with a modified WAR source. +# faster. Afterwards, simply comment out the above "RUN" command above and enable the "COPY" one below. # COPY ./build cas-overlay/build/ +# In fact, the above "overlay" stage can be skipped if you have the WAR built locally. Simply run this second stage +# "cas" with a modified WAR source. FROM adoptopenjdk/openjdk11:alpine-jre AS cas LABEL "Organization"="Center for Open Science" @@ -33,9 +34,9 @@ RUN cd / \ COPY etc/cas/ /etc/cas/ COPY etc/cas/config/ /etc/cas/config/ -# Use "cas-local.properties" and "log4j2-local.xml" for local development -RUN rm etc/cas/config/cas.properties +# Use "cas-local.properties", "instn-authn-local.xsl" and "log4j2-local.xml" for local development COPY etc/cas/config/local/cas-local.properties etc/cas/config/cas.properties +COPY etc/cas/config/local/instn-authn-local.xsl etc/cas/config/instn-authn.xsl COPY etc/cas/config/local/log4j2-local.xml etc/cas/config/log4j2.xml RUN rm -r etc/cas/config/local diff --git a/docker-reload.sh b/docker-reload.sh index 2a685c21..bed6b7fa 100755 --- a/docker-reload.sh +++ b/docker-reload.sh @@ -1,18 +1,37 @@ -#!/bin/bash +#!/bin/zsh # Rebuild locally and replace the WAR +echo "######## Rebuild & Replace WAR ########" +echo "./gradlew clean build" ./gradlew clean build +echo "docker cp ./build/libs/cas.war cas:/cas-overlay" docker cp ./build/libs/cas.war cas:/cas-overlay +echo "################# Done ################" # Sync configuration files +echo "########## Sync Config Files ##########" +echo "docker exec -d cas sh -c \"rm -rf /etc/cas/config/*\"" docker exec -d cas sh -c "rm -rf /etc/cas/config/*" +echo "docker cp ./etc/cas/config/local/cas-local.properties cas:/etc/cas/config/cas.properties" docker cp ./etc/cas/config/local/cas-local.properties cas:/etc/cas/config/cas.properties +echo "docker cp ./etc/cas/config/local/instn-authn-local.xsl cas:/etc/cas/config/instn-authn.xsl" +docker cp ./etc/cas/config/local/instn-authn-local.xsl cas:/etc/cas/config/instn-authn.xsl +echo "docker cp ./etc/cas/config/local/log4j2-local.xml cas:/etc/cas/config/log4j2.xml" docker cp ./etc/cas/config/local/log4j2-local.xml cas:/etc/cas/config/log4j2.xml +echo "################# Done ################" # Sync JSON registered service files +echo "####### Sync Service Definition #######" +echo "docker exec -d cas sh -c \"rm -rf /etc/cas/services/*\"" docker exec -d cas sh -c "rm -rf /etc/cas/services/*" +echo "docker cp ./etc/cas/services/local/. cas:/etc/cas/services" docker cp ./etc/cas/services/local/. cas:/etc/cas/services +echo "################# Done ################" # Restart the container +echo "########## Restart Container ##########" +echo "docker restart cas" docker restart cas +echo "docker logs -f --tail 0 cas" +echo "####### OSF CAS LOG STARTS HERE #######" docker logs -f --tail 0 cas diff --git a/etc/cas/config/instn-authn.xsl b/etc/cas/config/instn-authn.xsl new file mode 100644 index 00000000..19bdf141 --- /dev/null +++ b/etc/cas/config/instn-authn.xsl @@ -0,0 +1,982 @@ + + + + + + + + + + + + + + + + + + + + asu + + + + + + + + + + + + + + + + + + + + + bt + + + + + + + + + + + + + + + + + + + + bu + + + + + + + + + + + + + + + + + + + + brown + + + + + + + + + + + + + + + + + + + + callutheran + + + + + + + + + + + + + + + + cmu + + + + + + + + + + + + + + + + + + + + cornell + + + + + + + + + + + + + + + + + + + + cwru + + + + + + + + + + + + + + + + + + + + duke + + + + + + + + + + + + + + + + + + + + ecu + + + + + + + + + + + + + + + + + + + + ferris + + + + + + + + + + + + + + + + + + fsu + + + + + + + + + + + + + + + + gmu + + + + + + + + + + + + + + + + + + + + gwu + + + + + + + + + + + + + + + + + + + + iit + + + + + + + + + + + + + + + + + + + + itb + + + + + + + + + + + + + + + + + + + + jmu + + + + + + + + + + + + + + + + + + + + jhu + + + + + + + + + + + + + + + + mit + + + + + + + + + + + + + + + + + + + + mq + + + + + + + + + + + + + + + + + + + + nyu + + + + + + + + + + + + + + + + ou + + + + + + + + + + + + + + + + + + + + csic + + + + + + + + + + + + + + + + temple + + + + + + + + + + + + + + + + + + + + tufts + + + + + + + + + + + + + + + + + + + + ugent + + + + + + + + + + + + + + + + + + + + ua + + + + + + + + + + + + + + + + + + + + ubc + + + + + + + + + + + + + + + + ucla + + + + + + + + + + + + + + + + + + + + ucsd + + + + + + + + + + + + + + + + ucr + + + + + + + + + + + + + + + + + + + + uct + + + + + + + + + + + + + + + + + + + + uc + + + + + + + + + + + + + + + + colorado + + + + + + + + + + + + + + + + ugoe + + + + + + + + + + + + + + + + + + + + universityofkent + + + + + + + + + + + + + + + + mq + + + + + + + + + + + + + + + + + + + + unc + + + + + + + + + + + + + + + + + + + + nd + + + + + + + + + + + + + + + + usc + + + + + + + + + + + + + + + + + + + + + + sc + + + + + + + + + + + + + + + + + + + + utdallas + + + + + + + + + + + + + + + + + + + + uva + + + + + + + + + + + + + + + + uw + + + + + + + + + + + + + + + + uwstout + + + + + + + + + + + + + + + + + + + + vcu + + + + + + + + + + + + + + + + vt + + + + + + + + + + + + + + + + wustl + + + + + + + + + + + + + + + + + + + + Error: Unknown Identity Provider '' + + + + + + + + + + + + + cord + + + + + + + + + + + + + + + + okstate + + + + + + + + + + + + + + + + + + Error: Unknown Identity Provider '' + + + + + + Error: Unknown Delegation Protocol '' + + + + + + diff --git a/etc/cas/config/local/instn-authn-local.xsl b/etc/cas/config/local/instn-authn-local.xsl new file mode 100644 index 00000000..7b281fcc --- /dev/null +++ b/etc/cas/config/local/instn-authn-local.xsl @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + esu + + + + + + + + + + + + + Error: Unknown Identity Provider '' + + + + + + + + + + + ecu + + + + + + + + + + + + + Error: Unknown Identity Provider '' + + + + + + Error: Unknown Delegation Protocol '' + + + + From 3d63c25804bc9ebb3f757fe18ef78420f4c0ce9e Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 12 Nov 2020 15:41:56 -0500 Subject: [PATCH 07/71] Refactor OSF API prop and replace separate attrs w/ one single object --- ...nProperties.java => OsfApiProperties.java} | 4 ++-- ...alFromNonInteractiveCredentialsAction.java | 19 ++++--------------- .../AuthenticationProperties.java | 6 +++--- 3 files changed, 9 insertions(+), 20 deletions(-) rename src/main/java/io/cos/cas/osf/configuration/model/{OsfApiAuthenticationProperties.java => OsfApiProperties.java} (87%) diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfApiAuthenticationProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfApiProperties.java similarity index 87% rename from src/main/java/io/cos/cas/osf/configuration/model/OsfApiAuthenticationProperties.java rename to src/main/java/io/cos/cas/osf/configuration/model/OsfApiProperties.java index fd18eec1..2ed7f7f9 100644 --- a/src/main/java/io/cos/cas/osf/configuration/model/OsfApiAuthenticationProperties.java +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfApiProperties.java @@ -7,7 +7,7 @@ import java.io.Serializable; /** - * This is {@link OsfApiAuthenticationProperties}. + * This is {@link OsfApiProperties}. * * @author Longze Chen * @since 20.1.0 @@ -15,7 +15,7 @@ @Getter @Setter @Accessors(chain = true) -public class OsfApiAuthenticationProperties implements Serializable { +public class OsfApiProperties implements Serializable { private static final long serialVersionUID = 427830234394415772L; diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java index f26b0ac7..2085ade6 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java @@ -2,7 +2,7 @@ import io.cos.cas.osf.authentication.credential.OsfPostgresCredential; import io.cos.cas.osf.authentication.support.DelegationProtocol; -import io.cos.cas.osf.configuration.model.OsfApiAuthenticationProperties; +import io.cos.cas.osf.configuration.model.OsfApiProperties; import lombok.Getter; import lombok.Setter; @@ -59,17 +59,9 @@ public class OsfPrincipalFromNonInteractiveCredentialsAction extends AbstractNon private CentralAuthenticationService centralAuthenticationService; @NotNull - private String osfApiInstnAuthnEndpoint; + private OsfApiProperties osfApiProperties; @NotNull - private String osfApiInstnAuthnJwtSecret; - - @NotNull - private String osfApiInstnAuthnJweSecret; - - @NotNull - private String osfApiInstnAuthnXslLocation; - private Map> authnDelegationClients; public OsfPrincipalFromNonInteractiveCredentialsAction( @@ -77,7 +69,7 @@ public OsfPrincipalFromNonInteractiveCredentialsAction( final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy, final CentralAuthenticationService centralAuthenticationService, - final OsfApiAuthenticationProperties osfApiAuthenticationProperties, + final OsfApiProperties osfApiProperties, final Map> authnDelegationClients ) { super( @@ -86,11 +78,8 @@ public OsfPrincipalFromNonInteractiveCredentialsAction( adaptiveAuthenticationPolicy ); this.centralAuthenticationService = centralAuthenticationService; + this.osfApiProperties = osfApiProperties; this.authnDelegationClients = authnDelegationClients; - this.osfApiInstnAuthnEndpoint = osfApiAuthenticationProperties.getInstnAuthnEndpoint(); - this.osfApiInstnAuthnJwtSecret = osfApiAuthenticationProperties.getInstnAuthnJwtSecret(); - this.osfApiInstnAuthnJweSecret = osfApiAuthenticationProperties.getInstnAuthnJweSecret(); - this.osfApiInstnAuthnXslLocation = osfApiAuthenticationProperties.getInstnAuthnXslLocation(); } @SneakyThrows diff --git a/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java b/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java index ca0b2c7c..b274e36e 100644 --- a/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java +++ b/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java @@ -1,6 +1,6 @@ package org.apereo.cas.configuration.model.core.authentication; -import io.cos.cas.osf.configuration.model.OsfApiAuthenticationProperties; +import io.cos.cas.osf.configuration.model.OsfApiProperties; import io.cos.cas.osf.configuration.model.OsfPostgresAuthenticationProperties; import lombok.Getter; @@ -101,10 +101,10 @@ public class AuthenticationProperties implements Serializable { private JsonResourceAuthenticationProperties json = new JsonResourceAuthenticationProperties(); /** - * OSF API authentication settings. + * OSF API settings. */ @NestedConfigurationProperty - private OsfApiAuthenticationProperties osfApi = new OsfApiAuthenticationProperties(); + private OsfApiProperties osfApi = new OsfApiProperties(); /** * OSF Postgres authentication settings. From 76c4aec9eb000ec9b25ac6919d76f2d12c8d3a7e Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 12 Nov 2020 17:34:11 -0500 Subject: [PATCH 08/71] Implement OSF URL prop and put it in the flow context CASv4.1.x-based oldCAS uses JSP as the template engine with Spring. Settings defined in .properties files can be accessed directly in JSPs. However, it is no longer the case for CASv6.2.x-based newCAS that uses Thymeleaf as the template engine (with Spring of course). Thus, server-specific URLs (i.e. production, test and stage) need to be manually put into the flow context for templates to access. --- etc/cas/config/cas.properties | 23 +++++ etc/cas/config/local/cas-local.properties | 23 +++++ .../configuration/model/OsfUrlProperties.java | 91 +++++++++++++++++++ .../OsfCasSupportActionsConfiguration.java | 1 + ...alFromNonInteractiveCredentialsAction.java | 14 +++ .../AuthenticationProperties.java | 7 ++ 6 files changed, 159 insertions(+) create mode 100644 src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java diff --git a/etc/cas/config/cas.properties b/etc/cas/config/cas.properties index 1ef4f7f2..2a535dbb 100644 --- a/etc/cas/config/cas.properties +++ b/etc/cas/config/cas.properties @@ -64,6 +64,29 @@ cas.logout.confirm-logout=false cas.logout.remove-descendant-tickets=false ######################################################################################################################## +######################################################################################################################## +# OSF URLs +######################################################################################################################## +# OSF +# +cas.authn.osf-url.home=https://{{ .Values.osfDomain }}/ +cas.authn.osf-url.dashboard=https://{{ .Values.osfDomain }}/dashboard/ +cas.authn.osf-url.logout=https://{{ .Values.osfDomain }}/logout/ +cas.authn.osf-url.resend-confirmation=https://{{ .Values.osfDomain }}/resend/ +cas.authn.osf-url.forgot-password=https://{{ .Values.osfDomain }}/forgotpassword/ +cas.authn.osf-url.register=https://{{ .Values.osfDomain }}/register/ +cas.authn.osf-url.search=https://{{ .Values.osfDomain }}/search/ +cas.authn.osf-url.support=https://{{ .Values.osfDomain }}/support/ +cas.authn.osf-url.donate=https://www.cos.io/about/support-cos/ +# +# OSF Products +# +cas.authn.osf-url.preprints-home=https://{{ .Values.osfDomain }}/preprints/ +cas.authn.osf-url.registries-home=https://{{ .Values.osfDomain }}/registries/ +cas.authn.osf-url.institutions-home=https://{{ .Values.osfDomain }}/institutions/ +cas.authn.osf-url.meetings-home=https://{{ .Values.osfDomain }}/meetings/ +######################################################################################################################## + ######################################################################################################################## # OSF API Settings for Institution Authentication ######################################################################################################################## diff --git a/etc/cas/config/local/cas-local.properties b/etc/cas/config/local/cas-local.properties index 0e32cbd9..b42c0d6b 100644 --- a/etc/cas/config/local/cas-local.properties +++ b/etc/cas/config/local/cas-local.properties @@ -65,6 +65,29 @@ cas.logout.confirm-logout=false cas.logout.remove-descendant-tickets=false ######################################################################################################################## +######################################################################################################################## +# OSF URLs +######################################################################################################################## +# OSF +# +cas.authn.osf-url.home=http://localhost:5000/ +cas.authn.osf-url.dashboard=http://localhost:5000/dashboard/ +cas.authn.osf-url.logout=http://localhost:5000/logout/ +cas.authn.osf-url.resend-confirmation=http://localhost:5000/resend/ +cas.authn.osf-url.forgot-password=http://localhost:5000/forgotpassword/ +cas.authn.osf-url.register=http://localhost:5000/register/ +cas.authn.osf-url.search=http://localhost:5000/search/ +cas.authn.osf-url.support=http://localhost:5000/support/ +cas.authn.osf-url.donate=https://www.cos.io/about/support-cos/ +# +# OSF Products +# +cas.authn.osf-url.preprints-home=http://localhost:5000/preprints/ +cas.authn.osf-url.registries-home=http://localhost:5000/registries/ +cas.authn.osf-url.institutions-home=http://localhost:5000/institutions/ +cas.authn.osf-url.meetings-home=http://localhost:5000/meetings/ +######################################################################################################################## + ######################################################################################################################## # OSF API Settings for Institution Authentication ######################################################################################################################## diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java new file mode 100644 index 00000000..5ca930b4 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java @@ -0,0 +1,91 @@ +package io.cos.cas.osf.configuration.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * This is {@link OsfUrlProperties}. + * + * CASv4.1.x-based oldCAS uses Java Server Pages (JSP) as the template engine with Spring Framework. Settings defined + * in .properties files can be accessed directly in JSP. However, this is no longer the case for CASv6.2.x-based newCAS + * which uses Thymeleaf as the template engine with Spring Framework. Thus, server-specific (i.e. production, test and + * staging servers) URLs need to be manually put into the flow context for the templates to access. + * + * @author Longze Chen + * @since 20.1.0 + */ +@Getter +@Setter +@Accessors(chain = true) +public class OsfUrlProperties implements Serializable { + + private static final long serialVersionUID = 5799818150523709901L; + + /** + * OSF home page URL. + */ + private String home; + + /** + * OSF dashboard page URL (must-be-signed-in). + */ + private String dashboard; + + /** + * OSF sign-up page URL. + */ + private String register; + + /** + * OSF logout endpoint URL. + */ + private String logout; + + /** + * OSF resend-confirmation page URL. + */ + private String resendConfirmation; + + /** + * OSF forgot-password page URL + */ + private String forgotPassword; + + /** + * OSF Preprints landing page URL. + */ + private String preprintsHome; + + /** + * OSF Registries landing page URL. + */ + private String registriesHome; + + /** + * OSF Institutions landing page URL. + */ + private String institutionsHome; + + /** + * OSF meetings landing page URL. + */ + private String meetingsHome; + + /** + * OSF search page URL. + */ + private String search; + + /** + * OSF support page URL. + */ + private String support; + + /** + * OSF / COS donation page URL. + */ + private String donate; +} diff --git a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java index e0d6fb3c..76992719 100644 --- a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java +++ b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java @@ -80,6 +80,7 @@ public Action osfNonInteractiveAuthenticationCheckAction() { serviceTicketRequestWebflowEventResolver.getObject(), adaptiveAuthenticationPolicy.getObject(), centralAuthenticationService.getObject(), + casProperties.getAuthn().getOsfUrl(), casProperties.getAuthn().getOsfApi(), authnDelegationClients ); diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java index 2085ade6..5b7148ba 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java @@ -3,6 +3,7 @@ import io.cos.cas.osf.authentication.credential.OsfPostgresCredential; import io.cos.cas.osf.authentication.support.DelegationProtocol; import io.cos.cas.osf.configuration.model.OsfApiProperties; +import io.cos.cas.osf.configuration.model.OsfUrlProperties; import lombok.Getter; import lombok.Setter; @@ -27,6 +28,7 @@ import javax.validation.constraints.NotNull; import java.util.List; import java.util.Map; +import java.util.Optional; /** * This is {@link OsfPrincipalFromNonInteractiveCredentialsAction}. @@ -49,6 +51,8 @@ public class OsfPrincipalFromNonInteractiveCredentialsAction extends AbstractNon private static final String VERIFICATION_KEY_PARAMETER_NAME = "verification_key"; + private static final String OSF_URL_FLOW_PARAMETER = "osfUrl"; + private static final String AUTHENTICATION_EXCEPTION = "authnError"; public static final String INSTITUTION_CLIENTS_PARAMETER_NAME = "institutionClients"; @@ -58,6 +62,9 @@ public class OsfPrincipalFromNonInteractiveCredentialsAction extends AbstractNon @NotNull private CentralAuthenticationService centralAuthenticationService; + @NotNull + private OsfUrlProperties osfUrlProperties; + @NotNull private OsfApiProperties osfApiProperties; @@ -69,6 +76,7 @@ public OsfPrincipalFromNonInteractiveCredentialsAction( final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy, final CentralAuthenticationService centralAuthenticationService, + final OsfUrlProperties osfUrlProperties, final OsfApiProperties osfApiProperties, final Map> authnDelegationClients ) { @@ -78,6 +86,7 @@ public OsfPrincipalFromNonInteractiveCredentialsAction( adaptiveAuthenticationPolicy ); this.centralAuthenticationService = centralAuthenticationService; + this.osfUrlProperties = osfUrlProperties; this.osfApiProperties = osfApiProperties; this.authnDelegationClients = authnDelegationClients; } @@ -139,6 +148,11 @@ protected Credential constructCredentialsFromRequest(final RequestContext contex @Override protected Event doPreExecute(final RequestContext context) throws Exception { + OsfUrlProperties osfUrl = Optional.of(context).map(requestContext + -> (OsfUrlProperties) requestContext.getFlowScope().get(OSF_URL_FLOW_PARAMETER)).orElse(null); + if (osfUrl == null) { + context.getFlowScope().put(OSF_URL_FLOW_PARAMETER, osfUrlProperties); + } return super.doPreExecute(context); } diff --git a/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java b/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java index b274e36e..d8d7b1fd 100644 --- a/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java +++ b/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java @@ -2,6 +2,7 @@ import io.cos.cas.osf.configuration.model.OsfApiProperties; import io.cos.cas.osf.configuration.model.OsfPostgresAuthenticationProperties; +import io.cos.cas.osf.configuration.model.OsfUrlProperties; import lombok.Getter; import lombok.Setter; @@ -100,6 +101,12 @@ public class AuthenticationProperties implements Serializable { @NestedConfigurationProperty private JsonResourceAuthenticationProperties json = new JsonResourceAuthenticationProperties(); + /** + * OSF URL settings. + */ + @NestedConfigurationProperty + private OsfUrlProperties osfUrl = new OsfUrlProperties(); + /** * OSF API settings. */ From 1d4e34d636100f0ca85b91ba86d1343327dcc5fa Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 12 Nov 2020 18:11:29 -0500 Subject: [PATCH 09/71] Use cas.properties instead of messages.properties for URLs on FE In addition, "Continue to OSF" on the generic / no-service login success page now goes to OSF dashboard instead of OSF home so that auto-login is triggered. --- src/main/resources/messages.properties | 29 ++----------------- .../templates/casAccountDisabledView.html | 2 +- .../casAccountNotConfirmedIdPView.html | 2 +- .../casAccountNotConfirmedOsfView.html | 4 +-- .../templates/casGenericSuccessView.html | 4 +-- .../casInstitutionSsoNotImplementedView.html | 2 +- .../templates/casInvalidUserStatusView.html | 2 +- .../casInvalidVerificationKeyView.html | 2 +- .../resources/templates/casLogoutView.html | 2 +- .../templates/casServiceErrorView.html | 2 +- src/main/resources/templates/error.html | 2 +- .../resources/templates/fragments/header.html | 24 +++++++-------- .../templates/fragments/pmlinks.html | 6 ++-- .../templates/fragments/totploginform.html | 2 +- 14 files changed, 31 insertions(+), 54 deletions(-) diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 181f2a99..d6fbeb89 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -504,16 +504,16 @@ noop.message=This's a noop message. # App drawer (left) # cas.drawer.title=OSF CAS -cas.drawer.subtitle=OSF CAS is the central authentication and authorization service for OSF +cas.drawer.subtitle=OSF CAS is the central authentication service for OSF cas.login.resources.cas.home=CAS Home cas.login.resources.osf.home=OSF Home cas.login.resources.osf.preprints=OSF Preprints cas.login.resources.osf.registries=OSF Registries cas.login.resources.osf.meetings=OSF Meetings cas.login.resources.osf.institutions=OSF Institutions +cas.login.resources.osf.search=Search cas.login.resources.osf.support=OSF Support -cas.login.resources.cos.donate=Donate -cas.login.resources.cos.home=COS Home +cas.login.resources.osf.donate=Donate # # App notifications (right) # @@ -646,29 +646,6 @@ screen.onetimepasswordrequired.message=Two-factor authentication has been enable screen.institutionssonotimplemented.heading=Institution login error screen.institutionssonotimplemented.message=The implementation of institution login page is work-in-progress, please \ check back later ... -# -# OSF URLs -# -# OSF -# -osf.home.url=https://staging3.osf.io/ -osf.logout.url=https://staging3.osf.io/logout -osf.resend.osf.confirmation.url=https://staging3.osf.io/resend/ -osf.forgot.password.url=https://staging3.osf.io/forgotpassword/ -osf.create.account.url=https://staging3.osf.io/register/ -# -# API -# -# Other -# -osf.preprints.home.url=https://staging3.osf.io/preprints/ -osf.registries.home.url=https://staging3.osf.io/registries/ -osf.institutions.home.url=https://staging3.osf.io/institutions/ -osf.meetings.home.url=https://staging3.osf.io/meetings/ -osf.support.url=https://staging3.osf.io/support/ -osf.cos.donation.url=https://www.cos.io/about/support-cos/ -osf.cos.home.url=https://www.cos.io/ -# ######################################################################################################################## # # Enf of OSF CAS customized messages.properties diff --git a/src/main/resources/templates/casAccountDisabledView.html b/src/main/resources/templates/casAccountDisabledView.html index 2915fe30..4e0fef4e 100644 --- a/src/main/resources/templates/casAccountDisabledView.html +++ b/src/main/resources/templates/casAccountDisabledView.html @@ -25,7 +25,7 @@

diff --git a/src/main/resources/templates/casAccountNotConfirmedIdPView.html b/src/main/resources/templates/casAccountNotConfirmedIdPView.html index 29fb0fe7..f23888f1 100644 --- a/src/main/resources/templates/casAccountNotConfirmedIdPView.html +++ b/src/main/resources/templates/casAccountNotConfirmedIdPView.html @@ -25,7 +25,7 @@

diff --git a/src/main/resources/templates/casAccountNotConfirmedOsfView.html b/src/main/resources/templates/casAccountNotConfirmedOsfView.html index de79a7b9..85048bae 100644 --- a/src/main/resources/templates/casAccountNotConfirmedOsfView.html +++ b/src/main/resources/templates/casAccountNotConfirmedOsfView.html @@ -25,12 +25,12 @@

diff --git a/src/main/resources/templates/casGenericSuccessView.html b/src/main/resources/templates/casGenericSuccessView.html index af9e40b5..7301f903 100644 --- a/src/main/resources/templates/casGenericSuccessView.html +++ b/src/main/resources/templates/casGenericSuccessView.html @@ -23,10 +23,10 @@

diff --git a/src/main/resources/templates/casInstitutionSsoNotImplementedView.html b/src/main/resources/templates/casInstitutionSsoNotImplementedView.html index fa52971a..7b1206a0 100644 --- a/src/main/resources/templates/casInstitutionSsoNotImplementedView.html +++ b/src/main/resources/templates/casInstitutionSsoNotImplementedView.html @@ -25,7 +25,7 @@

diff --git a/src/main/resources/templates/casInvalidUserStatusView.html b/src/main/resources/templates/casInvalidUserStatusView.html index 9cafce76..12cf1b2c 100644 --- a/src/main/resources/templates/casInvalidUserStatusView.html +++ b/src/main/resources/templates/casInvalidUserStatusView.html @@ -25,7 +25,7 @@

diff --git a/src/main/resources/templates/casInvalidVerificationKeyView.html b/src/main/resources/templates/casInvalidVerificationKeyView.html index 8b8b16ba..a56b93f2 100644 --- a/src/main/resources/templates/casInvalidVerificationKeyView.html +++ b/src/main/resources/templates/casInvalidVerificationKeyView.html @@ -25,7 +25,7 @@

diff --git a/src/main/resources/templates/casLogoutView.html b/src/main/resources/templates/casLogoutView.html index 18a0b36d..7118f8f2 100644 --- a/src/main/resources/templates/casLogoutView.html +++ b/src/main/resources/templates/casLogoutView.html @@ -28,7 +28,7 @@

diff --git a/src/main/resources/templates/casServiceErrorView.html b/src/main/resources/templates/casServiceErrorView.html index e7e173df..c75496f5 100644 --- a/src/main/resources/templates/casServiceErrorView.html +++ b/src/main/resources/templates/casServiceErrorView.html @@ -25,7 +25,7 @@

diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index d1283e95..0c3a0314 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -26,7 +26,7 @@

- +
diff --git a/src/main/resources/templates/fragments/pmlinks.html b/src/main/resources/templates/fragments/pmlinks.html index bef333eb..0ccf9071 100644 --- a/src/main/resources/templates/fragments/pmlinks.html +++ b/src/main/resources/templates/fragments/pmlinks.html @@ -14,15 +14,15 @@ diff --git a/src/main/resources/templates/fragments/totploginform.html b/src/main/resources/templates/fragments/totploginform.html index f044a796..1267233c 100644 --- a/src/main/resources/templates/fragments/totploginform.html +++ b/src/main/resources/templates/fragments/totploginform.html @@ -114,7 +114,7 @@

From 82503f0a68ba527e2091f973d1a6ff9398f8486b Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Wed, 18 Nov 2020 22:50:48 -0500 Subject: [PATCH 10/71] Fix instn-authn.xsl file path --- etc/cas/config/cas.properties | 2 +- etc/cas/config/local/cas-local.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/cas/config/cas.properties b/etc/cas/config/cas.properties index 2a535dbb..d258f9e0 100644 --- a/etc/cas/config/cas.properties +++ b/etc/cas/config/cas.properties @@ -101,7 +101,7 @@ cas.authn.osf-api.instn-authn-jwe-secret=${OSF_JWE_SECRET} # # Path of the XSL file for parsing and transforming XML authentication responses # -cas.authn.osf-api.instn-authn-xsl-location=file:etc/config/instn-authn.xsl +cas.authn.osf-api.instn-authn-xsl-location=file:/etc/cas/config/instn-authn.xsl ######################################################################################################################## ######################################################################################################################## diff --git a/etc/cas/config/local/cas-local.properties b/etc/cas/config/local/cas-local.properties index b42c0d6b..371c0218 100644 --- a/etc/cas/config/local/cas-local.properties +++ b/etc/cas/config/local/cas-local.properties @@ -102,7 +102,7 @@ cas.authn.osf-api.instn-authn-jwe-secret=osf_api_cas_login_jwe_secret_32b # # Path of the XSL file for parsing and transforming XML authentication responses # -cas.authn.osf-api.instn-authn-xsl-location=file:etc/config/instn-authn.xsl +cas.authn.osf-api.instn-authn-xsl-location=file:/etc/cas/config/instn-authn.xsl ######################################################################################################################## ######################################################################################################################## From e86150b014a1e78d0be48f90c6bf41c4f1e5a5f6 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 19 Nov 2020 16:47:19 -0500 Subject: [PATCH 11/71] Expand non-interactive action to support base institution sso * For both pac4j-cas and shib-saml: use an XSL file to transform delegation attributes in the credential to a JSON object; make a OSF API request with JWT/JWE signed/encrypted payload; use a dedicated object to store API authentication result; and throw a dedicated institution SSO failed exception upon error * For pac4j-cas: extract authentication principal and attributes from the delegated authentication result and put them into the delegation attributes of the credential. --- build.gradle | 6 + gradle.properties | 2 + .../InstitutionSsoFailedException.java | 29 ++ ...alFromNonInteractiveCredentialsAction.java | 300 +++++++++++++++++- ...OsfApiInstitutionAuthenticationResult.java | 29 ++ 5 files changed, 363 insertions(+), 3 deletions(-) create mode 100644 src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java create mode 100644 src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java diff --git a/build.gradle b/build.gradle index 13358a9f..aae47336 100644 --- a/build.gradle +++ b/build.gradle @@ -123,6 +123,12 @@ dependencies { // Google GSON implementation "com.google.code.gson:gson:${gsonVersion}" + + // Javascript Object Signing and Encryption (JOSE) and JSON Web Tokens (JWT) + implementation "com.nimbusds:nimbus-jose-jwt:${nimbusJoseVersion}" + + // Apache HttpComponents Client fluent API + implementation "org.apache.httpcomponents:fluent-hc:${fluentHcVersion}" } tasks.findByName("jibDockerBuild") diff --git a/gradle.properties b/gradle.properties index 948c5eb3..57abfbd4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,3 +30,5 @@ allowInsecureRegistries=false gsonVersion=2.8.6 hibernateCoreVersion=5.4.21.Final springBootTomcatVersion=9.0.37 +nimbusJoseVersion=8.20.1 +fluentHcVersion=4.5.12 diff --git a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java new file mode 100644 index 00000000..4702d915 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java @@ -0,0 +1,29 @@ +package io.cos.cas.osf.authentication.exception; + +import lombok.NoArgsConstructor; + +import javax.security.auth.login.AccountException; + +/** + * Describes an authentication error condition where institution SSO has failed. + * + * @author Longze Chen + * @since 20.1.0 + */ +@NoArgsConstructor +public class InstitutionSsoFailedException extends AccountException { + + /** + * Serialization metadata. + */ + private static final long serialVersionUID = 6977786012016534260L; + + /** + * Instantiates a new {@link InstitutionSsoFailedException}. + * + * @param msg the msg + */ + public InstitutionSsoFailedException(final String msg) { + super(msg); + } +} diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java index 5b7148ba..06b9758a 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfPrincipalFromNonInteractiveCredentialsAction.java @@ -1,9 +1,25 @@ package io.cos.cas.osf.web.flow.login; import io.cos.cas.osf.authentication.credential.OsfPostgresCredential; +import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; import io.cos.cas.osf.authentication.support.DelegationProtocol; import io.cos.cas.osf.configuration.model.OsfApiProperties; import io.cos.cas.osf.configuration.model.OsfUrlProperties; +import io.cos.cas.osf.web.support.OsfApiInstitutionAuthenticationResult; + +import com.nimbusds.jose.crypto.DirectEncrypter; +import com.nimbusds.jose.crypto.MACSigner; +import com.nimbusds.jose.EncryptionMethod; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWEAlgorithm; +import com.nimbusds.jose.JWEHeader; +import com.nimbusds.jose.JWEObject; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.JWSSigner; +import com.nimbusds.jose.Payload; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; import lombok.Getter; import lombok.Setter; @@ -11,21 +27,50 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.fluent.Request; +import org.apache.http.entity.ContentType; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.message.BasicHeader; import org.apereo.cas.CentralAuthenticationService; +import org.apereo.cas.authentication.Authentication; import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy; import org.apereo.cas.authentication.Credential; import org.apereo.cas.authentication.principal.ClientCredential; +import org.apereo.cas.authentication.principal.Principal; import org.apereo.cas.web.flow.actions.AbstractNonInteractiveCredentialsAction; import org.apereo.cas.web.flow.resolver.CasDelegatingWebflowEventResolver; import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver; import org.apereo.cas.web.support.WebUtils; +import org.json.JSONObject; +import org.json.XML; + +import org.springframework.util.ResourceUtils; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.security.auth.login.AccountException; import javax.servlet.http.HttpServletRequest; import javax.validation.constraints.NotNull; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Optional; @@ -55,6 +100,8 @@ public class OsfPrincipalFromNonInteractiveCredentialsAction extends AbstractNon private static final String AUTHENTICATION_EXCEPTION = "authnError"; + private static final int SIXTY_SECONDS = 60 * 1000; + public static final String INSTITUTION_CLIENTS_PARAMETER_NAME = "institutionClients"; public static final String NON_INSTITUTION_CLIENTS_PARAMETER_NAME = "nonInstitutionClients"; @@ -71,6 +118,8 @@ public class OsfPrincipalFromNonInteractiveCredentialsAction extends AbstractNon @NotNull private Map> authnDelegationClients; + private Transformer instnAuthnRespTransformer; + public OsfPrincipalFromNonInteractiveCredentialsAction( final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver, final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, @@ -117,11 +166,73 @@ protected Credential constructCredentialsFromRequest(final RequestContext contex clientName, credential.getId() ); + final Authentication authentication = WebUtils.getAuthentication(context); + final Principal principal = authentication.getPrincipal(); final OsfPostgresCredential osfPostgresCredential = new OsfPostgresCredential(); - osfPostgresCredential.setUsername(credential.getId()); - osfPostgresCredential.setInstitutionId(((ClientCredential) credential).getClientName()); - osfPostgresCredential.setRemotePrincipal(true); + osfPostgresCredential.setRemotePrincipal(Boolean.TRUE); osfPostgresCredential.setDelegationProtocol(DelegationProtocol.CAS_PAC4J); + osfPostgresCredential.getDelegationAttributes().put("Cas-Identity-Provider", clientName); + if (principal.getAttributes().size() > 0) { + for (final Map.Entry> entry : principal.getAttributes().entrySet()) { + final String attributeKey = entry.getKey(); + final List attributeValues = entry.getValue(); + if (attributeValues.isEmpty()) { + LOGGER.error( + "[CAS PAC4J] Empty-value attribute detected: '{}', '{}', '{}', '{}'", + clientName, + principal.getId(), + attributeKey, + attributeValues + ); + } else if (attributeValues.size() > 1) { + LOGGER.error( + "[CAS PAC4J] Multi-value attribute detected: '{}', '{}', '{}', '{}'", + clientName, + principal.getId(), + attributeKey, + attributeValues + ); + } else { + final Object firstAttributeValue = attributeValues.get(0); + LOGGER.debug( + "[CAS PAC4J] User's institutional identity '{}': '{}' w/ attribute '{}': '{}'", + clientName, + principal.getId(), + attributeKey, + firstAttributeValue + ); + if (firstAttributeValue instanceof String) { + LOGGER.info( + "[CAS PAC4J] Delegation attribute map updated: '{}', '{}', '{}', '{}'", + clientName, + principal.getId(), + attributeKey, + firstAttributeValue + ); + osfPostgresCredential.getDelegationAttributes().put( + attributeKey, + String.valueOf(firstAttributeValue) + ); + } else { + LOGGER.error( + "[CAS PAC4J] Attribute w/ non-string value: '{}', '{}', '{}', '{}', '{}'", + clientName, + principal.getId(), + entry.getKey(), + attributeKey, + firstAttributeValue.getClass().getName() + ); + } + } + } + } else { + LOGGER.error("[CAS PAC4J] No attributes for user '{} with client '{}'", principal.getId(), clientName); + } + + final OsfApiInstitutionAuthenticationResult remoteUserInfo = notifyOsfApiOfInstnAuthnSuccess(osfPostgresCredential); + osfPostgresCredential.setUsername(remoteUserInfo.getUsername()); + osfPostgresCredential.setInstitutionId(remoteUserInfo.getInstitutionId()); + WebUtils.removeCredential(context); return osfPostgresCredential; } LOGGER.debug("Unsupported delegation client [{}]", clientName); @@ -173,4 +284,187 @@ protected Event doExecute(final RequestContext requestContext) { */ @Override protected void onError(final RequestContext context) {} + + /** + * This method allows the bean instance to perform validation of its overall configuration and final initialization + * when all bean properties have been set. + * + * @throws Exception in the event of mis-configuration or if initialization fails for any other reason + */ + @Override + public void afterPropertiesSet() throws Exception { + final File xslFile = ResourceUtils.getFile(osfApiProperties.getInstnAuthnXslLocation()); + final StreamSource xslStreamSource = new StreamSource(xslFile); + final TransformerFactory tFactory = TransformerFactory.newInstance(); + instnAuthnRespTransformer = tFactory.newTransformer(xslStreamSource); + super.afterPropertiesSet(); + } + + /** + * Extract delegated authentication data from the given {@link OsfPostgresCredential} object and normalize it as + * required by the OSF API institution authentication endpoint. + * + * @param credential the credential object bearing delegated authentication data + * + * @return a {@link JSONObject} object bearing data required by the OSF API institution authentication endpoint + * @throws ParserConfigurationException a parser configuration exception + * @throws TransformerException a transformer exception + */ + protected JSONObject extractInstnAuthnDataFromCredential(final OsfPostgresCredential credential) + throws ParserConfigurationException, TransformerException { + + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + final DocumentBuilder builder = factory.newDocumentBuilder(); + final Document document = builder.newDocument(); + final Element rootElement = document.createElement("auth"); + document.appendChild(rootElement); + + final Element delegationProtocolAttr = document.createElement("attribute"); + delegationProtocolAttr.setAttribute("name", "Delegation-Protocol"); + delegationProtocolAttr.setAttribute("value", credential.getDelegationProtocol().getId()); + rootElement.appendChild(delegationProtocolAttr); + + for (final String key : credential.getDelegationAttributes().keySet()) { + final Element attribute = document.createElement("attribute"); + attribute.setAttribute("name", key); + attribute.setAttribute("value", credential.getDelegationAttributes().get(key)); + rootElement.appendChild(attribute); + } + + final DOMSource source = new DOMSource(document); + final StringWriter writer = new StringWriter(); + final StreamResult result = new StreamResult(writer); + instnAuthnRespTransformer.transform(source, result); + + return XML.toJSONObject(writer.getBuffer().toString()); + } + + /** + * Securely notify OSF API of a successful institution authentication between OSF CAS and an external IdP. This + * allows OSF API to either create a verified OSF account or find an existing active OSF account, and then assign + * institutional affiliation to them. OSF API returns HTTP 204 if successful and HTTP 401 / 403 if failed. Refer + * to the following code for the latest behavior of the institution authentication endpoint of OSF API: + * https://github.com/CenterForOpenScience/osf.io/blob/develop/api/institutions/authentication.py + * + * @param credential the credential object bearing delegated authentication data + * @return {@link OsfApiInstitutionAuthenticationResult} an object that stores institution and user info on success + * @throws AccountException if there is an issue with authentication data or if the OSF API request has failed + */ + protected OsfApiInstitutionAuthenticationResult notifyOsfApiOfInstnAuthnSuccess( + final OsfPostgresCredential credential + ) throws AccountException { + + final JSONObject normalizedPayload; + try { + normalizedPayload = extractInstnAuthnDataFromCredential(credential); + } catch (final ParserConfigurationException | TransformerException e) { + LOGGER.error("[CAS XSLT] Failed to normalize attributes in the credential: {}", e.getMessage()); + throw new InstitutionSsoFailedException("Attribute normalization failure"); + } + + final JSONObject provider = normalizedPayload.optJSONObject("provider"); + if (provider == null) { + LOGGER.error("[CAS XSLT] Missing identity provider."); + throw new InstitutionSsoFailedException("Missing identity provider"); + } + final String institutionId = provider.optString("id").trim(); + if (institutionId.isEmpty()) { + LOGGER.error("[CAS XSLT] Empty identity provider"); + throw new InstitutionSsoFailedException("Empty identity provider"); + } + final JSONObject user = provider.optJSONObject("user"); + if (user == null) { + LOGGER.error("[CAS XSLT] Missing institutional user"); + throw new InstitutionSsoFailedException("Missing institutional user"); + } + final String username = user.optString("username").trim(); + final String fullname = user.optString("fullname").trim(); + final String givenName = user.optString("givenName").trim(); + final String familyName = user.optString("familyName").trim(); + final String isMemberOf = user.optString("isMemberOf").trim(); + if (username.isEmpty()) { + LOGGER.error("[CAS XSLT] Missing email (username) for user at institution '{}'", institutionId); + throw new InstitutionSsoFailedException("Missing email (username)"); + } + if (fullname.isEmpty() && (givenName.isEmpty() || familyName.isEmpty())) { + LOGGER.error("[CAS XSLT] Missing names: username={}, institution={}", username, institutionId); + throw new InstitutionSsoFailedException("Missing user's names"); + } + if (!isMemberOf.isEmpty()) { + LOGGER.info( + "[CAS XSLT] Secondary institution detected. SSO is '{}' and member is '{}'", + institutionId, + isMemberOf + ); + } + final String payload = normalizedPayload.toString(); + LOGGER.info( + "[CAS XSLT] All attributes checked: username={}, institution={}, member={}", + username, + institutionId, + isMemberOf + ); + LOGGER.debug( + "[CAS XSLT] All attributes checked: username={}, institution={}, member={}, normalizedPayload={}", + username, + institutionId, + isMemberOf, + payload + ); + + final String jweString; + try { + final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() + .subject(username) + .claim("data", payload) + .expirationTime(new Date(new Date().getTime() + SIXTY_SECONDS)) + .build(); + final SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet); + final JWSSigner signer = new MACSigner(osfApiProperties.getInstnAuthnJwtSecret().getBytes()); + signedJWT.sign(signer); + final JWEObject jweObject = new JWEObject( + new JWEHeader.Builder(JWEAlgorithm.DIR, EncryptionMethod.A256GCM) + .contentType("JWT") + .build(), + new Payload(signedJWT)); + jweObject.encrypt(new DirectEncrypter(osfApiProperties.getInstnAuthnJweSecret().getBytes())); + jweString = jweObject.serialize(); + } catch (final JOSEException e) { + LOGGER.error( + "[OSF API] Notify Remote Principal Authenticated Failed: Payload Error - {}", + e.getMessage() + ); + throw new InstitutionSsoFailedException("OSF CAS failed to build JWT / JWE payload for OSF API"); + } + + try { + final HttpResponse httpResponse = Request.Post(osfApiProperties.getInstnAuthnEndpoint()) + .addHeader(new BasicHeader("Content-Type", "text/plain")) + .bodyString(jweString, ContentType.APPLICATION_JSON) + .execute() + .returnResponse(); + final int statusCode = httpResponse.getStatusLine().getStatusCode(); + LOGGER.info( + "[OSF API] Notify Remote Principal Authenticated Response: username={} statusCode={}", + username, + statusCode + ); + if (statusCode != HttpStatus.SC_NO_CONTENT) { + final String responseString = new BasicResponseHandler().handleResponse(httpResponse); + LOGGER.error( + "[OSF API] Notify Remote Principal Authenticated Failed: statusCode={}, body={}", + statusCode, + responseString + ); + throw new InstitutionSsoFailedException("OSF API failed to process CAS request"); + } + return new OsfApiInstitutionAuthenticationResult(username, institutionId); + } catch (final IOException e) { + LOGGER.error( + "[OSF API] Notify Remote Principal Authenticated Failed: Communication Error - {}", + e.getMessage() + ); + throw new InstitutionSsoFailedException("Communication Error between OSF CAS and OSF API"); + } + } } diff --git a/src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java b/src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java new file mode 100644 index 00000000..87a18256 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java @@ -0,0 +1,29 @@ +package io.cos.cas.osf.web.support; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +/** + * This is {@link OsfApiInstitutionAuthenticationResult}. + * + * @author Longze Chen + * @since 20.1.0 + */ +@AllArgsConstructor +@Getter +@NoArgsConstructor +@ToString +@Setter +public class OsfApiInstitutionAuthenticationResult implements Serializable { + + private static final long serialVersionUID = 3971349776123204760L; + + private String username; + + private String institutionId; +} From c4797b27f434368cef8ac22536af0eba85252df5 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 19 Nov 2020 17:12:47 -0500 Subject: [PATCH 12/71] Update web flow and view template to support instn sso failure --- ...InstitutionSsoNotImplementedException.java | 29 ------------------- .../OsfPostgresAuthenticationHandler.java | 4 +-- .../OsfCasCoreWebflowConfiguration.java | 4 +-- .../OsfCasLoginWebflowConfigurer.java | 12 ++++---- .../flow/support/OsfCasWebflowConstants.java | 2 +- src/main/resources/messages.properties | 9 ++++-- ....html => casInstitutionSsoFailedView.html} | 6 ++-- 7 files changed, 20 insertions(+), 46 deletions(-) delete mode 100644 src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoNotImplementedException.java rename src/main/resources/templates/{casInstitutionSsoNotImplementedView.html => casInstitutionSsoFailedView.html} (84%) diff --git a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoNotImplementedException.java b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoNotImplementedException.java deleted file mode 100644 index 85b60907..00000000 --- a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoNotImplementedException.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.cos.cas.osf.authentication.exception; - -import lombok.NoArgsConstructor; - -import javax.security.auth.login.AccountException; - -/** - * Describes an authentication error condition where institution SSO is not implemented. - * - * @author Longze Chen - * @since 20.0.0 - */ -@NoArgsConstructor -public class InstitutionSsoNotImplementedException extends AccountException { - - /** - * Serialization metadata. - */ - private static final long serialVersionUID = 5379752379314379863L; - - /** - * Instantiates a new {@link InstitutionSsoNotImplementedException}. - * - * @param msg the msg - */ - public InstitutionSsoNotImplementedException(final String msg) { - super(msg); - } -} diff --git a/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java b/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java index e77d6042..15d457b3 100644 --- a/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java +++ b/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java @@ -3,7 +3,7 @@ import io.cos.cas.osf.authentication.credential.OsfPostgresCredential; import io.cos.cas.osf.authentication.exception.AccountNotConfirmedIdpException; import io.cos.cas.osf.authentication.exception.AccountNotConfirmedOsfException; -import io.cos.cas.osf.authentication.exception.InstitutionSsoNotImplementedException; +import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; import io.cos.cas.osf.authentication.exception.InvalidOneTimePasswordException; import io.cos.cas.osf.authentication.exception.InvalidPasswordException; import io.cos.cas.osf.authentication.exception.InvalidUserStatusException; @@ -128,7 +128,7 @@ protected final AuthenticationHandlerExecutionResult authenticateOsfPostgresInte ); if (isRemotePrincipal) { - throw new InstitutionSsoNotImplementedException( + throw new InstitutionSsoFailedException( "Institution SSO not implemented for user [" + username + "] @ [" + institutionId +"]" ); } diff --git a/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java b/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java index 076b5a8a..bc545927 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java +++ b/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java @@ -2,7 +2,7 @@ import io.cos.cas.osf.authentication.exception.AccountNotConfirmedIdpException; import io.cos.cas.osf.authentication.exception.AccountNotConfirmedOsfException; -import io.cos.cas.osf.authentication.exception.InstitutionSsoNotImplementedException; +import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; import io.cos.cas.osf.authentication.exception.InvalidOneTimePasswordException; import io.cos.cas.osf.authentication.exception.InvalidPasswordException; import io.cos.cas.osf.authentication.exception.InvalidUserStatusException; @@ -42,7 +42,7 @@ public Set> handledAuthenticationExceptions() { errors.add(AccountNotConfirmedIdpException.class); errors.add(AccountNotConfirmedOsfException.class); errors.add(InvalidOneTimePasswordException.class); - errors.add(InstitutionSsoNotImplementedException.class); + errors.add(InstitutionSsoFailedException.class); errors.add(InvalidPasswordException.class); errors.add(InvalidUserStatusException.class); errors.add(InvalidVerificationKeyException.class); diff --git a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java index c533b128..93525c7b 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java +++ b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java @@ -3,7 +3,7 @@ import io.cos.cas.osf.authentication.credential.OsfPostgresCredential; import io.cos.cas.osf.authentication.exception.AccountNotConfirmedIdpException; import io.cos.cas.osf.authentication.exception.AccountNotConfirmedOsfException; -import io.cos.cas.osf.authentication.exception.InstitutionSsoNotImplementedException; +import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; import io.cos.cas.osf.authentication.exception.InvalidOneTimePasswordException; import io.cos.cas.osf.authentication.exception.InvalidUserStatusException; import io.cos.cas.osf.authentication.exception.InvalidVerificationKeyException; @@ -239,8 +239,8 @@ protected void createHandleAuthenticationFailureAction(final Flow flow) { ); createTransitionForState( handler, - InstitutionSsoNotImplementedException.class.getSimpleName(), - OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_NOT_IMPLEMENTED + InstitutionSsoFailedException.class.getSimpleName(), + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_FAILED ); // The default transition @@ -337,7 +337,7 @@ private void createOsfInstitutionLoginCheckAction(final Flow flow) { createTransitionForState( action, CasWebflowConstants.TRANSITION_ID_ERROR, - OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_NOT_IMPLEMENTED + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_FAILED ); createTransitionForState( action, @@ -374,8 +374,8 @@ private void createOsfCasAuthenticationExceptionViewStates(final Flow flow) { ); createViewState( flow, - OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_NOT_IMPLEMENTED, - OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_NOT_IMPLEMENTED + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_FAILED, + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_FAILED ); } diff --git a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java index e1e25498..c98c7bdf 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java +++ b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java @@ -42,5 +42,5 @@ public interface OsfCasWebflowConstants { String VIEW_ID_INSTITUTION_SSO_INIT = "casInstitutionLoginView"; - String VIEW_ID_INSTITUTION_SSO_NOT_IMPLEMENTED = "casInstitutionSsoNotImplementedView"; + String VIEW_ID_INSTITUTION_SSO_FAILED = "casInstitutionSsoFailedView"; } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index d6fbeb89..d456487c 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -643,9 +643,12 @@ screen.onetimepasswordrequired.heading=OSF Two-factor Authentication screen.onetimepasswordrequired.message=Two-factor authentication has been enabled for this OSF account. Please enter \ the one-time password generated by the authentication app. If you believe this should not happen, please contact OSF Support. -screen.institutionssonotimplemented.heading=Institution login error -screen.institutionssonotimplemented.message=The implementation of institution login page is work-in-progress, please \ - check back later ... +screen.institutionssofailed.pagetitle=Institution SSO Error +screen.institutionssofailed.heading=Institution login failed +screen.institutionssofailed.message=Your request cannot be completed at this time. Please \ + return to OSF and try again later.

If the issue persists, \ + check with your institution to verify your account is entitled to authenticate to OSF.

If you believe this \ + is in error, please contact Support for help. ######################################################################################################################## # # Enf of OSF CAS customized messages.properties diff --git a/src/main/resources/templates/casInstitutionSsoNotImplementedView.html b/src/main/resources/templates/casInstitutionSsoFailedView.html similarity index 84% rename from src/main/resources/templates/casInstitutionSsoNotImplementedView.html rename to src/main/resources/templates/casInstitutionSsoFailedView.html index 7b1206a0..0b85c17d 100644 --- a/src/main/resources/templates/casInstitutionSsoNotImplementedView.html +++ b/src/main/resources/templates/casInstitutionSsoFailedView.html @@ -5,7 +5,7 @@ - + @@ -21,8 +21,8 @@


-

-

+

+

From cdd24ac01aec9f62aea007aea122e625adc1ae5a Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 19 Nov 2020 17:15:14 -0500 Subject: [PATCH 13/71] Fix OSF API instn authn endpoint for local development --- etc/cas/config/local/cas-local.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/cas/config/local/cas-local.properties b/etc/cas/config/local/cas-local.properties index 371c0218..51a2927b 100644 --- a/etc/cas/config/local/cas-local.properties +++ b/etc/cas/config/local/cas-local.properties @@ -93,7 +93,7 @@ cas.authn.osf-url.meetings-home=http://localhost:5000/meetings/ ######################################################################################################################## # Authentication Endpoint # -cas.authn.osf-api.instn-authn-endpoint=http://localhost:8000/v2/institutions/auth/ +cas.authn.osf-api.instn-authn-endpoint=http://192.168.168.167:8000/v2/institutions/auth/ # # JWT / JWE secrets for signing and encrypting authentication request payload # From 688b0032d2800c23ef96918353e7b35133e601c4 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 19 Nov 2020 17:16:49 -0500 Subject: [PATCH 14/71] Use "none" for instn ID and delegation protocol if not instn SSO --- .../osf/authentication/credential/OsfPostgresCredential.java | 4 ++-- .../cas/osf/authentication/support/DelegationProtocol.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java b/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java index 52f27edc..91945814 100644 --- a/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java +++ b/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java @@ -38,9 +38,9 @@ public class OsfPostgresCredential extends RememberMeUsernamePasswordCredential public static String AUTHENTICATION_ATTRIBUTE_REMEMBER_ME = "rememberMe"; - private static String DEFAULT_INSTITUTION_ID = "none_osf"; + private static String DEFAULT_INSTITUTION_ID = "none"; - private static DelegationProtocol DEFAULT_DELEGATION_PROTOCOL = DelegationProtocol.NONE_OSF; + private static DelegationProtocol DEFAULT_DELEGATION_PROTOCOL = DelegationProtocol.NONE; /** * The one-time and ephemeral OSF verification key. diff --git a/src/main/java/io/cos/cas/osf/authentication/support/DelegationProtocol.java b/src/main/java/io/cos/cas/osf/authentication/support/DelegationProtocol.java index fb352f23..750d58ee 100644 --- a/src/main/java/io/cos/cas/osf/authentication/support/DelegationProtocol.java +++ b/src/main/java/io/cos/cas/osf/authentication/support/DelegationProtocol.java @@ -8,7 +8,7 @@ */ public enum DelegationProtocol { - NONE_OSF("none-osf"), + NONE("none"), OAUTH_PAC4J("oauth-pac4j"), From b5fa23243729ad09a09d147dbac7cdf62f5eb300 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 19 Nov 2020 17:19:59 -0500 Subject: [PATCH 15/71] Enable fakeCAS as an institution IdP for local development --- etc/cas/config/local/instn-authn-local.xsl | 12 ++++++++++++ etc/cas/services/local/osf-203948234207230.json | 3 ++- .../services/local/preprints-203948234207240.json | 3 ++- .../services/local/registries-203948234207340.json | 3 ++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/etc/cas/config/local/instn-authn-local.xsl b/etc/cas/config/local/instn-authn-local.xsl index 7b281fcc..19f963f7 100644 --- a/etc/cas/config/local/instn-authn-local.xsl +++ b/etc/cas/config/local/instn-authn-local.xsl @@ -49,6 +49,18 @@ + + + fakecas + + + + + + + + + diff --git a/etc/cas/services/local/osf-203948234207230.json b/etc/cas/services/local/osf-203948234207230.json index 2680c8a9..2851cb15 100644 --- a/etc/cas/services/local/osf-203948234207230.json +++ b/etc/cas/services/local/osf-203948234207230.json @@ -24,7 +24,8 @@ "allowedProviders": [ "java.util.ArrayList", [ - "orcid" + "orcid", + "fakecas" ] ], "permitUndefined": false diff --git a/etc/cas/services/local/preprints-203948234207240.json b/etc/cas/services/local/preprints-203948234207240.json index 506c33d6..6f919e82 100644 --- a/etc/cas/services/local/preprints-203948234207240.json +++ b/etc/cas/services/local/preprints-203948234207240.json @@ -24,7 +24,8 @@ "allowedProviders": [ "java.util.ArrayList", [ - "orcid" + "orcid", + "fakecas" ] ], "permitUndefined": false diff --git a/etc/cas/services/local/registries-203948234207340.json b/etc/cas/services/local/registries-203948234207340.json index 07ce061f..dcd65f00 100644 --- a/etc/cas/services/local/registries-203948234207340.json +++ b/etc/cas/services/local/registries-203948234207340.json @@ -24,7 +24,8 @@ "allowedProviders": [ "java.util.ArrayList", [ - "orcid" + "orcid", + "fakecas" ] ], "permitUndefined": false From de57f0991306fbd6b9718ae9f74a18deb6e9d8f6 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 19 Nov 2020 17:21:53 -0500 Subject: [PATCH 16/71] Fix an issue where pac4j-cas instn login URL were not put in context This is a similar solution to the ORCiD login URL except there are multiple cas clients in this case. Thus, the institution pre-login check action has been expanded to init w/ pre-defined cas clients, retrieve respective URLs from the flow and re-put them in as a map (which was a set) for easier template access. In addition, fixed the script on the institution sso view template by using +
+ + + diff --git a/src/main/resources/templates/layoutFlowless.html b/src/main/resources/templates/layoutFlowless.html new file mode 100644 index 00000000..d3237822 --- /dev/null +++ b/src/main/resources/templates/layoutFlowless.html @@ -0,0 +1,34 @@ + + + + + + + + OSF + + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+
+ +
+ + + From c1cf96fe05e1b30895648fee0a853f79280efb1f Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Wed, 9 Dec 2020 16:12:44 -0500 Subject: [PATCH 29/71] Update login web flow to handle param "errorSouce" --- etc/cas/config/cas.properties | 1 + etc/cas/config/local/cas-local.properties | 1 + .../configuration/model/OsfUrlProperties.java | 14 +++++++++ .../OsfCasLoginWebflowConfigurer.java | 19 ++++++++++++ .../OsfAbstractLoginPreparationAction.java | 8 +++++ .../OsfCasPreInitialFlowSetupAction.java | 10 +++---- .../flow/support/OsfCasWebflowConstants.java | 30 +++++++++++-------- .../osf/web/support/OsfCasLoginContext.java | 27 ++++++++++++++--- src/main/resources/messages.properties | 1 + ...AutoRedirectToDefaultServiceLoginView.html | 9 ++++++ 10 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 src/main/resources/templates/casAutoRedirectToDefaultServiceLoginView.html diff --git a/etc/cas/config/cas.properties b/etc/cas/config/cas.properties index 35a8c2e6..9d9b1e71 100644 --- a/etc/cas/config/cas.properties +++ b/etc/cas/config/cas.properties @@ -71,6 +71,7 @@ cas.logout.remove-descendant-tickets=false # cas.authn.osf-url.home=https://{{ .Values.osfDomain }}/ cas.authn.osf-url.dashboard=https://{{ .Values.osfDomain }}/dashboard/ +cas.authn.osf-url.login-with-next=https://{{ .Values.osfDomain }}/login?next= cas.authn.osf-url.logout=https://{{ .Values.osfDomain }}/logout/ cas.authn.osf-url.resend-confirmation=https://{{ .Values.osfDomain }}/resend/ cas.authn.osf-url.forgot-password=https://{{ .Values.osfDomain }}/forgotpassword/ diff --git a/etc/cas/config/local/cas-local.properties b/etc/cas/config/local/cas-local.properties index 7d5c4ec3..a9df2402 100644 --- a/etc/cas/config/local/cas-local.properties +++ b/etc/cas/config/local/cas-local.properties @@ -72,6 +72,7 @@ cas.logout.remove-descendant-tickets=false # cas.authn.osf-url.home=http://localhost:5000/ cas.authn.osf-url.dashboard=http://localhost:5000/dashboard/ +cas.authn.osf-url.login-with-next=http://localhost:5000/login?next= cas.authn.osf-url.logout=http://localhost:5000/logout/ cas.authn.osf-url.resend-confirmation=http://localhost:5000/resend/ cas.authn.osf-url.forgot-password=http://localhost:5000/forgotpassword/ diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java index ba65f3fd..8da32c89 100644 --- a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java @@ -5,6 +5,8 @@ import lombok.experimental.Accessors; import java.io.Serializable; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; /** * This is {@link OsfUrlProperties}. @@ -39,6 +41,11 @@ public class OsfUrlProperties implements Serializable { */ private String register; + /** + * OSF login endpoint with "?next=". + */ + private String loginWithNext; + /** * OSF logout endpoint URL. */ @@ -88,4 +95,11 @@ public class OsfUrlProperties implements Serializable { * OSF / COS donation page URL. */ private String donate; + + /** + * Build the default service URL using OSF login endpoint with OSF home page as destination. + */ + public String constructDefaultServiceUrl() { + return loginWithNext + URLEncoder.encode(home, StandardCharsets.UTF_8); + } } diff --git a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java index a30d33c6..bd4492eb 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java +++ b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java @@ -81,6 +81,7 @@ protected void createDefaultViewStates(final Flow flow) { createTwoFactorLoginFormView(flow); createInstitutionLoginView(flow); createOrcidLoginAutoRedirectView(flow); + createDefaultServiceLoginAutoRedirectView(flow); createOsfCasAuthenticationExceptionViewStates(flow); } @@ -324,6 +325,11 @@ private void createOsfDefaultLoginCheckAction(final Flow flow) { OsfCasWebflowConstants.TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT, OsfCasWebflowConstants.VIEW_ID_ORCID_LOGIN_AUTO_REDIRECT ); + createTransitionForState( + action, + OsfCasWebflowConstants.TRANSITION_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT, + OsfCasWebflowConstants.VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT + ); createTransitionForState( action, CasWebflowConstants.TRANSITION_ID_ERROR, @@ -434,6 +440,19 @@ protected void createOrcidLoginAutoRedirectView(final Flow flow) { ); } + /** + * Create the ORCiD login auto-redirect view to support the OSF feature "sign-up via ORCiD". + * + * @param flow the flow + */ + protected void createDefaultServiceLoginAutoRedirectView(final Flow flow) { + createViewState( + flow, + OsfCasWebflowConstants.VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT, + OsfCasWebflowConstants.VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT + ); + } + /** * Create the institution SSO init view state to support the OSF feature "sign-in via institutions". * diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java index 87d069de..dc3db860 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java @@ -8,6 +8,10 @@ import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + /** * This is {@link OsfAbstractLoginPreparationAction}. * @@ -39,6 +43,10 @@ public abstract class OsfAbstractLoginPreparationAction extends AbstractAuthenti protected static final String PARAMETER_ORCID_REDIRECT_VALUE = "true"; + protected static final String PARAMETER_ERROR_SOURCE = "errorSource"; + + protected static final List EXPECTED_ERROR_CODES = new LinkedList<>(Arrays.asList("401", "403", "404", "405", "423")); + public OsfAbstractLoginPreparationAction( final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver, final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java index b491b511..ec84b4c8 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java @@ -2,6 +2,7 @@ import io.cos.cas.osf.configuration.model.OsfUrlProperties; +import io.cos.cas.osf.web.flow.support.OsfCasWebflowConstants; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -22,17 +23,16 @@ @Slf4j public class OsfCasPreInitialFlowSetupAction extends AbstractAction { - private static final String OSF_URL_FLOW_PARAMETER = "osfUrl"; - @NotNull private final OsfUrlProperties osfUrlProperties; @Override protected Event doExecute(final RequestContext context) { - OsfUrlProperties osfUrl = Optional.of(context).map(requestContext - -> (OsfUrlProperties) requestContext.getFlowScope().get(OSF_URL_FLOW_PARAMETER)).orElse(null); + final OsfUrlProperties osfUrl = Optional.of(context).map( + requestContext -> (OsfUrlProperties) requestContext.getFlowScope().get(OsfCasWebflowConstants.FLOW_PARAMETER_OSF_URL) + ).orElse(null); if (osfUrl == null) { - context.getFlowScope().put(OSF_URL_FLOW_PARAMETER, osfUrlProperties); + context.getFlowScope().put(OsfCasWebflowConstants.FLOW_PARAMETER_OSF_URL, osfUrlProperties); } return success(); } diff --git a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java index ba66ca3b..aee280ae 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java +++ b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java @@ -2,7 +2,7 @@ /** * This is {@link OsfCasWebflowConstants}, which expands the default {@link org.apereo.cas.web.flow.CasWebflowConstants} - * interface by adding OSF CAS customized action, state and view IDs. + * interface by adding OSF CAS customized action, state, transition and view IDs as well as names web flow parameters. * * @author Longze Chen * @since 20.0.0 @@ -10,27 +10,37 @@ public interface OsfCasWebflowConstants { - String ACTION_ID_OSF_PRE_INITIAL_FLOW_SETUP = "osfCasPreInitialFlowSetupAction"; + String FLOW_PARAMETER_OSF_URL = "osfUrl"; - String ACTION_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheckAction"; + String ACTION_ID_OSF_PRE_INITIAL_FLOW_SETUP = "osfCasPreInitialFlowSetupAction"; - String STATE_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheck"; + String ACTION_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheckAction"; - String TRANSITION_ID_USERNAME_PASSWORD_LOGIN = "continueToUsernamePasswordLogin"; + String ACTION_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheckAction"; String ACTION_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheckAction"; - String STATE_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheck"; + String TRANSITION_ID_USERNAME_PASSWORD_LOGIN = "continueToUsernamePasswordLogin"; String TRANSITION_ID_INSTITUTION_LOGIN = "switchToInstitutionLogin"; String TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT = "autoRedirectToOrcidLogin"; + String TRANSITION_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT = "autoRedirectToDefaultServiceLogin"; + + String STATE_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheck"; + + String STATE_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheck"; + + String STATE_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheck"; + + String VIEW_ID_INSTITUTION_SSO_INIT = "casInstitutionLoginView"; + String VIEW_ID_ORCID_LOGIN_AUTO_REDIRECT = "casAutoRedirectToOrcidLoginView"; - String ACTION_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheckAction"; + String VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT = "casAutoRedirectToDefaultServiceLoginView"; - String STATE_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheck"; + String VIEW_ID_ONE_TIME_PASSWORD_REQUIRED = "casTwoFactorLoginView"; String VIEW_ID_ACCOUNT_NOT_CONFIRMED_OSF = "casAccountNotConfirmedOsfView"; @@ -40,9 +50,5 @@ public interface OsfCasWebflowConstants { String VIEW_ID_INVALID_VERIFICATION_KEY = "casInvalidVerificationKeyView"; - String VIEW_ID_ONE_TIME_PASSWORD_REQUIRED = "casTwoFactorLoginView"; - - String VIEW_ID_INSTITUTION_SSO_INIT = "casInstitutionLoginView"; - String VIEW_ID_INSTITUTION_SSO_FAILED = "casInstitutionSsoFailedView"; } diff --git a/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java b/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java index edf29b07..da17380e 100644 --- a/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java +++ b/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java @@ -26,7 +26,13 @@ public class OsfCasLoginContext implements Serializable { private static final long serialVersionUID = 7523144720609509742L; - private String serviceUrl; + /** + * The encoded service URL provided by the "service=" query param in the request URL. + * + * This attribute is deprecated and should be removed since 1) ThymeLeaf handles URL building elegantly in the template and 2) both of + * the flow parameters "service.originalUrl" and "originalUrl" stores the current service information. + */ + private String encodedServiceUrl; private String handleErrorName; @@ -38,18 +44,31 @@ public class OsfCasLoginContext implements Serializable { private String orcidLoginUrl; + private boolean defaultService; + + /** + * 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; + public OsfCasLoginContext ( - final String serviceUrl, + final String encodedServiceUrl, final boolean institutionLogin, final String institutionId, final boolean orcidRedirect, - final String orcidLoginUrl + final String orcidLoginUrl, + final boolean defaultService, + final String defaultServiceUrl ) { - this.serviceUrl = serviceUrl; + this.encodedServiceUrl = encodedServiceUrl; this.handleErrorName = null; this.institutionLogin = institutionLogin; this.institutionId = institutionId; this.orcidRedirect = orcidRedirect; this.orcidLoginUrl = orcidLoginUrl; + this.defaultService = defaultService; + this.defaultServiceUrl = defaultServiceUrl; } } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index d456487c..6529049a 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -545,6 +545,7 @@ screen.pm.button.backtoosf=Back to OSF screen.delegation.button.orcid=Sign in with ORCiD screen.delegation.button.institution=Sign in through institution screen.delegation.heading.orcidredirect=Redirecting to ORCiD +screen.flowless.heading.defaultserviceredirect=Redirecting to OSF login # # Two factor and login form submission # diff --git a/src/main/resources/templates/casAutoRedirectToDefaultServiceLoginView.html b/src/main/resources/templates/casAutoRedirectToDefaultServiceLoginView.html new file mode 100644 index 00000000..6539869d --- /dev/null +++ b/src/main/resources/templates/casAutoRedirectToDefaultServiceLoginView.html @@ -0,0 +1,9 @@ + + + + + + + + From 74d4a5e9c33cd0925d322542b604dd19ccc931b0 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Tue, 22 Dec 2020 11:16:01 -0500 Subject: [PATCH 30/71] Add a missing commit Update pre-login action to support server-specific settings --- .../OsfDefaultLoginPreparationAction.java | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java index 646db542..66a6ee91 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java @@ -1,5 +1,6 @@ package io.cos.cas.osf.web.flow.login; +import io.cos.cas.osf.configuration.model.OsfUrlProperties; import io.cos.cas.osf.web.flow.support.OsfCasWebflowConstants; import io.cos.cas.osf.web.support.OsfCasLoginContext; @@ -49,45 +50,63 @@ public OsfDefaultLoginPreparationAction( @Override protected Event doExecute(RequestContext context) { - OsfCasLoginContext loginContext; - final String serviceUrl = getEncodedServiceUrlFromRequestContext(context); final boolean institutionLogin = isInstitutionLogin(context); final String institutionId = getInstitutionIdFromRequestContext(context); final boolean orcidRedirect = isOrcidLoginAutoRedirect(context); final String orcidLoginUrl = getOrcidLoginUrlFromFlowScope(context); + final String encodedServiceUrl = getEncodedServiceUrlFromRequestContext(context); + final boolean defaultService = isFromFlowlessErrorPage(context); + final OsfUrlProperties osfUrl = Optional.of(context).map( + requestContext -> (OsfUrlProperties) requestContext.getFlowScope().get(OsfCasWebflowConstants.FLOW_PARAMETER_OSF_URL) + ).orElse(null); + if (osfUrl == null) { + LOGGER.error("The login web flow has not been initialized correctly."); + return error(); + } + final String defaultServiceUrl = osfUrl.constructDefaultServiceUrl(); + + OsfCasLoginContext loginContext; loginContext = Optional.of(context).map(requestContext -> (OsfCasLoginContext) requestContext.getFlowScope().get(PARAMETER_LOGIN_CONTEXT)).orElse(null); if (loginContext == null) { loginContext = new OsfCasLoginContext( - serviceUrl, + encodedServiceUrl, institutionLogin, institutionId, orcidRedirect, - orcidLoginUrl + orcidLoginUrl, + defaultService, + defaultServiceUrl ); } else { - loginContext.setServiceUrl(serviceUrl); + loginContext.setDefaultServiceUrl(encodedServiceUrl); loginContext.setInstitutionLogin(institutionLogin); loginContext.setInstitutionId(institutionId); loginContext.setOrcidLoginUrl(orcidLoginUrl); loginContext.setOrcidRedirect(false); + loginContext.setDefaultService(defaultService); + loginContext.setDefaultServiceUrl(defaultServiceUrl); } context.getFlowScope().put(PARAMETER_LOGIN_CONTEXT, loginContext); - if (loginContext.isInstitutionLogin()) { + if (loginContext.isDefaultService()) { + if (StringUtils.isNotBlank(defaultServiceUrl)) { + return autoRedirectToDefaultServiceLogin(); + } + LOGGER.error("Default service login auto-redirect failed due to URL configurations not found in context."); + return error(); + } else if (loginContext.isInstitutionLogin()) { return switchToInstitutionLogin(); - } - - if (loginContext.isOrcidRedirect()) { + } else if (loginContext.isOrcidRedirect()) { if (StringUtils.isNotBlank(orcidLoginUrl)) { return autoRedirectToOrcidLogin(); } LOGGER.error("ORCiD login auto-redirect failed due to delegation configurations not found in context."); return error(); + } else { + return continueToUsernamePasswordLogin(); } - - return continueToUsernamePasswordLogin(); } private boolean isInstitutionLogin(final RequestContext context) { @@ -127,6 +146,11 @@ private String getEncodedServiceUrlFromRequestContext(final RequestContext conte return URLEncoder.encode(serviceUrl, StandardCharsets.UTF_8); } + private boolean isFromFlowlessErrorPage(final RequestContext context) { + final String errorCode = context.getRequestParameters().get(PARAMETER_ERROR_SOURCE); + return !StringUtils.isBlank(errorCode) && EXPECTED_ERROR_CODES.contains(errorCode); + } + private Event continueToUsernamePasswordLogin() { return new Event(this, OsfCasWebflowConstants.TRANSITION_ID_USERNAME_PASSWORD_LOGIN); } @@ -138,4 +162,8 @@ private Event switchToInstitutionLogin() { private Event autoRedirectToOrcidLogin() { return new Event(this, OsfCasWebflowConstants.TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT); } + + private Event autoRedirectToDefaultServiceLogin() { + return new Event(this, OsfCasWebflowConstants.TRANSITION_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT); + } } From fd5c90328a609f01161106f2a8eeb8cc67e8191b Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 7 Jan 2021 18:06:55 -0500 Subject: [PATCH 31/71] Implement JPA-based terms of service consent check * JPA model update for OSF user * OSF credential and authentication handler update * Login web flow update with a new exception and form submission * New TOS consent page with updated language and styles --- .../credential/OsfPostgresCredential.java | 5 + ...ermsOfServiceConsentRequiredException.java | 29 +++++ .../OsfPostgresAuthenticationHandler.java | 8 +- .../java/io/cos/cas/osf/model/OsfUser.java | 8 ++ .../OsfCasCoreWebflowConfiguration.java | 2 + .../OsfCasLoginWebflowConfigurer.java | 41 ++++++ .../flow/support/OsfCasWebflowConstants.java | 2 + src/main/resources/messages.properties | 18 +++ src/main/resources/static/css/cas.css | 6 + .../casTermsOfServiceConsentView.html | 27 ++++ .../templates/fragments/tosloginform.html | 119 ++++++++++++++++++ 11 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java create mode 100644 src/main/resources/templates/casTermsOfServiceConsentView.html create mode 100644 src/main/resources/templates/fragments/tosloginform.html diff --git a/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java b/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java index 2efdc5de..c6972e7b 100644 --- a/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java +++ b/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java @@ -52,6 +52,11 @@ public class OsfPostgresCredential extends RememberMeUsernamePasswordCredential */ private String oneTimePassword; + /** + * The boolean flag that indicates whether the user has checked the terms of service consent agreement + */ + private boolean termsOfServiceChecked; + /** * The boolean flag that indicates successful delegated authentication if true. */ diff --git a/src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java b/src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java new file mode 100644 index 00000000..7cd576b2 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java @@ -0,0 +1,29 @@ +package io.cos.cas.osf.authentication.exception; + +import lombok.NoArgsConstructor; + +import javax.security.auth.login.AccountException; + +/** + * Describes an authentication error condition where a user account needs to agree to OSF's terms of service. + * + * @author Longze Chen + * @since 21.1.0 + */ +@NoArgsConstructor +public class TermsOfServiceConsentRequiredException extends AccountException { + + /** + * Serialization metadata. + */ + private static final long serialVersionUID = -7702088330316457626L; + + /** + * Instantiates a new {@link TermsOfServiceConsentRequiredException}. + * + * @param msg the msg + */ + public TermsOfServiceConsentRequiredException(final String msg) { + super(msg); + } +} diff --git a/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java b/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java index 0cb53930..52db8ae0 100644 --- a/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java +++ b/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java @@ -3,12 +3,12 @@ import io.cos.cas.osf.authentication.credential.OsfPostgresCredential; import io.cos.cas.osf.authentication.exception.AccountNotConfirmedIdpException; import io.cos.cas.osf.authentication.exception.AccountNotConfirmedOsfException; -import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; import io.cos.cas.osf.authentication.exception.InvalidOneTimePasswordException; import io.cos.cas.osf.authentication.exception.InvalidPasswordException; import io.cos.cas.osf.authentication.exception.InvalidUserStatusException; import io.cos.cas.osf.authentication.exception.OneTimePasswordRequiredException; import io.cos.cas.osf.authentication.exception.InvalidVerificationKeyException; +import io.cos.cas.osf.authentication.exception.TermsOfServiceConsentRequiredException; import io.cos.cas.osf.authentication.support.DelegationProtocol; import io.cos.cas.osf.authentication.support.OsfUserStatus; import io.cos.cas.osf.authentication.support.OsfUserUtils; @@ -111,6 +111,7 @@ protected final AuthenticationHandlerExecutionResult authenticateOsfPostgresInte final String oneTimePassword = credential.getOneTimePassword(); final String institutionId = credential.getInstitutionId(); final boolean isRememberMe = credential.isRememberMe(); + final boolean isTermsOfServiceChecked = credential.isTermsOfServiceChecked(); final boolean isRemotePrincipal = credential.isRemotePrincipal(); final DelegationProtocol delegationProtocol = credential.getDelegationProtocol(); @@ -169,6 +170,11 @@ protected final AuthenticationHandlerExecutionResult authenticateOsfPostgresInte } } + if (!osfUser.isTermsOfServiceAccepted() && !isTermsOfServiceChecked) { + LOGGER.info("Terms of service consent is required for [" + username + "]"); + throw new TermsOfServiceConsentRequiredException("Terms of service consent is required for [" + username + "]"); + } + if (OsfUserStatus.USER_NOT_CONFIRMED_OSF.equals(userStatus)) { throw new AccountNotConfirmedOsfException( "User [" + username + "] is registered via OSF but not confirmed" diff --git a/src/main/java/io/cos/cas/osf/model/OsfUser.java b/src/main/java/io/cos/cas/osf/model/OsfUser.java index 6249bf2c..4a7e5740 100644 --- a/src/main/java/io/cos/cas/osf/model/OsfUser.java +++ b/src/main/java/io/cos/cas/osf/model/OsfUser.java @@ -62,6 +62,10 @@ public final class OsfUser extends AbstractOsfModel { @Column(name = "date_confirmed") private Date dateConfirmed; + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "accepted_terms_of_service") + private Date dateTermsOfServiceAccepted; + @Temporal(TemporalType.TIMESTAMP) @Column(name = "date_disabled") private Date dateDisabled; @@ -86,6 +90,10 @@ public boolean isConfirmed() { return dateConfirmed != null; } + public boolean isTermsOfServiceAccepted() { + return dateTermsOfServiceAccepted != null; + } + public boolean isDisabled() { return dateDisabled != null; } diff --git a/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java b/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java index bc545927..a1bc0bd1 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java +++ b/src/main/java/io/cos/cas/osf/web/flow/config/OsfCasCoreWebflowConfiguration.java @@ -8,6 +8,7 @@ import io.cos.cas.osf.authentication.exception.InvalidUserStatusException; import io.cos.cas.osf.authentication.exception.InvalidVerificationKeyException; import io.cos.cas.osf.authentication.exception.OneTimePasswordRequiredException; +import io.cos.cas.osf.authentication.exception.TermsOfServiceConsentRequiredException; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.web.flow.config.CasCoreWebflowConfiguration; @@ -47,6 +48,7 @@ public Set> handledAuthenticationExceptions() { errors.add(InvalidUserStatusException.class); errors.add(InvalidVerificationKeyException.class); errors.add(OneTimePasswordRequiredException.class); + errors.add(TermsOfServiceConsentRequiredException.class); // Add built-in exceptions after OSF-specific exceptions since order matters errors.addAll(super.handledAuthenticationExceptions()); diff --git a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java index bd4492eb..9028baeb 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java +++ b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java @@ -8,6 +8,7 @@ import io.cos.cas.osf.authentication.exception.InvalidUserStatusException; import io.cos.cas.osf.authentication.exception.InvalidVerificationKeyException; import io.cos.cas.osf.authentication.exception.OneTimePasswordRequiredException; +import io.cos.cas.osf.authentication.exception.TermsOfServiceConsentRequiredException; import io.cos.cas.osf.web.flow.support.OsfCasWebflowConstants; import org.apereo.cas.authentication.PrincipalException; @@ -79,6 +80,7 @@ protected void createDefaultViewStates(final Flow flow) { super.createDefaultViewStates(flow); // Create OSF customized view states createTwoFactorLoginFormView(flow); + createTermsOfServiceConsentLoginFormView(flow); createInstitutionLoginView(flow); createOrcidLoginAutoRedirectView(flow); createDefaultServiceLoginAutoRedirectView(flow); @@ -246,6 +248,11 @@ protected void createHandleAuthenticationFailureAction(final Flow flow) { InvalidOneTimePasswordException.class.getSimpleName(), OsfCasWebflowConstants.VIEW_ID_ONE_TIME_PASSWORD_REQUIRED ); + createTransitionForState( + handler, + TermsOfServiceConsentRequiredException.class.getSimpleName(), + OsfCasWebflowConstants.VIEW_ID_TERMS_OF_SERVICE_CONSENT_REQUIRED + ); createTransitionForState( handler, InstitutionSsoFailedException.class.getSimpleName(), @@ -427,6 +434,40 @@ private void createTwoFactorLoginFormView(final Flow flow) { attributes.put("history", History.INVALIDATE); } + /** + * Create the customized terms of service consent form submission view state for OSF CAS. + * + * @param flow the flow + */ + private void createTermsOfServiceConsentLoginFormView(final Flow flow) { + List propertiesToBind = CollectionUtils.wrapList("termsOfServiceChecked", "source"); + BinderConfiguration binder = createStateBinderConfiguration(propertiesToBind); + casProperties.getView().getCustomLoginFormFields() + .forEach((field, props) -> { + String fieldName = String.format("customFields[%s]", field); + binder.addBinding( + new BinderConfiguration.Binding(fieldName, props.getConverter(), props.isRequired()) + ); + }); + ViewState state = createViewState( + flow, + OsfCasWebflowConstants.VIEW_ID_TERMS_OF_SERVICE_CONSENT_REQUIRED, + OsfCasWebflowConstants.VIEW_ID_TERMS_OF_SERVICE_CONSENT_REQUIRED, + binder + ); + state.getRenderActionList().add(createEvaluateAction(CasWebflowConstants.ACTION_ID_RENDER_LOGIN_FORM)); + createStateModelBinding(state, CasWebflowConstants.VAR_ID_CREDENTIAL, OsfPostgresCredential.class); + Transition transition = createTransitionForState( + state, + CasWebflowConstants.TRANSITION_ID_SUBMIT, + CasWebflowConstants.STATE_ID_REAL_SUBMIT + ); + MutableAttributeMap attributes = transition.getAttributes(); + attributes.put("bind", Boolean.TRUE); + attributes.put("validate", Boolean.TRUE); + attributes.put("history", History.INVALIDATE); + } + /** * Create the ORCiD login auto-redirect view to support the OSF feature "sign-up via ORCiD". * diff --git a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java index aee280ae..fab9fc8c 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java +++ b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java @@ -42,6 +42,8 @@ public interface OsfCasWebflowConstants { String VIEW_ID_ONE_TIME_PASSWORD_REQUIRED = "casTwoFactorLoginView"; + String VIEW_ID_TERMS_OF_SERVICE_CONSENT_REQUIRED = "casTermsOfServiceConsentView"; + String VIEW_ID_ACCOUNT_NOT_CONFIRMED_OSF = "casAccountNotConfirmedOsfView"; String VIEW_ID_ACCOUNT_NOT_CONFIRMED_IDP = "casAccountNotConfirmedIdPView"; diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 6529049a..a6227342 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -558,6 +558,22 @@ screen.twofactor.button.verifywip=One moment please... screen.twofactor.button.cancel=Cancel screen.twofactor.instructions.bottom=Open the two-factor authentication app on your device to view your authentication code and verify your identity. # +# Terms of service consent check login form submission +# +screen.tosconsent.pagetitle=Terms of service +screen.tosconsent.instructions.top=Terms of use and privacy policy +screen.tosconsent.message.p1=You must read and agree to our \ + Terms of Use and \ + Privacy Policy \ + to finish login. +screen.tosconsent.message.p2=You are seeing this page, either because this is your first-time login to OSF via your \ + institution, or because we have recently updated the terms. +screen.tosconsent.message.p3=Please read them carefully and contact \ + OSF Support should you have any question. +screen.tosconsent.checkbox.title=I have read and agree to these terms. +screen.tosconsent.button.agree=Continue +screen.tosconsent.button.agreewip=One moment please... +# # Institution login page # screen.institutionlogin.pagetitle=Institution SSO @@ -594,6 +610,7 @@ screen.generic.button.hidedetails=Hide authentication details username.required=Email is required. password.required=Password is required. oneTimePassword.required=One-time password is required. +termsOfServiceChecked.required=Terms of service consent is required. authenticationFailure.AccountDisabledException=This account has been disabled. authenticationFailure.AccountNotFoundException=The email or password you entered is incorrect. authenticationFailure.AccountNotConfirmedOsfException=The account you tried to log in to has not been confirmed. @@ -605,6 +622,7 @@ authenticationFailure.InvalidPasswordException=The email or password you entered authenticationFailure.InvalidVerificationKeyException=The verification key you entered is incorrect. authenticationFailure.InvalidUserStatusException=The account you tried to log in to is not active. authenticationFailure.OneTimePasswordRequiredException= +authenticationFailure.TermsOfServiceConsentRequiredException= # # Authentication exception messages in stand-alone exception views # diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index c5cc0b9a..48a59d62 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -593,6 +593,7 @@ button.close { --cas-theme-osf-green: #357935; --cas-theme-osf-blue: #1b6d85; --cas-theme-osf-red: #b52b27; + --cas-theme-osf-disabled: #EFEFEF; --cas-theme-primary: var(--cas-theme-osf-navbar, #263947); --cas-theme-danger: var(--cas-theme-osf-red, #b52b27); --mdc-theme-primary: var(--cas-theme-primary, #263947); @@ -811,6 +812,11 @@ body { background-color: var(--cas-theme-osf-red, #b52b27); } +.form-button .button-osf-disabled, +.form-button-inline .button-osf-disabled { + background-color: var(--cas-theme-osf-disabled, #EFEFEF); +} + .login-error-inline { margin: 0.25rem 0; } diff --git a/src/main/resources/templates/casTermsOfServiceConsentView.html b/src/main/resources/templates/casTermsOfServiceConsentView.html new file mode 100644 index 00000000..9c3db492 --- /dev/null +++ b/src/main/resources/templates/casTermsOfServiceConsentView.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + +
+ +
+ +
+
+ + + diff --git a/src/main/resources/templates/fragments/tosloginform.html b/src/main/resources/templates/fragments/tosloginform.html new file mode 100644 index 00000000..f8ec1f4c --- /dev/null +++ b/src/main/resources/templates/fragments/tosloginform.html @@ -0,0 +1,119 @@ + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +

+ + +

+ +
+

+

+

+
+ +
+
+ +
+ + + +
+ +
+
+ + + +
+
+ +
+ +
+ +
+ + + +

+ + + + + +

+
+ +
+ +
+
+ + + + + +
+
+
+ + + From 9d739601bf3b4762f540ffaf004ac5a3f5dd6d64 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 7 Jan 2021 18:24:59 -0500 Subject: [PATCH 32/71] Release terms of service consent info to OSF via attribute release --- .../authentication/credential/OsfPostgresCredential.java | 2 ++ .../OsfPostgresAuthenticationMetaDataPopulator.java | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java b/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java index c6972e7b..9027ecd6 100644 --- a/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java +++ b/src/main/java/io/cos/cas/osf/authentication/credential/OsfPostgresCredential.java @@ -38,6 +38,8 @@ public class OsfPostgresCredential extends RememberMeUsernamePasswordCredential public static String AUTHENTICATION_ATTRIBUTE_REMEMBER_ME = "rememberMe"; + public static String AUTHENTICATION_ATTRIBUTE_TOS_CONSENT = "termsOfServiceChecked"; + private static String DEFAULT_INSTITUTION_ID = "none"; private static DelegationProtocol DEFAULT_DELEGATION_PROTOCOL = DelegationProtocol.NONE; diff --git a/src/main/java/io/cos/cas/osf/authentication/metadata/OsfPostgresAuthenticationMetaDataPopulator.java b/src/main/java/io/cos/cas/osf/authentication/metadata/OsfPostgresAuthenticationMetaDataPopulator.java index 67d491db..de3b22fd 100644 --- a/src/main/java/io/cos/cas/osf/authentication/metadata/OsfPostgresAuthenticationMetaDataPopulator.java +++ b/src/main/java/io/cos/cas/osf/authentication/metadata/OsfPostgresAuthenticationMetaDataPopulator.java @@ -27,17 +27,22 @@ public void populateAttributes(final AuthenticationBuilder builder, final Authen transaction.getPrimaryCredential().ifPresent(r -> { final OsfPostgresCredential credential = (OsfPostgresCredential) r; LOGGER.debug( - "Credential is of type [{}], thus adding attributes [{}, {}, {}, {}]", + "Credential is of type [{}], thus adding attributes [{}, {}, {}, {}, {}]", OsfPostgresCredential.class.getSimpleName(), OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_REMEMBER_ME, OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_REMOTE_PRINCIPAL, OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_DELEGATION_PROTOCOL, - OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_INSTITUTION_ID + OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_INSTITUTION_ID, + OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_TOS_CONSENT ); builder.addAttribute( OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_REMEMBER_ME, credential.isRememberMe() ); + builder.addAttribute( + OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_TOS_CONSENT, + credential.isTermsOfServiceChecked() + ); builder.addAttribute( OsfPostgresCredential.AUTHENTICATION_ATTRIBUTE_REMOTE_PRINCIPAL, credential.isRemotePrincipal() From b5ca819d49f5044c9481222f2cd47e1c79f2ac13 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 7 Jan 2021 18:25:45 -0500 Subject: [PATCH 33/71] Fix an issue where TOS agree button is not disabled when page loads --- src/main/resources/templates/fragments/tosloginform.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/templates/fragments/tosloginform.html b/src/main/resources/templates/fragments/tosloginform.html index f8ec1f4c..79feafc5 100644 --- a/src/main/resources/templates/fragments/tosloginform.html +++ b/src/main/resources/templates/fragments/tosloginform.html @@ -99,7 +99,6 @@

var j = /*[[@{#{screen.tosconsent.button.agree}}]]*/ 'Continue'; /*]]>*/ $(window).on('pageshow', function () { - $(':submit').prop('disabled', false); $(':submit').attr('value', j); }); $(document).ready(function () { From 485bc03599245edee3cd031576ebad6e7cc33d95 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Thu, 7 Jan 2021 18:29:09 -0500 Subject: [PATCH 34/71] Remove TOS consent check from institution login page --- src/main/resources/messages.properties | 3 --- .../templates/casInstitutionLoginView.html | 27 +------------------ 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index a6227342..192bd1bc 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -587,9 +587,6 @@ screen.institutionlogin.select.errormessage=You must select an institution. screen.institutionlogin.button.submit=Sign in screen.institutionlogin.osf=Sign in with OSF screen.institutionlogin.backtoosf=Exit and go back to OSF -screen.institutionlogin.consent.checkbox=I have read and agree to the Terms of Use and Privacy Policy. -screen.institutionlogin.consent.errormessage=You must read and agree to the Terms of Use and Privacy Policy. - # # Generic login and logout success page # diff --git a/src/main/resources/templates/casInstitutionLoginView.html b/src/main/resources/templates/casInstitutionLoginView.html index 1417e10a..2aa69489 100644 --- a/src/main/resources/templates/casInstitutionLoginView.html +++ b/src/main/resources/templates/casInstitutionLoginView.html @@ -43,16 +43,6 @@

× - -
+
+ +
+ + +
+ diff --git a/src/main/resources/templates/fragments/totploginform.html b/src/main/resources/templates/fragments/totploginform.html index 0a03ca81..9483d662 100644 --- a/src/main/resources/templates/fragments/totploginform.html +++ b/src/main/resources/templates/fragments/totploginform.html @@ -12,20 +12,22 @@
+
-
+
-
+ -

+

-

+
+
@@ -88,13 +90,13 @@
- +
@@ -109,7 +111,9 @@

-
+
+
+
From a5e22e801b4ee058d2df9223e69a8fbebcb91d45 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Fri, 29 Jan 2021 20:50:42 -0500 Subject: [PATCH 49/71] Update local registered service JSON definitions * Removed deprecated fakeosf * Set empty names and descriptions for non-branded services --- .../services/local/cas-203948234207100.json | 4 +-- .../local/fakeosf-203948234207210.json | 31 ------------------- .../local/legacyosf-203948234207220.json | 4 +-- .../services/local/osf-203948234207230.json | 2 +- .../local/preprints-203948234207240.json | 2 +- .../local/registries-203948234207340.json | 2 +- 6 files changed, 7 insertions(+), 38 deletions(-) delete mode 100644 etc/cas/services/local/fakeosf-203948234207210.json diff --git a/etc/cas/services/local/cas-203948234207100.json b/etc/cas/services/local/cas-203948234207100.json index 27fc8ff5..9c12c746 100644 --- a/etc/cas/services/local/cas-203948234207100.json +++ b/etc/cas/services/local/cas-203948234207100.json @@ -1,8 +1,8 @@ { "@class": "org.apereo.cas.services.RegexRegisteredService", "serviceId": "^https?://(localhost|127\\.0\\.0\\.1|192\\.168\\.168\\.167)(|:8080|:8443)/.*", - "name": "OSF CAS", - "description": "OSF CAS is the centralized authentication and authorization service for OSF", + "name": "", + "description": "", "id": 203948234207100, "evaluationOrder": 10, "logo": "/images/osf-banner.png", diff --git a/etc/cas/services/local/fakeosf-203948234207210.json b/etc/cas/services/local/fakeosf-203948234207210.json deleted file mode 100644 index 4500aabf..00000000 --- a/etc/cas/services/local/fakeosf-203948234207210.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "@class": "org.apereo.cas.services.RegexRegisteredService", - "serviceId": "^https?://(localhost|127\\.0\\.0\\.1|192\\.168\\.168\\.167):5000/fake/.*", - "name": "One Special Fake OSF", - "description": "This is the One Special Fake OSF for testing hard-to-reach corner cases and errors (local-dev only)", - "id": 203948234207210, - "evaluationOrder": 25, - "logo": "/images/osf-logo.png", - "attributeReleasePolicy": { - "@class": "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy", - "allowedAttributes": [ - "java.util.ArrayList", - [ - "givenName", - "familyName", - "username" - ] - ] - }, - "accessStrategy": { - "@class": "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy", - "delegatedAuthenticationPolicy": { - "@class": "org.apereo.cas.services.DefaultRegisteredServiceDelegatedAuthenticationPolicy", - "allowedProviders": [ - "java.util.ArrayList", - [] - ], - "permitUndefined": false - } - } -} diff --git a/etc/cas/services/local/legacyosf-203948234207220.json b/etc/cas/services/local/legacyosf-203948234207220.json index 57027e71..84810908 100644 --- a/etc/cas/services/local/legacyosf-203948234207220.json +++ b/etc/cas/services/local/legacyosf-203948234207220.json @@ -1,8 +1,8 @@ { "@class": "org.apereo.cas.services.RegexRegisteredService", "serviceId": "^https?://(localhost|127\\.0\\.0\\.1|192\\.168\\.168\\.167):5000/.*", - "name": "OSF", - "description": "Manage and share your research with OSF – an free, open, easy and integrated platform to support your research and enable collaboration.", + "name": "", + "description": "", "id": 203948234207220, "evaluationOrder": 25, "logo": "/images/osf-logo.png", diff --git a/etc/cas/services/local/osf-203948234207230.json b/etc/cas/services/local/osf-203948234207230.json index 250f19b1..953c0ed4 100644 --- a/etc/cas/services/local/osf-203948234207230.json +++ b/etc/cas/services/local/osf-203948234207230.json @@ -2,7 +2,7 @@ "@class": "org.apereo.cas.services.RegexRegisteredService", "serviceId": "^https?://(localhost|127\\.0\\.0\\.1|192\\.168\\.168\\.167):5000/(login|logout)/?\\?next=.*", "name": "", - "description": "There's a better way to manage your research! OSF is a free, open platform to support your research and enable collaboration.", + "description": "", "id": 203948234207230, "evaluationOrder": 20, "logo": "/images/osf-banner.png", diff --git a/etc/cas/services/local/preprints-203948234207240.json b/etc/cas/services/local/preprints-203948234207240.json index aae6858e..5928bc27 100644 --- a/etc/cas/services/local/preprints-203948234207240.json +++ b/etc/cas/services/local/preprints-203948234207240.json @@ -2,7 +2,7 @@ "@class": "org.apereo.cas.services.RegexRegisteredService", "serviceId": "^https?://(localhost|127\\.0\\.0\\.1):5000/(login|logout)/?\\?next=https?(%3A|:)(%2F|/)(%2F|/)(localhost|127\\.0\\.0\\.1)(%3A|:)5000(%2F|/)preprints($|%2F|/).*", "name": "", - "description": "Accelerating scholarly review, publishing, and discovery.", + "description": "", "id": 203948234207240, "evaluationOrder": 15, "logo": "/images/osf-preprints-banner.png", diff --git a/etc/cas/services/local/registries-203948234207340.json b/etc/cas/services/local/registries-203948234207340.json index de4af6d1..160d2232 100644 --- a/etc/cas/services/local/registries-203948234207340.json +++ b/etc/cas/services/local/registries-203948234207340.json @@ -2,7 +2,7 @@ "@class": "org.apereo.cas.services.RegexRegisteredService", "serviceId": "^https?://(localhost|127\\.0\\.0\\.1):5000/(login|logout)/?\\?next=https?(%3A|:)(%2F|/)(%2F|/)(localhost|127\\.0\\.0\\.1)(%3A|:)5000(%2F|/)registries($|%2F|/).*", "name": "", - "description": "The open registries network", + "description": "", "id": 203948234207340, "evaluationOrder": 15, "logo": "/images/osf-registries-banner.png", From 5a5169632f4b588b178ec246516c594ff903790d Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Fri, 29 Jan 2021 22:32:31 -0500 Subject: [PATCH 50/71] Institution login page rework - part 1 * Rewrote boy and content styles to match other login pages * Removed not-so-useful and duplicating institution banner UI * Rewrote the institution banner into a pair of shield (logo) with short / full name, which behaves similar to the OSF / CAS brand in the app (nav) bar. --- src/main/resources/messages.properties | 1 - src/main/resources/static/css/cas.css | 67 ++++++++++++------- .../templates/casInstitutionLoginView.html | 30 ++++++--- .../fragments/osfinstitutionbannerui.html | 24 ------- 4 files changed, 62 insertions(+), 60 deletions(-) delete mode 100644 src/main/resources/templates/fragments/osfinstitutionbannerui.html diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 0038892a..c72dc64f 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -581,7 +581,6 @@ screen.tosconsent.link.cancel=Cancel and go back to OSF # Institution login page # screen.institutionlogin.pagetitle=Institution SSO -screen.institutionlgoin.bannertitle=OSF Institutions screen.institutionlogin.heading=Sign in through institution screen.institutionlogin.message=If your institution has partnered with OSF, please select its name below and sign in with your institutional credentials. If you do not currently have an OSF account, this will create one for you. screen.institutionlogin.select=Select your institution diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index d723de4c..4fb3d0bc 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -756,26 +756,6 @@ body { max-width: 48rem; } -.login-instn-card .card-message { - padding: 0.25rem 0; -} - -.login-instn-card .instn-select select { - width: 100%; - height: 3rem; - font-size: 1.25rem; - padding: 0 1rem; - margin: 0.5rem 0; -} - -.login-instn-card .instn-consent { - padding: 1rem 0; -} - -.login-instn-card .instn-consent input { - margin-right: 0.5rem; -} - .mdc-top-app-bar__row, .mdc-top-app-bar__row .mdc-top-app-bar__section { min-width: fit-content; @@ -803,7 +783,8 @@ body { color: #F7F7F7; } -.mdc-top-app-bar__row .hidden-narrow { +.mdc-top-app-bar__row .hidden-narrow, +.service-ui .osf-shield-with-name .hidden-narrow { font-weight: normal; } @@ -829,6 +810,20 @@ body { display: none; } +.service-ui .osf-shield-with-name { + margin: 0 auto; + padding-bottom: 1rem; +} + +.osf-shield-with-name .service-ui-logo { + padding-right: 0.5rem; +} + +.osf-shield-with-name .service-ui-name { + font-size: 2.25rem; + font-weight: bold; +} + .text-with-mdi, .text-without-mdi { font-size: 1rem; @@ -887,6 +882,13 @@ body { padding: 1rem 0; } +.login-section .instn-select select { + width: 100%; + height: 56px; + font-size: 1.25rem; + margin: 0.5rem 0; +} + .login-error-list .banner { border: none; position: relative; @@ -1049,10 +1051,6 @@ body { @media all and (min-width: 699.99px) { - .mdc-top-app-bar__row .hidden-narrow { - display: inline; - } - .w-card-narrow { width: 50%; } @@ -1075,7 +1073,8 @@ body { @media all and (max-width: 699.99px) { - .mdc-top-app-bar__row .hidden-narrow { + .mdc-top-app-bar__row .hidden-narrow, + .service-ui-name .osf-shield-with-name .hidden-narrow { display: None; } @@ -1090,6 +1089,14 @@ body { max-width: 280px; } + .osf-shield-with-name .service-ui-logo { + max-height: 48px; + } + + .osf-shield-with-name .service-ui-name { + font-size: 2rem; + } + .login-section .text-with-mdi { font-size: 0.875rem; } @@ -1132,6 +1139,14 @@ body { max-width: 240px; } + .osf-shield-with-name .service-ui-logo { + max-height: 36px; + } + + .osf-shield-with-name .service-ui-name { + font-size: 1.75rem; + } + .login-section .text-with-mdi { font-size: 0.875rem; } diff --git a/src/main/resources/templates/casInstitutionLoginView.html b/src/main/resources/templates/casInstitutionLoginView.html index 2aa69489..550aed7d 100644 --- a/src/main/resources/templates/casInstitutionLoginView.html +++ b/src/main/resources/templates/casInstitutionLoginView.html @@ -9,15 +9,27 @@ - -
+ +
+
+
-
+
+ + +
From 84623af9a9d236c77130457a80d7cef2a4749830 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Sat, 30 Jan 2021 01:03:24 -0500 Subject: [PATCH 52/71] Flowless page rework * Rewrote flowless header to use a similar app / nav bar where OSF CAS replaces OSF HOME and the sign-up button is disabled. * Updated pre-login action to support clicking OSF CAS in app / nav bar to go back to login with default service added. * Rewrote flowless error pages into follow customized top-down (banner-title-heading-message-button-link) style, with new style class login-error-card copyinmg most of the behaviors of class login-section. * Cleaned up cas.css. --- .../OsfAbstractLoginPreparationAction.java | 2 +- src/main/resources/messages.properties | 9 ++- src/main/resources/static/css/cas.css | 76 +++++++------------ src/main/resources/templates/error/401.html | 42 +++++++--- src/main/resources/templates/error/403.html | 42 +++++++--- src/main/resources/templates/error/404.html | 42 +++++++--- src/main/resources/templates/error/405.html | 42 +++++++--- src/main/resources/templates/error/423.html | 42 +++++++--- .../templates/fragments/headerflowless.html | 30 +++++--- .../resources/templates/layoutFlowless.html | 8 ++ 10 files changed, 220 insertions(+), 115 deletions(-) diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java index dc3db860..3e029506 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java @@ -45,7 +45,7 @@ public abstract class OsfAbstractLoginPreparationAction extends AbstractAuthenti protected static final String PARAMETER_ERROR_SOURCE = "errorSource"; - protected static final List EXPECTED_ERROR_CODES = new LinkedList<>(Arrays.asList("401", "403", "404", "405", "423")); + protected static final List EXPECTED_ERROR_CODES = new LinkedList<>(Arrays.asList("401", "403", "404", "405", "423", "-1")); public OsfAbstractLoginPreparationAction( final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver, diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 6d5d5044..2c0e26fc 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -170,7 +170,7 @@ screen.error.page.title.requestunsupported=Error - Unsupported Request screen.error.page.accessdenied=Access Denied screen.error.page.permissiondenied=You do not have permission to view this page. screen.error.page.requestunsupported=The request type or syntax is not supported. -screen.error.page.loginagain=Login Again +# screen.error.page.loginagain=Login Again screen.error.page.notfound=Page Not Found screen.error.page.doesnotexist=The page you are attempting to access does not exist at the moment. screen.error.page.authdenied=Authorization Denied @@ -531,9 +531,9 @@ screen.welcome.label.loginwith=Sign in through external identity providers # # Texts and messages that are shared across all pages # -screen.generic.label.source = Source: -screen.generic.button.wip = One moment please ... -screen.generic.link.support = Need help signing in? +screen.generic.label.source=Source: +screen.generic.button.wip=One moment please ... +screen.generic.link.support=Need help signing in? # # Login page and login form submission # @@ -625,6 +625,7 @@ authenticationFailure.TermsOfServiceConsentRequiredException= # # Authentication exception messages in stand-alone exception views # +screen.error.page.loginagain=Log in again screen.authnerror.instructions=Oops! Something went wrong ... screen.authnerror.button.resendosfconfirmation=Resend confirmation email screen.authnerror.button.backtoosf=Exit and go back to OSF diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index 1449876c..ce61afcd 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -639,10 +639,6 @@ body { font-size: 1rem; } -.login-error-card .hr-text, -.login-generic-card .hr-text { - margin: 1.5rem 0; -} .hr-text::before { content: ''; @@ -718,42 +714,13 @@ body { background-color: var(--cas-theme-osf-disabled, #EFEFEF); } -.login-error-card, -.login-generic-card { - min-width: fit-content; -} - .login-error-card .pre-formatted-small pre { font-size: 0.75rem; white-space: pre-wrap; } -.banner-generic, -.banner-danger { - min-width: fit-content; -} - -.banner-danger .title-danger { - margin: 0.5rem 0; +.title-danger { color: var(--cas-theme-osf-red, #b52b27); - white-space: nowrap; -} - -.banner-generic hr, -.banner-danger hr { - width: 100%; -} - -.card-message { - padding: 1rem 0; -} - -.w-card-narrow .card-message { - max-width: 36rem; -} - -.w-card-wide .card-message { - max-width: 48rem; } .mdc-top-app-bar__row, @@ -778,6 +745,12 @@ body { color: #F7F7F7; } +.mdc-top-app-bar__row .button-osf-disabled { + opacity: 0.8; + cursor: not-allowed; + color: var(--cas-theme-osf-disabled-dark, #cccccc); +} + .mdc-top-app-bar__row .cas-brand-name { font-weight: bold; color: #F7F7F7; @@ -788,10 +761,17 @@ body { font-weight: normal; } -.login-section { +.login-section, +.login-error-card { + border: none; width: 512px; } +.login-error-card { + padding: 2rem 2.5rem; + flex: 1; +} + #serviceui { background-color: transparent; } @@ -865,8 +845,10 @@ body { padding-left: 28px; } +.login-section .mdc-button, .login-section .mdc-text-field, -.login-section .mdc-button { +.login-error-card .mdc-button, +.login-error-card .mdc-text-field { font-size: 1rem; } @@ -886,6 +868,10 @@ body { padding: 1rem 0; } +.login-error-card .card-message { + padding: 0; +} + .login-section .instn-select select { width: 100%; height: 56px; @@ -1065,10 +1051,6 @@ body { .service-ui .service-ui-logo { max-width: 320px; } - - .login-error-card .title-danger { - font-size: 1rem; - } } @media all and (max-width: 699.99px) { @@ -1096,15 +1078,12 @@ body { .osf-shield-with-name .service-ui-name { font-size: 2rem; } - - .login-error-card .title-danger { - font-size: 0.875rem; - } } @media all and (max-width: 511.99px) { - .login-section { + .login-section, + .login-error-card { width: fit-content; min-width: 360px; } @@ -1143,14 +1122,11 @@ body { font-size: 1.75rem; } - .login-section .mdi-before-text { + .login-section .mdi-before-text, + .login-error-card .mdi-before-text { display: none; } - .login-error-card .title-danger { - font-size: 0.875rem; - } - .cas-footer-osf { font-size: 0.625rem!important; padding-bottom: 0.625rem!important; diff --git a/src/main/resources/templates/error/401.html b/src/main/resources/templates/error/401.html index 15ec7321..46da1ccf 100644 --- a/src/main/resources/templates/error/401.html +++ b/src/main/resources/templates/error/401.html @@ -5,20 +5,42 @@ - Error - 401 + - -
-
-

Access Denied

-

You do not have permission to view this page.

- - Login Again - + +
+
+
-
+ diff --git a/src/main/resources/templates/error/403.html b/src/main/resources/templates/error/403.html index abdd18fb..cc0a4cf1 100644 --- a/src/main/resources/templates/error/403.html +++ b/src/main/resources/templates/error/403.html @@ -5,20 +5,42 @@ - Error - Permission Denied + - -
-
-

Authorization Denied

-

You do not have permission to view this page.

- - Login Again - + +
+
+
-
+ diff --git a/src/main/resources/templates/error/404.html b/src/main/resources/templates/error/404.html index b1c65601..69a48853 100644 --- a/src/main/resources/templates/error/404.html +++ b/src/main/resources/templates/error/404.html @@ -5,20 +5,42 @@ - Error - Page Not Found + - -
-
-

Page Not Found

-

The page you are attempting to access does not exist at the moment.

- - Login Again - + +
+
+
-
+ diff --git a/src/main/resources/templates/error/405.html b/src/main/resources/templates/error/405.html index c9f0db8c..990fb844 100644 --- a/src/main/resources/templates/error/405.html +++ b/src/main/resources/templates/error/405.html @@ -5,20 +5,42 @@ - Error - Unsupported Request + - -
-
-

The request type or syntax is not supported.

-

You do not have permission to view this page.

- - Login Again - + +
+
+
-
+ diff --git a/src/main/resources/templates/error/423.html b/src/main/resources/templates/error/423.html index d7606989..beeff20e 100644 --- a/src/main/resources/templates/error/423.html +++ b/src/main/resources/templates/error/423.html @@ -5,20 +5,42 @@ - Error - Permission Denied + - -
-
-

Access Denied

-

You've entered the wrong password for the user too many times. You've been throttled.

- - Login Again - + +
+
+
-
+ diff --git a/src/main/resources/templates/fragments/headerflowless.html b/src/main/resources/templates/fragments/headerflowless.html index 2a699f20..d082d61a 100644 --- a/src/main/resources/templates/fragments/headerflowless.html +++ b/src/main/resources/templates/fragments/headerflowless.html @@ -11,29 +11,39 @@
+
+ +
+
+
+
From 3891dc01954c34d62bb3a0a87b5e6c7fd8c4f114 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Sat, 30 Jan 2021 02:56:25 -0500 Subject: [PATCH 53/71] Add an option for pages to disable the sign-up button * The sign-up button may not make sense all the time for all pages. Thus CAS needs to let individual pages decide whether to disable it and if so when to. * In addititon, reworked the account-not-confirmed error page as a proof of concept implementation for: 1) disabling sign-up button for all customized authn error pages, and 2) the "banner-title- heading-message-button-link" design works well without the need to add extra css tweaking / hacking, which is much cleaner than previous versions. --- .../casAccountNotConfirmedOsfView.html | 56 ++++++++++++------- .../resources/templates/fragments/header.html | 15 ++++- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/main/resources/templates/casAccountNotConfirmedOsfView.html b/src/main/resources/templates/casAccountNotConfirmedOsfView.html index 85048bae..91c45bbb 100644 --- a/src/main/resources/templates/casAccountNotConfirmedOsfView.html +++ b/src/main/resources/templates/casAccountNotConfirmedOsfView.html @@ -9,34 +9,48 @@ - -
- -
+ + +
diff --git a/src/main/resources/templates/fragments/header.html b/src/main/resources/templates/fragments/header.html index 4e84f128..cb393f90 100644 --- a/src/main/resources/templates/fragments/header.html +++ b/src/main/resources/templates/fragments/header.html @@ -29,7 +29,7 @@
@@ -38,6 +38,19 @@ + + + + diff --git a/src/main/resources/templates/casAccountNotConfirmedIdPView.html b/src/main/resources/templates/casAccountNotConfirmedIdPView.html index f23888f1..2cf7a89c 100644 --- a/src/main/resources/templates/casAccountNotConfirmedIdPView.html +++ b/src/main/resources/templates/casAccountNotConfirmedIdPView.html @@ -9,29 +9,42 @@ - -
-

-
+

-
- - + +
+
+ + +
+ - + + + + diff --git a/src/main/resources/templates/casAccountNotConfirmedOsfView.html b/src/main/resources/templates/casAccountNotConfirmedOsfView.html index 91c45bbb..e1f9b250 100644 --- a/src/main/resources/templates/casAccountNotConfirmedOsfView.html +++ b/src/main/resources/templates/casAccountNotConfirmedOsfView.html @@ -11,45 +11,39 @@
+
+
diff --git a/src/main/resources/templates/casInstitutionSsoFailedView.html b/src/main/resources/templates/casInstitutionSsoFailedView.html index 0b85c17d..1b715e36 100644 --- a/src/main/resources/templates/casInstitutionSsoFailedView.html +++ b/src/main/resources/templates/casInstitutionSsoFailedView.html @@ -9,29 +9,42 @@ - -
- -
+ + + + diff --git a/src/main/resources/templates/casInvalidUserStatusView.html b/src/main/resources/templates/casInvalidUserStatusView.html index 12cf1b2c..1f1ad20b 100644 --- a/src/main/resources/templates/casInvalidUserStatusView.html +++ b/src/main/resources/templates/casInvalidUserStatusView.html @@ -9,29 +9,42 @@ - -
- -
+ + + + diff --git a/src/main/resources/templates/casInvalidVerificationKeyView.html b/src/main/resources/templates/casInvalidVerificationKeyView.html index a56b93f2..853f6e0e 100644 --- a/src/main/resources/templates/casInvalidVerificationKeyView.html +++ b/src/main/resources/templates/casInvalidVerificationKeyView.html @@ -9,29 +9,42 @@ - -
- -
+ + + + diff --git a/src/main/resources/templates/casServiceErrorView.html b/src/main/resources/templates/casServiceErrorView.html index c75496f5..90bb4163 100644 --- a/src/main/resources/templates/casServiceErrorView.html +++ b/src/main/resources/templates/casServiceErrorView.html @@ -2,36 +2,49 @@ - - + + - Service Error View + - -
- -
+ + + + From be4586216c0c0622ec5184fcbddfeafde792e2a0 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Sat, 30 Jan 2021 13:29:38 -0500 Subject: [PATCH 55/71] CAS unavailable / server error page rework * In addititon to standard style updates, this page includes a developer mode option (depending on which server environment on which newCAS is running) that allows error info and stack trace to be displayed. * Currently, this is not fully implemented and the page assumes developer mode by default. --- src/main/resources/static/css/cas.css | 19 +++- src/main/resources/templates/error.html | 122 ++++++++++++++---------- 2 files changed, 84 insertions(+), 57 deletions(-) diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index ce61afcd..d985801b 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -688,6 +688,11 @@ body { padding: 0 8px; } +.form-button .button-osf-navbar, +.form-button-inline .button-osf-navbar { + background-color: var(--cas-theme-osf-navbar, #263947); +} + .form-button .button-osf-grey, .form-button-inline .button-osf-grey { background-color: var(--cas-theme-osf-grey, #eeeeee); @@ -714,11 +719,6 @@ body { background-color: var(--cas-theme-osf-disabled, #EFEFEF); } -.login-error-card .pre-formatted-small pre { - font-size: 0.75rem; - white-space: pre-wrap; -} - .title-danger { color: var(--cas-theme-osf-red, #b52b27); } @@ -830,6 +830,10 @@ body { margin: 1rem 0; } +.hidden-details { + display: none; +} + .form-button-inline .delegation-button-logo { position: absolute; left: 4px; @@ -852,6 +856,11 @@ body { font-size: 1rem; } +.login-error-card .pre-formatted-small pre { + font-size: 0.75rem; + white-space: pre-wrap; +} + .login-section .background-disabled { background-color: var(--cas-theme-osf-disabled-dark, #cccccc); } diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index 0c3a0314..3cc182be 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -2,70 +2,88 @@ - - + + - CAS Error View + - -
- From 096879ec79b166fa9b02e9286d2a60fc9d065601 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Sat, 30 Jan 2021 15:57:27 -0500 Subject: [PATCH 56/71] Clean-up * Removed properties that are no longer needed due to FE rework * Futher cleaned up cas.css to sperate vanilla Apereo styles and OSF CAS customized ones; and re-organized the styles for better context awareness and readability. * Minor fixes / improvements for a few pages. --- etc/cas/config/cas.properties | 10 -- etc/cas/config/local/cas-local.properties | 10 -- .../configuration/model/OsfUrlProperties.java | 35 ------- src/main/resources/messages.properties | 1 + src/main/resources/static/css/cas.css | 94 +++++++++++++------ src/main/resources/templates/error.html | 13 ++- .../templates/fragments/tosloginform.html | 2 +- 7 files changed, 75 insertions(+), 90 deletions(-) diff --git a/etc/cas/config/cas.properties b/etc/cas/config/cas.properties index 9d9b1e71..c1d152cb 100644 --- a/etc/cas/config/cas.properties +++ b/etc/cas/config/cas.properties @@ -76,16 +76,6 @@ cas.authn.osf-url.logout=https://{{ .Values.osfDomain }}/logout/ cas.authn.osf-url.resend-confirmation=https://{{ .Values.osfDomain }}/resend/ cas.authn.osf-url.forgot-password=https://{{ .Values.osfDomain }}/forgotpassword/ cas.authn.osf-url.register=https://{{ .Values.osfDomain }}/register/ -cas.authn.osf-url.search=https://{{ .Values.osfDomain }}/search/ -cas.authn.osf-url.support=https://{{ .Values.osfDomain }}/support/ -cas.authn.osf-url.donate=https://www.cos.io/about/support-cos/ -# -# OSF Products -# -cas.authn.osf-url.preprints-home=https://{{ .Values.osfDomain }}/preprints/ -cas.authn.osf-url.registries-home=https://{{ .Values.osfDomain }}/registries/ -cas.authn.osf-url.institutions-home=https://{{ .Values.osfDomain }}/institutions/ -cas.authn.osf-url.meetings-home=https://{{ .Values.osfDomain }}/meetings/ ######################################################################################################################## ######################################################################################################################## diff --git a/etc/cas/config/local/cas-local.properties b/etc/cas/config/local/cas-local.properties index a9df2402..073cc42f 100644 --- a/etc/cas/config/local/cas-local.properties +++ b/etc/cas/config/local/cas-local.properties @@ -77,16 +77,6 @@ cas.authn.osf-url.logout=http://localhost:5000/logout/ cas.authn.osf-url.resend-confirmation=http://localhost:5000/resend/ cas.authn.osf-url.forgot-password=http://localhost:5000/forgotpassword/ cas.authn.osf-url.register=http://localhost:5000/register/ -cas.authn.osf-url.search=http://localhost:5000/search/ -cas.authn.osf-url.support=http://localhost:5000/support/ -cas.authn.osf-url.donate=https://www.cos.io/about/support-cos/ -# -# OSF Products -# -cas.authn.osf-url.preprints-home=http://localhost:5000/preprints/ -cas.authn.osf-url.registries-home=http://localhost:5000/registries/ -cas.authn.osf-url.institutions-home=http://localhost:5000/institutions/ -cas.authn.osf-url.meetings-home=http://localhost:5000/meetings/ ######################################################################################################################## ######################################################################################################################## diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java index 8da32c89..04704c24 100644 --- a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java @@ -61,41 +61,6 @@ public class OsfUrlProperties implements Serializable { */ private String forgotPassword; - /** - * OSF Preprints landing page URL. - */ - private String preprintsHome; - - /** - * OSF Registries landing page URL. - */ - private String registriesHome; - - /** - * OSF Institutions landing page URL. - */ - private String institutionsHome; - - /** - * OSF meetings landing page URL. - */ - private String meetingsHome; - - /** - * OSF search page URL. - */ - private String search; - - /** - * OSF support page URL. - */ - private String support; - - /** - * OSF / COS donation page URL. - */ - private String donate; - /** * Build the default service URL using OSF login endpoint with OSF home page as destination. */ diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 2c0e26fc..b602eb14 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -627,6 +627,7 @@ authenticationFailure.TermsOfServiceConsentRequiredException= # screen.error.page.loginagain=Log in again screen.authnerror.instructions=Oops! Something went wrong ... +screen.authnerror.instructions.devmode=Developer mode only !!! screen.authnerror.button.resendosfconfirmation=Resend confirmation email screen.authnerror.button.backtoosf=Exit and go back to OSF screen.accountdisabled.heading=Account disabled diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index d985801b..9b4a6b3b 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -1,3 +1,7 @@ +/************************************************** + * Start of default styles as of Apereo CAS 6.2.x * + **************************************************/ + /* Root / Reset */ :root { @@ -114,6 +118,20 @@ header>nav .cas-brand .cas-logo { border: none; } +/** + * Disabled for OSF CAS. + * + * @media screen and (max-width: 767.99px) { + * .login-section { + * border-right: none; + * border-bottom: 1px solid rgba(0, 0, 0, .2); + * border-bottom: var(--cas-theme-border-light, 1px solid rgba(0, 0, 0, .2)); + * max-width: none; + * padding: 0 1.5rem; + * } + * } + */ + .close { font-size: 1.5rem; font-weight: 700; @@ -122,7 +140,6 @@ header>nav .cas-brand .cas-logo { text-shadow: 0 1px 0 #fff; text-transform: none; text-decoration: none; - ; } button.close { @@ -209,6 +226,16 @@ button.close { margin-right: 0.375rem; } +/** + * Disabled for OSF CAS. + * + * @media screen and (max-width: 767.99px) { + * .logout-banner { + * width: 100%; + * } + * } + */ + .cas-footer { font-size: 0.75rem; } @@ -568,7 +595,13 @@ button.close { border-radius: 4px; } -/* customized styles for OSF CAS */ +/************************************************ + * End of default styles as of Apereo CAS 6.2.x * + ************************************************/ + +/****************************************** + * Start of customized styles for OSF CAS * + ******************************************/ :root { --cas-theme-osf-navbar: #263947; @@ -578,12 +611,12 @@ button.close { --cas-theme-osf-green: #357935; --cas-theme-osf-blue: #1b6d85; --cas-theme-osf-red: #b52b27; - --cas-theme-osf-disabled: var(--cas-theme-osf-grey, #eeeeee); + --cas-theme-osf-disabled: #eeeeee; --cas-theme-osf-disabled-dark: #cccccc; --cas-theme-primary: var(--cas-theme-osf-navbar, #263947); --cas-theme-danger: var(--cas-theme-osf-red, #b52b27); --mdc-theme-primary: var(--cas-theme-primary, #263947); - --mdc-theme-surface: var(--cas-theme-osf-surface, #F7F7F7); + --mdc-theme-surface: var(--cas-theme-osf-surface, #f7f7f7); } body { @@ -611,22 +644,6 @@ body { justify-content: center; } - -.mdi-before-text { - font-size: inherit; - vertical-align: text-bottom; - margin-right: 0.5rem; -} - -.mdi-before-text:before { - font-size:inherit; -} - -.cas-field-primary { - margin-bottom: 1rem!important; - margin-top: 0.5rem!important; -} - .hr-text { line-height: 1rem; position: relative; @@ -639,7 +656,6 @@ body { font-size: 1rem; } - .hr-text::before { content: ''; background: linear-gradient(to right, transparent, black, var(--cas-theme-osf-surface, #f7f7f7)); @@ -719,10 +735,6 @@ body { background-color: var(--cas-theme-osf-disabled, #EFEFEF); } -.title-danger { - color: var(--cas-theme-osf-red, #b52b27); -} - .mdc-top-app-bar__row, .mdc-top-app-bar__row .mdc-top-app-bar__section { min-width: fit-content; @@ -810,6 +822,20 @@ body { margin: 0.5rem 0; } +.mdi-before-text { + font-size: inherit; + vertical-align: text-bottom; + margin-right: 0.5rem; +} + +.mdi-before-text:before { + font-size: inherit; +} + +.title-danger { + color: var(--cas-theme-osf-red, #b52b27); +} + .text-no-wrap { white-space: nowrap; } @@ -822,14 +848,11 @@ body { font-size: 1.125rem; } -.text-extra-large { - font-size: 1.25rem; -} - .margin-large-vertical { margin: 1rem 0; } +.hidden-button, .hidden-details { display: none; } @@ -849,6 +872,10 @@ body { padding-left: 28px; } +.login-error-card .form-button { + padding-top: 1rem; +} + .login-section .mdc-button, .login-section .mdc-text-field, .login-error-card .mdc-button, @@ -903,6 +930,11 @@ body { margin: 0.25rem 0; } +.cas-field-primary { + margin-bottom: 1rem!important; + margin-top: 0.5rem!important; +} + .cas-field-col-2 { margin-top: 1rem!important; margin-bottom: 1.5rem!important; @@ -1142,3 +1174,7 @@ body { padding-top: 0.625rem!important; } } + +/**************************************** + * End of customized styles for OSF CAS * + ****************************************/ diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index 3cc182be..2c3e9491 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -14,7 +14,7 @@
-
+ + + + + + diff --git a/src/main/resources/templates/casLogoutView.html b/src/main/resources/templates/casLogoutView.html index 7118f8f2..d92ce3ba 100644 --- a/src/main/resources/templates/casLogoutView.html +++ b/src/main/resources/templates/casLogoutView.html @@ -2,40 +2,48 @@ - - + + - + - -
-
-
+ + + From df3699caad48c79d3ee4434eb90083fa3d5df6f6 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Feb 2021 11:20:59 -0500 Subject: [PATCH 58/71] Replace "errorSource" with "casRedirectSource" With recent FE rework on the "login again" link / button, how CAS handles such redirection no longer only applies to customized or flowless error pages. Thus, the property name and its query param name and accepted values have all been updated. --- .../osf/web/flow/login/OsfAbstractLoginPreparationAction.java | 4 ++-- .../osf/web/flow/login/OsfDefaultLoginPreparationAction.java | 4 ++-- src/main/resources/templates/casAccountDisabledView.html | 2 +- src/main/resources/templates/casInstitutionSsoFailedView.html | 2 +- src/main/resources/templates/casInvalidUserStatusView.html | 2 +- .../resources/templates/casInvalidVerificationKeyView.html | 2 +- src/main/resources/templates/casLogoutView.html | 2 +- src/main/resources/templates/casServiceErrorView.html | 2 +- src/main/resources/templates/error.html | 2 +- src/main/resources/templates/error/401.html | 2 +- src/main/resources/templates/error/403.html | 2 +- src/main/resources/templates/error/404.html | 2 +- src/main/resources/templates/error/405.html | 2 +- src/main/resources/templates/error/423.html | 2 +- src/main/resources/templates/fragments/headerflowless.html | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java index 3e029506..f337502d 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java @@ -43,9 +43,9 @@ public abstract class OsfAbstractLoginPreparationAction extends AbstractAuthenti protected static final String PARAMETER_ORCID_REDIRECT_VALUE = "true"; - protected static final String PARAMETER_ERROR_SOURCE = "errorSource"; + protected static final String PARAMETER_REDIRECT_SOURCE = "casRedirectSource"; - protected static final List EXPECTED_ERROR_CODES = new LinkedList<>(Arrays.asList("401", "403", "404", "405", "423", "-1")); + protected static final List EXPECTED_REDIRECT_CODES = new LinkedList<>(Arrays.asList("tomcat", "cas")); public OsfAbstractLoginPreparationAction( final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver, diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java index 66a6ee91..a084040e 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java @@ -147,8 +147,8 @@ private String getEncodedServiceUrlFromRequestContext(final RequestContext conte } private boolean isFromFlowlessErrorPage(final RequestContext context) { - final String errorCode = context.getRequestParameters().get(PARAMETER_ERROR_SOURCE); - return !StringUtils.isBlank(errorCode) && EXPECTED_ERROR_CODES.contains(errorCode); + final String errorCode = context.getRequestParameters().get(PARAMETER_REDIRECT_SOURCE); + return !StringUtils.isBlank(errorCode) && EXPECTED_REDIRECT_CODES.contains(errorCode); } private Event continueToUsernamePasswordLogin() { diff --git a/src/main/resources/templates/casAccountDisabledView.html b/src/main/resources/templates/casAccountDisabledView.html index fc4cc481..42562bc4 100644 --- a/src/main/resources/templates/casAccountDisabledView.html +++ b/src/main/resources/templates/casAccountDisabledView.html @@ -33,7 +33,7 @@


-
+
diff --git a/src/main/resources/templates/casInstitutionSsoFailedView.html b/src/main/resources/templates/casInstitutionSsoFailedView.html index 1b715e36..e2071a1b 100644 --- a/src/main/resources/templates/casInstitutionSsoFailedView.html +++ b/src/main/resources/templates/casInstitutionSsoFailedView.html @@ -27,7 +27,7 @@

-
+
diff --git a/src/main/resources/templates/casInvalidUserStatusView.html b/src/main/resources/templates/casInvalidUserStatusView.html index 1f1ad20b..41d5b641 100644 --- a/src/main/resources/templates/casInvalidUserStatusView.html +++ b/src/main/resources/templates/casInvalidUserStatusView.html @@ -33,7 +33,7 @@


-
+
diff --git a/src/main/resources/templates/casInvalidVerificationKeyView.html b/src/main/resources/templates/casInvalidVerificationKeyView.html index 853f6e0e..05e4f727 100644 --- a/src/main/resources/templates/casInvalidVerificationKeyView.html +++ b/src/main/resources/templates/casInvalidVerificationKeyView.html @@ -33,7 +33,7 @@


-
+
diff --git a/src/main/resources/templates/casLogoutView.html b/src/main/resources/templates/casLogoutView.html index d92ce3ba..0bbc1de8 100644 --- a/src/main/resources/templates/casLogoutView.html +++ b/src/main/resources/templates/casLogoutView.html @@ -35,7 +35,7 @@


- +
diff --git a/src/main/resources/templates/casServiceErrorView.html b/src/main/resources/templates/casServiceErrorView.html index 90bb4163..6ad422a7 100644 --- a/src/main/resources/templates/casServiceErrorView.html +++ b/src/main/resources/templates/casServiceErrorView.html @@ -27,7 +27,7 @@

-
+
diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index 2c3e9491..ff828987 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -27,7 +27,7 @@

-
+
diff --git a/src/main/resources/templates/error/401.html b/src/main/resources/templates/error/401.html index 46da1ccf..e6ee834c 100644 --- a/src/main/resources/templates/error/401.html +++ b/src/main/resources/templates/error/401.html @@ -35,7 +35,7 @@

- +
diff --git a/src/main/resources/templates/error/403.html b/src/main/resources/templates/error/403.html index cc0a4cf1..fa8cc7ed 100644 --- a/src/main/resources/templates/error/403.html +++ b/src/main/resources/templates/error/403.html @@ -35,7 +35,7 @@

- +
diff --git a/src/main/resources/templates/error/404.html b/src/main/resources/templates/error/404.html index 69a48853..3c1b4b33 100644 --- a/src/main/resources/templates/error/404.html +++ b/src/main/resources/templates/error/404.html @@ -35,7 +35,7 @@

- +
diff --git a/src/main/resources/templates/error/405.html b/src/main/resources/templates/error/405.html index 990fb844..56202180 100644 --- a/src/main/resources/templates/error/405.html +++ b/src/main/resources/templates/error/405.html @@ -35,7 +35,7 @@

- +
diff --git a/src/main/resources/templates/error/423.html b/src/main/resources/templates/error/423.html index beeff20e..ca5de1c9 100644 --- a/src/main/resources/templates/error/423.html +++ b/src/main/resources/templates/error/423.html @@ -35,7 +35,7 @@

- +
diff --git a/src/main/resources/templates/fragments/headerflowless.html b/src/main/resources/templates/fragments/headerflowless.html index d082d61a..3120b477 100644 --- a/src/main/resources/templates/fragments/headerflowless.html +++ b/src/main/resources/templates/fragments/headerflowless.html @@ -20,7 +20,7 @@
- + OSF CAS From d2783fe337a78a6e8830b35188d91e8cd4e09571 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Feb 2021 13:33:08 -0500 Subject: [PATCH 59/71] Service UI rework to support branded sign-in * OSF branded services use full banner without name * Custom branded services use square logo with name, which is similar to the banner design for the instn SSO page. The only difference is: custom branded service names wraps on narrow screens while the instn SSO one hides optional prefix. * In addition, redesigned the default banner for OSF preprints and OSF registries so they look better after rework. * Finally, added all logos for both stagings and the production custom branded preprints. --- .../local/casarxiv-203948234207241.json | 36 ++++++++++++++++++ src/main/resources/static/css/cas.css | 31 ++++++++++++++- .../branded/preprints-africarxiv-logo.png | Bin 0 -> 8571 bytes .../images/branded/preprints-agrixiv-logo.png | Bin 0 -> 998 bytes .../branded/preprints-arabixiv-logo.png | Bin 0 -> 5643 bytes .../branded/preprints-banglarxiv-logo.png | Bin 0 -> 4086 bytes .../branded/preprints-biohackrxiv-logo.png | Bin 0 -> 2828 bytes .../images/branded/preprints-bitss-logo.png | Bin 0 -> 20748 bytes .../branded/preprints-bodoarxiv-logo.png | Bin 0 -> 10014 bytes .../branded/preprints-casarxiv-logo.png | Bin 0 -> 15454 bytes .../branded/preprints-eartharxiv-logo.png | Bin 0 -> 2248 bytes .../branded/preprints-ecoevorxiv-logo.png | Bin 0 -> 3239 bytes .../branded/preprints-ecsarxiv-logo.png | Bin 0 -> 1475 bytes .../images/branded/preprints-edarxiv-logo.png | Bin 0 -> 3218 bytes .../images/branded/preprints-engrxiv-logo.png | Bin 0 -> 3478 bytes .../preprints-experimentalprotocols-logo.png | Bin 0 -> 11303 bytes .../branded/preprints-focusarchive-logo.png | Bin 0 -> 4847 bytes .../images/branded/preprints-frenxiv-logo.png | Bin 0 -> 1135 bytes .../images/branded/preprints-hsrxiv-logo.png | Bin 0 -> 5878 bytes .../images/branded/preprints-inarxiv-logo.png | Bin 0 -> 8404 bytes .../branded/preprints-indiarxiv-logo.png | Bin 0 -> 66225 bytes .../branded/preprints-lawarxiv-logo.png | Bin 0 -> 5292 bytes .../images/branded/preprints-lissa-logo.png | Bin 0 -> 4654 bytes .../branded/preprints-livedata-logo.png | Bin 0 -> 1063 bytes .../images/branded/preprints-marxiv-logo.png | Bin 0 -> 1721 bytes .../branded/preprints-medarxiv-logo.png | Bin 0 -> 4321 bytes .../branded/preprints-mediarxiv-logo.png | Bin 0 -> 4069 bytes .../branded/preprints-metaarxiv-logo.png | Bin 0 -> 14025 bytes .../branded/preprints-mindrxiv-logo.png | Bin 0 -> 2358 bytes .../branded/preprints-nutrixiv-logo.png | Bin 0 -> 4683 bytes .../branded/preprints-paleorxiv-logo.png | Bin 0 -> 4157 bytes .../branded/preprints-psyarxiv-logo.png | Bin 0 -> 4810 bytes .../images/branded/preprints-scielo-logo.png | Bin 0 -> 4291 bytes .../branded/preprints-socarxiv-logo.png | Bin 0 -> 9258 bytes .../branded/preprints-sportrxiv-logo.png | Bin 0 -> 1205 bytes .../branded/preprints-thesiscommons-logo.png | Bin 0 -> 4658 bytes .../static/images/osf-preprints-banner.png | Bin 19967 -> 12920 bytes .../static/images/osf-registries-banner.png | Bin 21349 -> 10787 bytes .../templates/fragments/serviceui.html | 18 +++++++-- 39 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 etc/cas/services/local/casarxiv-203948234207241.json create mode 100644 src/main/resources/static/images/branded/preprints-africarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-agrixiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-arabixiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-banglarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-biohackrxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-bitss-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-bodoarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-casarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-eartharxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-ecoevorxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-ecsarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-edarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-engrxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-experimentalprotocols-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-focusarchive-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-frenxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-hsrxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-inarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-indiarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-lawarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-lissa-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-livedata-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-marxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-medarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-mediarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-metaarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-mindrxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-nutrixiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-paleorxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-psyarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-scielo-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-socarxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-sportrxiv-logo.png create mode 100644 src/main/resources/static/images/branded/preprints-thesiscommons-logo.png diff --git a/etc/cas/services/local/casarxiv-203948234207241.json b/etc/cas/services/local/casarxiv-203948234207241.json new file mode 100644 index 00000000..9232feec --- /dev/null +++ b/etc/cas/services/local/casarxiv-203948234207241.json @@ -0,0 +1,36 @@ +{ + "@class": "org.apereo.cas.services.RegexRegisteredService", + "serviceId" : "^https?://(localhost|127\\.0\\.0\\.1):5000/(login|logout)/?\\?next=https?(%3A|:)(%2F|/)(%2F|/)((local\\.casarxiv\\.org(%3A|:)4200)|((localhost|127\\.0\\.0\\.1)(%3A|:)5000(%2F|/)preprints(%2F|/)casarxiv))($|%2F|/).*", + "name" : "CasArxiv Preprints", + "description" : "", + "id" : 203948234207241, + "evaluationOrder": 10, + "logo" : "/images/branded/preprints-casarxiv-logo.png", + "attributeReleasePolicy": { + "@class": "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy", + "allowedAttributes": [ + "java.util.ArrayList", + [ + "givenName", + "familyName", + "username" + ] + ] + }, + "accessStrategy": { + "@class": "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy", + "delegatedAuthenticationPolicy": { + "@class": "org.apereo.cas.services.DefaultRegisteredServiceDelegatedAuthenticationPolicy", + "allowedProviders": [ + "java.util.ArrayList", + [ + "cord", + "fakecas", + "okstate", + "orcid" + ] + ], + "permitUndefined": false + } + } +} diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index 9b4a6b3b..ce73f61a 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -798,8 +798,9 @@ body { max-width: 360px; } -.service-ui .service-ui-info { - display: none; +.service-ui .service-ui-logo-branded { + max-height: 48px; + max-width: 360px; } .service-ui .osf-shield-with-name { @@ -807,15 +808,29 @@ body { padding-bottom: 1rem; } +.osf-shield-with-name-branded { + width: 1px; +} + .osf-shield-with-name .service-ui-logo { padding-right: 0.5rem; } +.osf-shield-with-name .service-ui-logo-branded { + padding-right: 1rem; +} + .osf-shield-with-name .service-ui-name { font-size: 2.25rem; font-weight: bold; } +.osf-shield-with-name .service-ui-name-branded { + font-size: 2rem; + font-weight: normal; + white-space: nowrap; +} + .text-with-mdi, .text-without-mdi { font-size: 1rem; @@ -1119,6 +1134,10 @@ body { .osf-shield-with-name .service-ui-name { font-size: 2rem; } + + .osf-shield-with-name .service-ui-name-branded { + font-size: 1.75rem; + } } @media all and (max-width: 511.99px) { @@ -1147,6 +1166,10 @@ body { .form-button-inline .delegation-button-label { font-size: 1rem; } + + .osf-shield-with-name .service-ui-name-branded { + white-space: normal; + } } @media all and (max-width: 399.99px) { @@ -1163,6 +1186,10 @@ body { font-size: 1.75rem; } + .osf-shield-with-name .service-ui-name-branded { + font-size: 1.5rem; + } + .login-section .mdi-before-text, .login-error-card .mdi-before-text { display: none; diff --git a/src/main/resources/static/images/branded/preprints-africarxiv-logo.png b/src/main/resources/static/images/branded/preprints-africarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..667c18f1bb7fe5754e5e625c1db1acbbcedc935a GIT binary patch literal 8571 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-arabixiv-logo.png b/src/main/resources/static/images/branded/preprints-arabixiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9e01641380431b97b60078c79856a881e1eed9b1 GIT binary patch literal 5643 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-banglarxiv-logo.png b/src/main/resources/static/images/branded/preprints-banglarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b73d3cb8a7f08cf2017d07a6ecd5fee61699e60c GIT binary patch literal 4086 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 ccIZ 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-ecsarxiv-logo.png b/src/main/resources/static/images/branded/preprints-ecsarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..248db7e5dd9d566828d6e70e2e91cbf1017cd35e GIT binary patch literal 1475 zcmai!eLT|%0LGco^0NIVc{y$SEi!4!Tcy10w;7{EqA-c!4u_k!I>lr&Z_UlhU5NNt zR#IN(yd~_4kwfJ=qA72^nD~T{6wZCF|L^m8p6~Pg_5Ar{9e1N?sD7uaprD}P;!HiU znIZogp|Z*7iQl{w6qGNyP|02iiZlH#iV7g0P&ylMA$we!3U`%~Z&DBxE=c_bU?&_; z`41cbk3fF|7eUShxQNfPiOymn+?!*@FR73EP#-0WkTpbo)2Wvm4t9&(E}?>9A~u;< zr7CeD*pZbN{NFfTELCfE6rhT>Fe0_94r!T94@awW99CrIyV|WrI+chI68FV{pFp&6 z;Zd-s20N@SuU|fZ4J5YxVLd`NsYE^a{wo_-qht{97HXa}<~s^VrfkWyMEE!ZPN6mQS=TQ%ZfDe{JT|*kX{3e*NQ6gBBG-LA7W{gS%_CX{zeX zmwteTy1!hj3aIvl4QKpdQs`00SHq78m`~A#c8SAg4DD86AXsMQ#N1}sZj_nf znGo=4+(wYrcjXQV7*rzD>(bIwR;${twJCoz<(@IM*fDjWfLahdOG z`>KKck3D#)yMT6l8H+K9UwwA27oX>`p>Gr8zOmk3&dNU2R6!=T=P|6$8Q$gi)Wt5+ zy0Df0v?F<}&cQg%8E!fn0uQHod3MLoM0i;;E7mXzGxB$JJ|m9w8;w}%$+@A>_;@D^ zj2cmp4J?WI`%?o8`Uxg}#>)j*l7YUed{inaBoGrg+NNjP3khIV($i(o}r}~ z0JFnka=E-#QcS<27Xq@tX-k@ELzl3QZmhIhw1jCO^qMx8!I686j6AR?$H*YPVS`S5$LMSpoN5z4s_>{29y5)wi67 zb8PIDT++*(!<@&?BUjtRx^D@Gp5PiP4jr6S8P9ggEEN-@a`%l%>@o~V7} z3&Jo%^fStB46nIGKXdKP)xIgcwK}CzLV&P|@2IM{eAYmq+k_P7-)Uv5)FLK? z<^8`Kra(@Rmm+QUV5an}p_)7Rf}|VdvEmE=3pF8Z9LybW6WwCxK#>QNE{j67JA~Dn zoiR#-bBI$o6O^_^u$Ts`e4;WG#xhn8H3#BP z1shF+S@SSrHay4hDDTF8Vo#=TZ9`(My*13O| zLsC*IZiD$8xpnhVb-7E-HH3H5R?Xg6a!7;9P7ns8LMaFYps4u&eMv*T?wAL%AdRy* OrQqV|My;X*a{d88W`#@u literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-edarxiv-logo.png b/src/main/resources/static/images/branded/preprints-edarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..66807d3c95d7c84695fb5c158e0affea3476bb2c GIT binary patch literal 3218 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 Ef@>cn$p8QV literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-engrxiv-logo.png b/src/main/resources/static/images/branded/preprints-engrxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a5f5008685bf40e6de0477804f828ac3b38cca94 GIT binary patch literal 3478 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 Ef?OQb`Tzg` literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-experimentalprotocols-logo.png b/src/main/resources/static/images/branded/preprints-experimentalprotocols-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..036ffee0ae294d0e9b7d35ff4db53ae3182b386c GIT binary patch literal 11303 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

h%*^LbwY+?N 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-frenxiv-logo.png b/src/main/resources/static/images/branded/preprints-frenxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b9657a740cb179fc0b7499311b39c4422eec953d GIT binary patch literal 1135 zcmeAS@N?(olHy`uVBq!ia0vp^DIm=V~+M}np zNn0DJCQ49nf}$cs@dXnTPad9XX=xxgJ3ITxkt3f!fBts+_P>As-frFu)D<2ce&ND} zo}QlV+qb`X@xsy3@s5wr_XiI?ojNsp_Ut=%?z~>U{KNkJYHDit;^Tk5diCeamlv~U zeYtw|S#R&_d-qnZTnRMlVSfIJMT=@`YJPtC^5xQ{m8q!@i;5tw;tXn80JPh#B*-tA zVfTL}mow#eX9~IiJ!Jgv>07&Kk{{I0=v;WLvZJ-gr5FTB3hOl;17-oFKg%{e(e0!w@&^aPHCi3=W?B$&yk z*dEbmBDh3qVw-@Ym8774k*UIo&`(E>%sTgu`{xer6E%%Bn`-1DA4Zud-PdhU6Hu(M z+<2=)kfreV#Gh6*tMff1BVFgWpH(>etuST#jr(m4c@E1y@--+WJu=+GwN3spYn=P7 z6^c`4F?h@t)Xa7OnsDyFqg}&>D-9e{?$d&JiuCD zXZ`Oh5VGm#+o|h61r!Oh9r|!)nfuDi4nI3tIu>_6d+_di{rWfaEbr)^GK-%7b^Wnl z&5t|MPTarkn4*)k%U+0K<(`QFlXg|_{XgrW>&iE(^+j7wZ;ZBSnQ-|*=rYyw@rUlT zYBa7`RmYQfESQ7UW95Z;w(nnXE(!F#;wCE<%D87$okZ3Gp<|Ea4UAN-aNMt}W)k7q zcCBlv0B6#+G@oV$2gUVIO;cF6W;HUdUKQ1Akh)ue1^zK1M@?mrczPD%t` z(plx|kXp3wtmLJ2VWNG(tK=A14$Sgwn}7D@>&m+Bne zQwuGeEd=j7)O4y?wzsUjeCzye=VYCid@g6TC+?kdR=_Vp@CB2R(!LJ!3A^ShD&L54 zSi&rva`1BboezzS5`8msxT9NcdHZveMNPdsg`-*1EGj~kYh}j{z7OK{i+1z9P)c)= zJ#tFzv~lHi+jOz}-!ubuML0`;o8+n2bAk1^rr`dsZAoX3Wfe+F#L2O@i}w4d%vzK6 znZ-fy}4PM!BK+i@Rn)EDh@Ya ze(^86vi*sp^2Uo_;val|#(nn~`v%+eloST(bm4#VPxK4Ej-F96anrsAfqE&&^hrJf znk5BOxf~9Z-}HCc$02cGfvvr(##dqKMJDWlj2xe3TCPf8TxQgub4!I`=5%c#4~0e+ gp%ax?m!8-zEx@yRXQJ7KouFdC)78&qol`;+04QJ)i~s-t literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-hsrxiv-logo.png b/src/main/resources/static/images/branded/preprints-hsrxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9b63e7078f39ac2c87594baa25973dba83db5a8b GIT binary patch literal 5878 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 qXA))o|I!mZ>)CeOUsC>Gp#K1)P0_Y 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

n%NFX;XY| z&W?|)5#JrIv_u2ak)q22StJ?979^d6C&4YVF&=yYm&S*rqN(8kP_jvaS%iut5H+i? zTqetyndsuF*e3EiFqYwas@x(aVHuCZe-Z-uCU*E;0IPTO!0Lh31FHvC53K*uqX$+G ktR7fBuzFzi!0H|U1}BewT3&UQ>;M1&07*qoM6N<$f)w}RrvLx| literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-livedata-logo.png b/src/main/resources/static/images/branded/preprints-livedata-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2558d5159d9c54a0fdd4e9e0dfa21858fb94c35e GIT binary patch literal 1063 zcmV+?1laqDP)_{r~^}{r&y@{r&g%_x$|){r&y^{{H>_{rvp=WZSO>0000G zbW%=J|3ENckig*opnxE7u<+1OQJoFz000A)Nkl%*Ycw1#j1g!?F)3zJsuBt!}e=JHG@G%ht`j7`x=T^S$z!kM!l#4z)ZbcN%% zL5Roz{>*^-`F*C|6~+(EmUi*%V7==ilJ`10^qcPy3_bchsaJyZC>BA~et5e{|M`Ev zeztcY1wd#lq1b1gi3va`Y|k2f(qOne@P$Hh00->=qbhHt=PzR92Iocn@`|Nyq87mS zp>43M6}TzR_*@BsKjr+52qbC2tXevFgNRpUND6@9-F0Y9XzWu&JKl;_JdmOlS)Ra? z$ZNyFd12sqWByVzGA|sOJL1bV%TLHM!)LA`{=VfNl0^wWjToghBk)%4NDiykzA(-+ z2JKVVTjI=^h ztM86g%}G{+{Jd{;zd#ab?E?84Tf(_)6ctN6XD8|uH}0S$8%5=HoLn$!s@j-?l57+e z_nN>U-cH5J z3}7ThxyH$@0>R8JB6)C4sI-G;UgNp){UQNL)+R zw;a5dx?U6J5){;g7i!y_zo53gQls}S6=O`&R7iQ?uEBG6Cf4tMJaC8Q;k!8NcZ#0B h8}$);JGW3tDXZJK8P?3wqx-}64td--P0nIoe4ZABPb z8Ny&Ngb$TW2j7VK4c7yHt9xV=45rgY`;p7t;y;l0-9e;?? zs*aKIu0*bu$AlySpzUKH5{KJ=6sQ=^A>5`gj3*zYxwu7P_a$u*7rLFR-duBaWB%E7 z0wIRY#YE@Y3+n6-D*#5(r55aqW+62z{d2wj(gN6pL1AUv7$-fvld#c=E+T9o`EI{8fuUfQ9j8hQKnVzqd~=L_L^iy}d2&yc?Z3c=*96J|2|O^6 z2@Hh5w4J}^zm|adp9$Y|(58XY`ClvA1o=HEkP7I2J77dKl86>V8aW3kQ)$$4j!Z2i zw$V63JOqyUo2C8|bLNp+uF*iBk(P&$91W!5L24orua*HF54IW-wyB9iNQ{=FWk|V- zqvFuoh;pb6&1)0Wcr?6FO_R3?ks7>8jOGy`8Am;wm(vJ?Eim&TlNbke{)F@-T|`UR z=Lbg_Xbn3egSKyZ@bV*1u{Foz3L@t}qEoHiwQqSLeQBPe{bn4k+ z?{N{mlTm{%VJQpi5`W5}xQ3cGLM{mh3Tsm-4m#4^xAJe3-qcR%SGVg|6ZW?o#!9Z}ftj zgk6boDNovh%=1y>aNvt zErmLm3&*p=^E>a{Vcr~GK6`am_a2V-p=xY2FZ`K(6k%)u_7&B(Q`yt%5hQW$?l5s( z?VGK*%EP=o>G4j|V|TxO%xz2pUGTy^NV#Ez8}VWim_eDS;4=n`4U{uHr%YoDqhF^- z*+#3dC~VjLd4Q3Y`&6(@6=Sa4*LfB9nqsXi2KmZP{$3_1%8Y!w0*m^ki(kuQT6A}G zjxtezIvRMkUH#|)!ba*PBBu+ zrQ-B6cI*qX(c9S9&mIWd_mDpD_y*pP(t&|xQ8;EWOGjgJ4+#k$pS;|NF$i9|woaaO z+jC~o$>$pfSmSnoarK|iB}y7QW;ET->9fTxY17YaD@~*-bX@k?%@YakHOk)PHwGUI z-%|U3?nxWT$!V=Z=}KkRr5CRJoXIw-n;gq<99)-sS&*DgO_UTombEbk>F^9aQ{9UX zM`HDgGF7E-<|?O1B>h7civlNy>q5(%dE|ybuRF5}9YrwJH#GS!5f>9;%%x10_@>Pj zG>{9VPmUtZ&($$*nj;6&B5D6ev+uCG-vxqsGp)D{6v8pNxg$Y3Pve#8~q?WBm@pe;`| zsaXqbmX4b@H?w8dc-gKV|2bmc693xb6v8?vMws&oewQTYsUAj$;=0o3C6Uwoe$ndj##Pi&f@_jfGQy|3 zIWM9tK5}q?qKEM77)sB2MLB<1kv|Tfnz|4h<*aUjcZb%VptCiish#q>QCad0ko#+C xd}7LkCTM8t{oqi{r$<6zz~^gVxv(5u1K7)eCVo=BL*)F6=i}{1uGzv#`3H`f7M=hA literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-medarxiv-logo.png b/src/main/resources/static/images/branded/preprints-medarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b88a13d4f1497508bde6d10f0fd457a4ecf0e365 GIT binary patch literal 4321 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 GBmM*6K2AUY literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-mediarxiv-logo.png b/src/main/resources/static/images/branded/preprints-mediarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..67879765221189ce772ddecaedcd28b61620d2ee GIT binary patch literal 4069 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-nutrixiv-logo.png b/src/main/resources/static/images/branded/preprints-nutrixiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..94f0fe65fe316fb0d180fac9ff76c9548781be5a GIT binary patch literal 4683 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 Hu0mjfJKH1c literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-psyarxiv-logo.png b/src/main/resources/static/images/branded/preprints-psyarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cd34b46b473c6e6da3224e3efc32e759dd0a0339 GIT binary patch literal 4810 zcmV;*5;g6KP)@W%yi7m%*@Qp%*@QpoWzpDPz*QBoZkPl9!FKZ{yR?NT;ja; zP4(6*8htf0J3Bk0MEn%=zit1vffeRpZQ8VH2!qw#-QC#KRaf6t-!RBj*RZLreMn1I zM`?M%{wHS7-79a!A-T&A93(m@XXydibN8%#>;)xU-Q7bJtoC(<>Eq`WMknV)CFDmZ z4hrRZZe0>HtK{lC6kkIZtPRCk2|H&*#=A$&GGh{jtk@*BI_U>k+OB|S`R}wwB(u$m zN+`Yg{-F+5X54bbNkhKCZLehMJ&sPT0SQ=Yn;RBjW$m;=B+DrU`m37g63GfDHPp392dhtH zLb@{A?XXcpU9$A|uQ#-|CP9HIfMg|x6<9vTTS$5$<1LdF_FijblI*o6&XvbDy(lXvUB-^)f8yM6i>&dp+2sT) z>_@{bz(U0)%}q0m%!7`q%gk!8uCDs-hm2MGx{QC(@6pX<_7+@qee;IGwu;K?A5-1) zcX1ipDb(z}*WB2&ZbMr|MfrOlq#1u!;EqTfhLVN$Aup+hk$uAHoz2baDcalfFS#R&h!CGQj$!0t@IzdBFPMV=q`P z%K=uHJEgjxWrLN~16BuMU3!%htdxidz_KOF1J*A@vb>(Hr)NJUeypYZ-b?)VT-1Q0+z0Z<}fnw8d%4j+GDdegJty*tlBNX zGBukuTwI5vPm2?KH+#(JRFdCY%2@vO2efz!Ktm>QZIM^CH%ZjllJ>eU5&?F16cx;!kJ?>?FPM(}o z{PL@S1&DOwqx*t|pT*uO^T5&k;}oVlP3zXni6t+;rcRu`&>ldBiR)lbcR+;K4kD#* zy(8x|u32kMP;(&ntQA11JotMau))e$xsS{EuRC#>HDlqAhOy?x+qyeC*wxk2l6T%E zsUDQ=d8IX+=7wUnkOi^v9kq3G8aA6A$oyZNCRuxcBXJ0j%H01*oC&XWH!anVsM>)V z-GdM77(66{myByg&%R(Uu`_4RJ>xtKkP@GpZ});#Sj55T8Z*Roci-PqS|*3L*VJYo zf0|Oy$@6Tn)%>jC5u!mHh_3u$N}BNxl+k{Y?zXnZ)oUs~{T!(gusZ7N`C0wLkFDh! z?R&IW*A!fFEm%tc$G&X%ukHv~e({o=S8gW#d1$OM>$!)ogxQt3U*2m z@xKlf-g853bw_Nly*wc?KRg3b%-L#=l3_L3oNE5>-Kh@QAQPLMI!rgU{ zhJVG`K{)~9->6`cIdzBQaUCR5+T&*xi=Txi zGA1~W51i{@#e^eR!DleYx`UbJBeJQAmao?EYpPAa+X?x9~au!@9ziU!;xl5DaZBt80GpSCmtUqQbP z>hB(z%r+-_$V*mtYirYYsSTff)9~eY4PSVv@yqX>M33H~-YUpMKr8u247w zuT7m@KXr8vF2Tbl8eXu5SiRbi6)S*>P}}y7=8T-?)bwUEv)Pp~DAWX{rNcu4H_%J$%0dP$sKMb}%AoPL(w_IqXU z;x)oU`Q49s!Mg00g6Kqy10c%5`gMZmq*u=MUG(s(@}m;7=k4VK)=Do}9Q5-OkL>{~ zdrPqL66KMqg2{|PzyEn<&46gHBt<&ytIriH9 zboL(U4ob2l!WkR|2wL?aJ`)UB8drg@tTSVicDlB!Z;}nW zi=V7Q$pIuX5(IZ7UTD09PO|*hp%Q)fW!ISrG60e#>V_bzrEg>Wnp^HH|L~LImtM^~ z=OV?xFDLQNSZYEs5hW`8GWR`v!(&etKK*RYDQCNk|FB}f={~BrRW>VVyttysJauwp zF_*siPT5=UuD$gx^B>d9zfA){b_E72_|Z@&$pEIRkFA{%*4@?)4=y7T9*`i#!++x_ zW2^o#MG}Y$F26?4)*K);)bh5b&QCM`kiKA75*>tH68_RxsC8+QN6hWw?1KkHvXp*J zAOnR|=(ehA`@1abAAH10@hdzT?M;2+5e1(?g(!x-vU=IZHQP#y=1%NgwTOXzXt9P>=e;%aZc0 zY>E@#P`M78fJ@c|gI&}54f4X)+;kf~q?f0!+=s$Zh2YwC9E>C?gXQ082(`^}ij|aK z7C!x);;*Bl;zp6fEkQdSL`7~la?L+KP|P&e)cGh|)ZH42h+SM>Dr(o^`v z(oK&(0OImAUU>Vzz8e453qMYHf@o z_X4b(6VD)3Qxbo(jyQpyrnT$%$q10XWDl3I1DSZ*=|Z8FEK|slZ&dvJOY(T7ufO?& zVUTF5tV2iV>g#S2z2M-`OP0nG^2^J^Y`KhoR(=12Tx7$;k5j3DsZ#8{`F5(LB#sO) zMu!G0O~l3{R@PCs29)N?}#5nB_-7P+M6(^jvQ@!fCC7Y)UY93DB7A^@5Cm^ z*oVg;#cWxJ9fza?Xn^Fp5UZgK*yub-?XX2Tj#sSSQ11=OyWrA}hDLg7-Rb7PW?(h2 z5xn-$tD%0K?W8R0&+eqZio2 zvMOVbgK!R+Qlu~1O)8t{%sS*)sl*R#nBbs;N<*6c8wrTIb z8tMYCzd#sbzKU33q=Xy1n-l?MyEwaM4u1!A5EjA0|A^KPHPrcpF&N+*3Mrn-27A4) z)=F33D={X(iM%#VFhexm(S0k_3PcbkoEI5%GWS1%Q3e%oCoD~Iyw$RI-v=x;PK|X6 z|G?QSvGEho{hHJ?`Ou<#Pr@`Nxr}ihux9o?y$_*eAwemQiaHt~!VrUtAoex?;wv$z z?5fYn#TSEh@wNs^vYg(-PRd`;JO9$ImR8T8+#wEN{zW}%sII0duLfV==7##UoQ18- z;M*$I`K@K;?%69T45KsEv!!kReY%*fj=FksbEO=`9<2w;z$5a=?|)~c^?aj*0lLne zA%4TgPd<~1V+qa-ke{VpYqGLdW$(PtiQ=NN$g=Ri~uYxXhX~2e~XJhFB|^QFDx^%6cSDtbi3lHPr0`B?}aYayoui z#xDB<*7^q?5i{SAUx437v5|Q2AyC6D*>Z^0|Gc&{`zR4|&&=!aM-~SSR z`fsze(^P;##jP+&!VL|@&F?28)haIfpBd)Aq3Mc=zfS`lL`;q(n5*P}oGt&M1`Cft zMT%n3L?l}L;p`(%^x(3RH%IA*T$7J~{V0Wf|C|mpuo_sh`Vc8~ij`Z$>X=j7syt#< zQ$u~Z;wF9xVP&|q30TD~EP3?}FN@!PCnFJiLl2g$W>1`x>iOoG{Hmxn|Fpc7Yd&6;F$Z1u0$#cM@)#DN3}(&*0%X zh6y7pdaQ{tS~~?$ZqYZ%(!UeF`BL$4?)vSdp5b_$AjK|7@G`;c?^D?;rE9PR|8h*I zCen_p@Tk9@#QWi;@l#)h(1&vh>F{F#i(tI@*Qvmv9Urn7yxb0%A{>JJ>JE^|7YFdl zoqnm4jlQoN>PR`g2U(pLr>?iG6&e0|PSKd_`%;*0;PuocK!N=F<*MH!gWOB(rbb)k zl;CWOC6{L3n_Lei#FwveM= zNIJdeI@|Ux|EEX~4fp8T**>Y=ZR?BNQCDg$0Vb69pyb>b(C%_*!TFX z!waA>lj5--ba|VZU7VMKbWBKX>PwJ|!^@7Ec zQCDq!XH`vSbuGP}KRd}yVF2oGX%(>e^JN`n707>|s59vP&fqQr4{*iD!iMUf>>Ij& kg>KuwZD4H!Ymoo_AA$hA*8oq`2><{907*qoM6N<$g8x5!cK`qY literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-scielo-logo.png b/src/main/resources/static/images/branded/preprints-scielo-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..46e1bbee535ae9c124f740bf3aa1ada8c1df11d1 GIT binary patch literal 4291 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-socarxiv-logo.png b/src/main/resources/static/images/branded/preprints-socarxiv-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6b22136e555bdbea1715fcfbb372a6d08ef87690 GIT binary patch literal 9258 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 TXS+YO00000NkvXXu0mjfo+Li7 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/branded/preprints-thesiscommons-logo.png b/src/main/resources/static/images/branded/preprints-thesiscommons-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b8f2955a1e00ff900ddf556729f3dca8dff45d0b GIT binary patch literal 4658 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/osf-preprints-banner.png b/src/main/resources/static/images/osf-preprints-banner.png index b56823bcd2b5d52e5b31e6e80d7c7cb1f7ca13d5..b00f14fe623af80ad97aed0460877b0f07c1a539 100644 GIT binary patch literal 12920 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 TgPh{xzn-d!nhJGt@525cHOXO! literal 19967 zcmZr%Wl$Vlu*C^3!CjUR9D=*U0>Km9U4y&3!?L)$1-Ibt?(XjH{`lVe`>JkDZSCBh z+jF~n`kd3VVG44RD2N1z5D*Y3Qa~{!2nfjh&(Dcp;69JBVXxE>5VHMJV#2>%Ay3y} zwbBQknJ&ozQ7s@C7d5@J3^x-T1dzqCds$-P`8jt{$y#&EHz$`U8D$q2nYJiPQA7uy z9`*4cPMO7^AbQT5SHTUzDjDa4HSh5k=4WO?j-N&-_&`pa=VPFs8nflnG&++vMJ4cu`ip71|4v!#`V+_>w|O}_r~s`5$(8@5uU#~#;Yik z*&1qSXz1!)8GW9H)u{^ts)+nl_CFRHFf&$BnLp~>9;%_YL~1poV`X)ar!vDhbapo! z4aFc*YgJ1$w${hBio#(i4J)OD;_6L{APm zB?=9PjE6u^LO)W|Y`4R3ihV3-wOHjyzcxO=kxTC>7|N0eQ!b(6{`_a_w?nfimlv4b z-4Um1KKUMnn1_vWwf*OefL`q9qE5ANn#r)oaS5pfKW3(*6_wVrVfab5*|ahEi-2qA z5AO0nd3oG&$sr{r3o0@mSaM zqqnzltUrGIlgK4NE(WJMoR8t&0(g_H73NDW7F zbn{NE_)Ab^>AWtgdQnwdVGpITS7^C)V=g}Y_8dV+OUuO!9UHj5RA-wzt5}RHEKn++ zC7|B<-!=q|wnud_;tUl#@6La+{Q#cWo02o3m$W{TCq`TghP zMd0lhglbXAeGfnpuP;7LPlycPy`13>`$onIlDr1~T`}z@+k|~mvoreD?59@t<&+K; zc-_i{z=3|j*9sC{UL9qfLX{us@uBA@3zZvqdeayKF8N-)M|umBS^u{{Coqv%w@_Q& z&lj!x1=O4IjeKYox$Q20#}O7Rw^SVr+u^i&|LUeI<82K z4veB!Wm}`prMUBeW`{Dg2QG8=K9%gd=c6B_p7cE6q8H8N z$9o`<+Y=2O!IrT$9RPBuZxK)My~}98WccnJ9s*4nl^EXZpGi>;caR=Wwx-C3*9xEP z7e{ap%Ip?rU$LsB!=YdBQ$49qeh-lniIvqY3m~08SuQ1A!0v0(fPEqaS_$h#Z}@~; zey`RZ4&uUE+z$o@3l~06H?6AJIfY@}(qfc%FThP&oB0ar{iA3`kKpTP>3^mI+DrSl zd&dmOr)N>ZwtX29lFX5_e{aXS_RN~VWiAEq>Ki)hQuW$_M?M|c5-<8d%Sh6>5E6O$ z@W3HJZKe@Av-bGz-M1I8?{+iyYDL015#n>vF54FT<6`cXKtupyblDTL)h`jy%tnHM z;62u(d)|pY^owiX|5)a{eCJ|5#6v=cV<@FXI*Cawr_|+Rz-Fl@ga`t8D!@TNP~a?X z!e(E;MF1Kel|EkSygaZ`81Z>D!FSoRjoU&BBO~}t?Oiwk4h4FCE|}~xWDthJ9f+s_ z-3+brwdf!|54G3wVBo4_MF{h@&MjsvpCq~d3E&FNKxIa9h`O^~si&WVn@ld(reEiI z)v)I|K3u5Z%t1f@noy5&omzBZPH^2h-1bh3r$vx-kMUMB#<7A7H=lq$lqV5&Z6_!g z5vub80mjjkOjwsja+SwqG?{-|G7=A|td<B7nAeTf|#DfQU=pr=+cNv!xXQ5 zDO1zSn5HlOyQo}A$!+4SRLDRce1kAe0&H1nvOcwq)R1B!yy2hzv}Q%c9a)Wb25z53 z82&P@j*QSh0ci#34V?k5-W9ub-^26o^Du9J{!uv>>>g@U?oN-7&B*Xd#JZjdJtNbA ztptJ}WLQb}i$yJD0(@i$`P~Onx3_)tGA|XjLVdm#rAbX9U3$EFAirO9 z7ovl!%ey0-#@9fui~whq>@~MV+l+3!lZ`sEPWGh@v<05k(UKhMBlZtD#4F|937OWY zUZpj^KsE);wT)M&1ceFoqMm~Ifv;06W;Z#H?qo#11K+j|D7Uz7TAvUlw_gHAZyvo3 z9v@;@CPIj#22jo432cAOSVGitWWm^E7jUi3ZUye%91q*oYw+K+?IX>%@mW-gw(bY- zw0-oX0Dqul=hfBhE+2Umo!0npWYuoNa=R2%EPMDcMBMPEgGBss9OsC@=(&N7t_}4% z782nRA;l7x#J8Cgr9=Tt-t5v%5&;CvB2cSu1 zu}PPbX4|rk!AV&^I5J)DlNBnCP|Cg^dHhtiXUamq#nAGxwkBH%@A%7v z>1EkX<{|ZRwpq$^ep+y@)XDwz>cDK6V5Ls5jKUeq#Wl>fr<@mYEz~d{h-HaY#JzCX3B*}yQabLkdEeCK*oiN z2s#R*0W|N6nuX6|wMa4ucLzs#*+L%;9<5>yvr3*U%UmqHj-h z)g!KPJ-rN?&AW33*f*RbiHgA1fz^1wdfZ?N)`D#D3b7YcVehW`&TUylyH^R(OtB7w z?+OqRLHKa>2sB-v0Ec=reYWCjvy{cK+|0^pT}Xwiak=w;xw$ms1?uJRcnF6~w^GtE zEe`mYavN)M=(2nM=clGlxTG+mvc@#iOi_86(guRt`H=K7V~udP4rlC_I1#OxAt$`}^Dax_0;FQ`L1e)s4T@)ZE&y0T8`@Jcmte;t-BCRTT zTj9LEIBC@}wOtA4Du%#pm=!`QcfVSFRg1*f_>uqWaIrMRy0=yC%YKxk&L=Ud@uTIa{t+2@t*u>W zf$!e0V$DI9nD)jj2-~aXthY|b{z=-~yZv;u!&i0))y90ufl$6PVq=&uGc4_?^1?{# z0|NtxkL?S2bY#7?y16<#_^>50%&+~&OP{Y(VS0Kx@`3_6IJXt<^G3Y1N7_%W9`QTN z7(_oYWkPCd>OReNda0`+e}3@C980$8qW1!~%4+Z8>AsT|~vx!(H=VXF_eAW0o`F7U{a(ZvONK znUVnq6b`FI$9(}JF+t>*l&}Z(^Es0)y-NkXG(rQq)zO&9ssYm>=N0P))+#eHaFwkA z7^|*s?_^NZ*NH={hWlaM38f>FnAaJm>bux7o~FE55#)b+LPFSsH{ zdKPr6KAVqme0AJ=mpnSIt(eC~Yb!V3A{aZUbi9isU>M@s{y5$6%M?~xCRcXGVoiMA z%(U75u1SvbUP71o2vp7TD6L3$O|Muo=hSAL!=2u$l%XMwi{|14k>Z6A$cy?peY5f` zkN0nfJ3D44N&~{1Z=0;faCI2uaZ}|o+07~wRQ)3ZGaI?2TW%;q+ws7CRvGE09}6S} z?o_=wow>dat;tTu_r?Z!!}T=D&d&~}HTINOFb$I^)azp_s~ zE3mem9wv$3TQ-o(7`6f(%dqNN#nF0lp#7X6m0ReP5xHBg+PKTXO5^cb=Wz4{pfZ%*=(swlJbOn8)Zl%(2f`0eW0P?q=U08F+$b~fWk{EM6@>_y zA8uTaQx?$R=N0iKb=a^f-AqeMZ+`ObS9lic>g&;0?T^Otn-sO~-j;FSVkh=o>~d9J z>0LtE*x8}0NuD5d4Pc|0Pl<+&7 z{hu!WzI#A*lPe9g-KY<^4nHy1o~~5X)ap~R1pk>%$R@;|`pba><0*9e1dIf^_KU9~|nArcCb__Ju$dyr;ZR(feAbzI&o6#u?OatCY} z7p?!y)jfOtPmll@#hnc!OTcGdA~b!%WmbStZ-WH>-xZ{rdr7-gT^K^(7UPEjT%d zr$QX%;~zo^(r2Bc;GqbIa*pD>lJ0W4i$AerTq8JZ)h^0dqGKB~Q#^Cxj)rS?-JJJ8 zhM%8)p8BlyiZ_Qj0jYIVZC)h739{A~VoZmuVh8wZn|lM2m@C%cCe& zRlhh^ex6D?T#J0io18n?$UU0FUQTJSh)d9UitJl3mQ7!TS5v(@t({OAA1z3#pZ_+a zbGuKlqU+FA-n?p8w@VS85Ag0?RUoPQ$2Q*cnX$95x`WLVztd>82KRgRTS|v zdagQtZr^I;FG~gz$f@O&tnwdi>DRBlO#O?}(a0;Ua2G4})h#`A zmtumjj3_bOZASPA4?-2zTMOHM#e8r={^aqRdQ+X3TCrHyeJXOCy6_u;{y9f#^4_$G zQFQQoKwoQ#3Men*0;1W|N!niuJDZbB{5Uo4n9*Vx~`ZSxZk9@Lc=}C>rG_1~5MW^x#&rOCi z`cNwJu1Mp#PM);%Cb7P0#%L0yr=6@rS|YdnS3fhAl{T0%S$~|mbdRl>>T5<^H5ZD& z%NA8c%qi|_oOV$_+V7A;>OVTvh(0uOS!|4Dw!6;k?Cf5?PC>wt_Nic2E0N>oD*dn1 zq}C50sOG<|TB@rL8fE+d;`I92PZFsAp{V#X409oew=;%nt>b@_J51wozcopWd}B{rUygNtC$?MVr_q?IYcspATHR*k5?8=e^>X1cJp%r zhY}i!D(SG1+jM7#cZd72XQo2NCLg5sK6}=(qF66hVPI~L{W}0PqCT}YANLp4yRs(+ z);%7Sm2BKY&M*BmcW~IWphqaV-p6$u+|uBt2oDsi^|KD&;d)ywAc|L*VTR#A{50rh zmyC5{rp7g^u{|$jI#tB0_X+Z`EEAcOwQin0e<2m_af-fVpd(?QY}PCUjaMOCK8{9N zq^>#TH)Cnkcb|c`S81x=_N|jD{hnZM3hMBuuMDvui*Fg(d#lE&6FMYwuNYbFx4-nX z#mC=wV3dzr%m1a^&%FL_ejcnHrEMw3VUL&L#$GH;4&1GP$J)Nei60<=E8}H>Kaobx zX!={FV=fo!-w1>HPxdA;o@kTdZoLrbO(Kw7k9u2(j+y)fEsQ}t)#7rYMW2fYQx>2F z``j!hI*9N#@(n=9(XE)CrfKo6WX(#$9bEyER$Y6J+&`oekBv9klWlTAuc`n$?3JPkznzgm>e*=k>Di`?lVx)+WCeknM{+V&z-9g5N%n!4zVa^83V4h@izRP>xSh4jvLX(tz`2tI`& z&K1o61W}q^pWL;GU-dnV&BxKW^%{*hVdmw|CQL3_vsH-`YR|vs^_9bYo$BiXigt70 zX1;D=9xgMVIqa8BLY*ZrmCx)Hj!n;fb)FkOU|+zVyAqzV+DArPVz7T>_gO)Q@pq!; zVs^?t(Q1aH+1=a9sgaAS6E^ReR+;~OE1X#scP0ktdrLmBV4d!_`MPL90z^qD`4xYRL%P=c4-bVL=7+Swf`+=PlLo3Xay2VR7y1;G> zYkE6GKRW)QfP3Nk!kL0hSC!h|b5r5vt#I^KSzsiau>!AVTH5vEdg1LB|M8bP7(x`l zioC^z=98g#@5gu?7n{Y}&U|8_sFiKZ{8yjH5a&-YiQW|0U&p-ZR8wxiG!3?lcS}d- z_&ApByOOERzNnIi&`0-bH*tRUQu%H2u^VW@WYCmZVIvTLk(dTZ)ElZ0l_Y% z1RkdOci>i>kX~gJ2eZM%7nS+5FxDNDoQ7NYGT)1gBHXo$mWQ?szrM7G@rD6jd4}c) z6NY!xi+W_72z;N>yp#wuJjLo0p-=GCHe`p2Z1>z8C3ah+UXj7^gMn0yUPR2L#T|Ho zdL~$htmYyj#@oc%pW5w$@B=anrcELC;c(tvMmqFmbO@=_%1?lhquDNdyM*@O6_aXL z#eYIK26hCqP; z&cVGUe&~L{EqSPSUJrsT&va=>?06iYDl?Im*CUQ~do3^}e<}~Z71)2vaH&%j9*$sLMJVY?00M50DWw@X!1Z@D4rxuv0~zeMDI=dXjjKNjj&WGCz6q8H|H*UIU1 zUWIvWtR_9>dX>96@M|X&c_Az-4Z30;1ism4SXMUdwxugjY`DiL#R=R zM8=DFH(#l{U6bieRlz=6EgtHykWsUmZh+89zYE`8cKj{-nTrrwGom9gzkdDVC_{0 zX>wtk{z+b9J)~PF==(YwI(BxaMyzcMDzm3=rNj0)#!}UcOv5uf59_L`g3s;ymE{Yq z>QG$@D>7a;t>&Gngw+T7h7xC@ZwCPFtsxsvpP{BdhWh=qeMip9&V*`wcH_Y*8WIp z-_24l3oBWu=-=P0H&MBDM*7Dwk;Xbr|E4BWWA+&gQ(OuYHY*y+ZScqsWkKTSImYtH3O3UWxMdryU^64kk~_ii$Xd#EfCY|L<8#* zxk~IHp8LhBE?r|-zP7d&$xpmzbR-92!%R;bVM^IeIwryYcr}91x4!Q)D?S@Q?#TzC{GE}2)@?<$s-R+RA}svo!iZw!&?OUB;Y_F-20VI8PEgzsxEX)o2Psw55rYK6dj=A)#g^@p_ z@)VSj&^e08yTGjdGoRAYZQhLDxltyffg>>FG*N(cRylSni^t`Qw+@!Eep_EbLz@O) zRVRLzDSi7_sh>#n>BZu63*qU%7>F0pwXG7c90${`oyM^e_coX zyf7$eQKAP&L6@-GkYR93MK}9O5m(x z3R;Tcy2j~j15J#{JYoNEj;l5?-I8PK`P}Vc*i7yK)$)@6aS9rllN)Q7H*-Q`o=jJ# zvb4G;=K4n(4ntj9$s9Dj&M2kcq)V4X)_11~ikZ@ufuN zSKMq8Advt2WD@9YMk!ni$aKx}rk5{oPo2yDmgNcl0xnD`pY0Ec7$Uc9UKVK@YDmk7 zH9X563I7nR>jcz|(*R-ZJ(%0Z7Tq^W%WG>%D7xm;FalO&cpf;q@Je@Y7rl}qZ6Cck zXq$H>Q7vV%#j8NTVVmoQt3(V5e~r0Z_a5iKjuC_m%(oO!cI9eY9w`0*G9q{>573mp zWFM6FyiSkhTM_Op5_+=+Um-nE0yB@};wRwY2tpx5z$pZ{gxK7pF8t1X<#F0wiu1!4 zS8c1J#vGNNWKlb4a=WkYMCP%-uHGx?JL!(V=Q&P8_*87*aOCk2SH^$4&6zPrz=uaf zuyQ_(ji>W51f{nqPRHBt$I~dgLqx!-G~I1QJCrwZETFudRy6l}zdc7$$<1gR(|B|A z!THrwiTJg5t`Y#H|=nGTt3ai8zv6Pn&f%VJqPqgJf)=crIiS2VsgaO((K+4CLtzO9_;TI zLPy|GAPl*v&b&BW=u_k>;9AK7rKO~n)Dbn#niESub6q=|iSN`Eu8JWb;S!~;_qScs zR-8s=xRjxu#AbAmVMfyY`=@4T-7ZM;gU`l0Wr)n))8r~#14muws*iTI!R?^86 z@Pw4%;4KwskKja3ZeqAGKCkUIpMfvkD{;^RD0-j-iKr!3Z+5gDJ2s}x)q4{6EtD|N5#%KicF{E|B(A)Z-F4FJnv+hJPPV;$;^ zuqs+(g*GH&RS@V|8Nm4pH*f;flWnD;d9(CyFS4}ptPuA6RT*G1LoXfG5*N#AT7X0P zS}?Hj(M&Rsf&FACnE_XZ@Zc_!kln#ED=@xsoZBP+BE$ILQVwNVgE=wAL`S!RqSm^X zU-&6w`JLpW3yL3>umj~Be%34N5&Io(-8`XMEXT~IZ*HTEyNUCKe3vajr#U=HbWjzt zN8KNgfQ(3N5z?g?Cs%hy9a8$6Ysl%@-0k(1c6dTCNSdFnR2uQt8Fw{T^umJJvq*>c zX2F8~=+7&GXRS`iy5;1G&P{Oz>LVLAuDST}&Fbi?y&fEe6o%{(@FmpDGl`_o@;x1&6;pRrewQ?r7FvSHlS_3^re9RwR1nvO`!Lv{0jMNB#Tp=Dz(Mm&Ky>bF^3F6d<_{RCAyIFMB^TWCHY## z`O~>&zf_H4=5{`uLP2^N<7V8* zn%xK191A+IVv5WWdG;UPH$2g%Y8$T#p)HjH;z$7p4r4D88T8yfxi%Z^=A9fNTRkB~ z(i9K6PqA$1VCB%6S~15U+g^O~+yGfAyV|3fSyyoMV?&8E9c(F1zUOQfI_8~g$r{z6>{dUs_!tprmI)<)9iGSI%Mfr1A<(_taiUVWHbko|c* z=@WMJNHn1QB#X%*(=LH|Lp{-KdRpiqI7idjSS|$Knnknt3^m8#f&F|FGbv<)+%#}- zEsh=-lMhw@YZ7PpYUFD8 zw82CHIk*m@-*C1LU_vlk?nEBoo+pN`GM!fqd$jQ++{w12VZwTf23bj_GAAS?cOiOKevC z#PDTwZF<_vH)ZK&vd~?9@7N=`ve$^v*`t{Y|GYRoFrGY5>w!ifd#%oGX%dpDg zSwrl%D?NR5B!b~}Lm(_=oK5a`QK2|XukZK8vB&Ju`l z9ljpxJ-j`H+S`IYb}O`mTU{MKg=)jDtY~%xD~BzsN&mf5NrVW&YDCZ457#>7IIn`d zMXfDh9fY>{G4XTB0a^Tc$j%w8L{dP&xe(4vl@!B{^SW~j;3E(6{Au4D5n7=fo!aVT ze$@5o@|8^Q+p!-NrdSM%VZYHf0UaptLr#pk3p?B_wF$>T)<2?Xls(l=;75#uTgk)@ zFOiRt6+Fp}hS!*FKCZqr)H|{P4bzXk1=k{1m!LOTh*m-(z1AIE+J)0UAN|KHa_^*>lyU+P5(S-!(U^x;G=EqXMeF8#CSGio8R_nDD*wpyxK8(Z&|elhGp zJh7*Uun6zIw){&Op0=Dz%kwQ1|!ZJ?ZlP?tA zJ5UR+r=I&@d2KU_{$eU~?J~*xE%8G6V!8GW(;#WM^5a=|ZI*y+_H=;qOsG^@1-!X+Gu)f*+-egcO05dan9T zux}rS#!*T9-ap{qdg8o@>(jE6;W%nz0xy$*=!3oOAAN1>>j|ec%jfocxVFo>^)94( zidrWhow`3yp`=C4_WfoYCuERsf?5$|?0hiV%6iax(5lWQ*e@RTuRz5G_Bv4q zO^~Rf`Q1-4zYb+CDn^3!!uRc$t2}1R$!(@ou&~fNfH8cFQ@}AJ{|4d%-U5N6<8p+w zHQt5sY9)AJ!p)Q6bs2uzukqJ{Ae-kP%10C8!db}Ow*jcOrF-kP2gn4PCFT!0Inh4soxvzag@1ONN z&eBbYpuoXga?yb{3HQz%q|o^xei=dhpBm!Z>37lqi>hu?xIAm+ZmS(|vMKHc_x2FC zqEIHsr9Ur)t%4wKhi;hT2`W7l*kDjLW-TO(`?$c1+njkNX7huC=wt2Z+e;FQJcAng zOK&<2C5dkQmt96H{z;S4*18WL$Z;gelrE!6C|_>qT6_Hp{~g1_G#EbI9>H z_quY*v-7l}b&z>Q8xY0_+?>HP2P>#ayVn-6lgMW?B8ru=1U+b3Q`1tAFk6=7$oKQ! zJv(u8?8!Wl8@IW_w1@{eB2P!t^^%;7h5-6Prc_Bnp!T*LIq!{b;fjyuW7(!Q*V=}} zutFQ_<+huyhs3j-Q^Dg)$157CkJ`DL2G5EHDQ<_!Ume*)o6K?B!=klvazygBBT0@apSe+jjR!&)W-OIv2uy zq4#SPxAUHSN~6Lvq4Dp$Fxk^;5~4uYJmXK+^#LsqZj35prmmW?)?;RGAuu9A~X=-Yh1-)NCV3rtBhF3K{trXUnp1O{;RlwRT$l*bcc zxYtQ{9u2XbD*!Em4>>e*yjf*3c3wca@xlW&s4YCc^8qFR^(R|Y95~8Tk~#HE{P3W) z>iFjKXbk{yhWh5OE2NEl0j_Bv0cp4sF2W6`yP&2wQdfx|pz7h$HbPxo#Ev3R_g>68 z-ib`@b=FKCZq4G(8d%@9$bT#tW3625L{HsD%K|TTgbaj|jB=aq4I1EX$WFI;^N=M< z)pMd+b!uN5(0l=xe}oLs*U(Z$G=Ff?6}x=A>%aQ$x&<3(E?pj6e}ihG9CUy6EP*sH zD>?pVB6K{C3dHdU7&r5hg@LN%C-+jR^~V4;H{gK40%h)+j=D}&zQ2mz9Z&d$%JF|Y zLh%2L&Jf@ywaY7JU#`)x)^!zm)@Cup`gSr9A2)*y3>WCZlw^SdHxU2Qj5Z0&-jx%= zlm})&4)y%}H~k1@3H~BIi~vN&(RAw-xk34pzgz<~?bbg`*hT`<^6R`zx$`8GzcCYf z&OXjS#RI+nVI{M!LKSVP$%su8tKBiWey%~%JgpH|>OmDpNyjDDkP;S#6gs<#`5Ah5 zjEDIFvm(e>`6qG}DFjdS2i_T#^jXbJ* zMh2S)FQGAU>^~9A%yCP66ITuGyPIMd@u~3ng4mp{I!4+eVPS24%hQH>zhIa~#$RkP z)>mwPOHrV!8YX5;{Zp(~cP@Pxg9iI&&2GkJ*A4jGUEyWlD*!_U|C^1B^Kv1KPrdEe z_)2&3Bj0rCw|4(%4R1)?>?G0hE2&>?3>xfpd_Q$Q3j0%}?`%Q6Z~l8Px9TmrV_iPn zSo7Nlq{ZKZ@oC{k32T)>6wkJE)>uIy?NqpY!~(BmxQIM*r?JeCPwVIa2HDe4;B3|v zLA3V6ePJQwaQT<{N+wNY03_wvN&~XVfDgQEyD;o5j@4Q`4k%mL#*rQ&)l(D#T~cUF zs{EF|g}nb+vdhW?$E3;}PoQbpTkqQg%kXVDi1#Xar~nhb6a zKEJ!BPYCln2br)aPd}~SvVVCg6f{^NMl4^_7Y~aB)M-$;Kv>=s@W-1TZ%~^A1xQB# zJzWxw3qs{b2I$=o-mm`~nJQd50C*Svw6tqy8FszR6y_A(CNwvVS~lK>1&mB;|%*ZrsyI-0v82&1VQ$R?O5?%@`c=W$@?jqx0@D9CHqNZ6Yw7;;Qa}giqO$yf)?4EB z^k|{e^v1$+;J2r4!=H_MAtl@9(@S-0uC}c0hcGX}wk!jmUhlUH{$->oSD(JVlfX3V z6Wd$mtVmdkC^c9y3!(0JA8LWp{j4N2nQaH03(?6mE2f=QwTOi^Kfg71&Ssv|smcm` zI6y*2Eu*%((BJ0SIBjQS>S;t7T{})qY^@s*m$q{`{APZipf1CBR^h;$6C?k^Z8LfM z!Y#p49m>wd2*Bk-Jyc)kvI~Wz5>5-7Y|oV^{z-M0YvdkM(I!}t95i2 zl<&Y*bslSCT%+M@#f3#ZTA-#c>u?@tQd|ZPN1%`H?j5C-;gE%CNukW6DCr6c6(I7w z>1Yk)6Q)DEGR5+zcBo#lFTC)@2^se{bdmVWsE8rK_QZv80*2xVZ~9 zhrQXK=_+JZ>A!jK$d`bI`QdOE-F^&|94q5|G@=)?W1*u1*h}>5hMrV9!qoj_C!mEr z+s9UtxH#QIBvA2c>l_>V)!bnjfAn4dNGPj>l$u-cwo2c11MVMN_L^SA=EJoI#Ij~~ zzzw2Qu;efENeEfch2?3s{O5&w=cu3R&pTomwp8a6Sqzz#6*ofH+#3Kz!^t(K{>|V+ zQx!NPsVC!Y7YHc||CwENNGZ3MtUWj?==~m4kIlEP)jAt6<$W7iuY5>AQbO=_sMtJ2 z7s3L8`b-lhUto$RM~GmJ{b_M*g!0GWK(KBv*Ju5xc& zeJ^z#oLATmEN3CU<5cC+3!rvn9_Qv!lGA~@AFQ<tMm6 z=8!bzQ~OiX&|oK0P?6qE#H!n_;?M!5Knwy^k-y)rNZz6UdUZm&4$|3js=Qdznu@m& zSpF1nASI={t@T|_E!zbBJ9wL09{A3}LM~)4F32ZI_57jkvTb>f4J9@86bSGkthZX} zNRGq(2>1G9&Y>XFJ1yLf2<+ZWBOwjC5Kzrvie3u>TAu?QPk-{0i~kW!XMk#(oq(2~Tk~CIvB+RYHZ1se4}~$? zWrwU;h5>0F!vu}lb|dGavzL={1+Iw)jOB9>AthW;oMdlwQo5%P?IdHWg0V)^Tbl5K5gI3&l}_m$JX-2D;Ju~ z%F1{NuVK7$&b;I#6ep8MzCp4tI82fy?AF=ju}UJRLpMm7x+xet0{;;#T8URCa=aW#Vi$1X4pY( z#SLNvhbZl>{qcWvGzUnAuOn`iy?hO~P{TTt(8V+upt5#UU@in+kv?2hI{>MeduoD- zoy<5ngER~oi>x6#XC%2^R;h8iy<@YZV*3&bJmifFYWb!9@UTmi)XRy~0cC;k&w(3~ z2J_C#cNL>9|GSXxY4KJhC8ShWN(fuOnuFiMKKa$0IpWBM0gihdJK9hh8?29<9+7Gc ze11+kBQMLiO-T)MqrM6eh*u0DxvN3I+p_m8W{qWcTyoCrkl$CMkA6}zbJDdYEgx+& zIJ)W7B70vA_W3e!S2_gXf*(%nEY%TF{zwQ!#Fqzpe*{wJBgZ)rfT(T1NyoV7ZOZ(& zt6hk|loWp7RdUAD)CnTqRxFSs;`d2vRc(9WG5E53#yp`c&VqeT0dn^AYTw)It)rvX zuyqu(j}7FHt3ju!+VvyUT_g&!Gk$2u5^Cyda--LTg-Y`JD$k!Xu|+; z!9Mrnl~(9QlUGysUvo$IF?}2{lF=ApAKq*yf=5V2uk(x5Z2*+>H7h>hprOw*{R)!AY+YjA+2;cYSb3{i z?0o)F(uH~V)shLuV*Jew=t*;79ol&^C%xt)yH4ui2RKX*+1)Q>tU=w0SBW0eX@x1K zYFo?18wo*ZisQny)XHvvl*&$a2fF%DSCj4)Jp@@sE;Z4(&x0YdIUL7DE#T60Pm!9G z7f;66XBu~Z+Z8Bls@VyGikdoHl?30Z<4rf zwAo4@tRTVuq#%*kGE-7by8?B`9!X z0C7{n^Y3y0x?mAa0T31lB>}5+gGp#==7FgDwJUDjRfJv0Qz)-Lg2d(vs;gb<<-#`quwi7IotYI_%b>jSWTT(n z0}KNEcBNe%-zSl0|L7;=s?{=~0TBzZ4rkQUE92ayRmoD+AkFLgoGV*CYr-8V%Xfw@ zb@83W!2{J+s98+K?1>~un(h4}rCW)YiS)4Q#|JbBDL*K$uUJai7rUD$=N}WG(^amv zrE1CjAY0SNx!P|~_5E|k4dCC|6A^^-HH4I2Bp_>25GTM}!JdS*NjMyi&*<0ot7b~| zm5_!)9pk1W2l3YyA=06s+6vWQ`cHWA>RkQDoQzfN3(IQ?F_5vbpE#!ak`A3PHp^o9 zCctrjn0-_nno#MQuHuuNq|I*5`37Qp`t5E5*vZJ&Pyq1%7}qwQtnrrT&{pRbcXTuz zC_k%DI=k+eD1l>N25lMfKhWI2-bckDaug8OE0ou|w1tpR^L{&g=%rX=yGj4ixlJJ) zvC6K^nFO{R?xE%Y?c_lpgZ1A1PdiWktl3W7hpR+Qd`|RL3h;p4pR>v2vI&@8OE$kA zc2OFhPv8Y}>JID`w{Thj*{NHMEemEzTy9p3dfJ=4PfS46=c^8G+S(L(J!IKxFK(`o z233pvO{ zmn4uV`gEcH{%syfBSFRtg?MGl+Jm)?5zo zmQRX2%IjN$DYTT+Ke+rUlNYS)e_{qIoQacYBz${K`l6<-d_2do=`CNcWs<_Dzu8Ae znarIR2$kz$9}-$S?hcqTHPKq^(*g}BTkFQM>Ne3IpX1tur@nWW4IVMIhDJ7f zs$0uM-X#C6gaHGkAWP02g)n=KOac^V(ZIh+|Ej#DIKe5fW_&fII`ny(&3DY(A%-@j z;Y@k&zgUS)zZp9XRkz8nd%ERc26&0A6erz;vq#0-(XKj2<{1U5u& zgjPmeoJ7!d^#0VH@~T0yQlNg21$Zgc{Ed<{SMd{AaP9B9?ML!8%-W>Yv_+@wMBKC8 z^pV2lfWHVU#*ec$&5FMf@dFrO9ln@4Erqf8JtnCpy;gdauO(mpJ8H>C<9Oe-(ADe> zM>Hq=D>%UNir5R4-;#rQY@8@tF~{)2fKkl8=*~*p{|<|-Fkj|H>}y{oA|5BG$}SVR zl{o%LPj9DWLl*W~@R-q#FqdGT@#KL;VK-tn&K01BR!}*``CNj!knGTZaW9+EV4B`o zNJB%0K#rgENR9Qzj_>oXb^Si%0(H6{s z4vog*oOiKiug=c9T|&9r^rUK7dA4MKw0-Hm+fI_ zR%9HykFbmjrn_m~F_sbMU9P*F3_i*``u5e zbH3e@I`8`*(-!^syLQF)y}GkjpTAAT0!7t{+j{i0d=`%c}e-3N4e zdrGw{w(UtyV!ma&TE;ghdavRURXJPDRaKtg7fNtIG!F^&3(aFvx$gZpwCNe*0{~Jxsll$djLtqE70d91{1o0)>nM0 zx^j9VkUO|pb{)S!pV!r+AAHxScZ^ra7}M*;$g=Ye6gG=nQ~hbg%-5oT+~E5HeT*!- z<|r#9Ete`0OA%)ou_nF>hwy?e*3ub3Ti+v9gqR_-}KZekbc^VK}0)&!iN6{ODFyF_N! zP+eL{)qC0!=Z4OCNZzN)%IX>Mz{gjPT3tN{YulB}eoD&udOo*6pQnh@#A_42s=U7M zOCLtcykIa^YG7cLk5-kQ>Ivi_XKjH#PcoqENMkO4tly`5FBWqwfaJi|{mca8E-=<_rz5PLG=3+G)x9&*+e=yUVpeF76jzcrYg z_oe-}a&n*HqehB#6Wt8ftO9)=XK_@;zhCliAP-SMfj)jfYD@(;IpcABW#8B+Weh28 z`EQxr0(~73HopLsDoDNVP!>v6)N-d}h=8@oxQmDNX@dtGA*BK3d@o; z>#aj|1*OB2L7QI@r7J2^>DF1p5?5FB*O_haGgoIgocaFNK0qFDwif6Ehec98=Pp~(Jp)Al94C;m-i`!hRl&nU7@PB&MK>X&mW5RU*NWw)zG$JG48LnH>I2A!qi zBhjwZ`Q<}IO(xO4QrDG6i}saNP&z2C&^92|R5e?2mX%<#?E&(XV8`)^oC1B`UhNx5 z3T%D`Q;k-Bz){9(->C}Cvcu*#YWZ)2v9{x5!DBDh0C|E4@Tn#nZh{y|4;Thv%|nt9 zNc>!Uv3a~eU-Uag-8E*`MBxVY=MIbLvH)_^*NmNhlCqG%*U&E3lAi}V6M>#(T?%8 zrzkA3H;|_w$UM(ULgE+bQx2~b=u4Xa!)?qm0QR_7)@Xs;)mbrC?xy^JM1&I3uUGwt z(~X&d>Ym9T{uBx1u8tm%M7N-!#36H8tI}ryO1@(5EXZ-^du0YtR`hz6za@-3Q1G>;ip^lgQ_r`~rOn+5G)O zJQK8o3p(@UytNtkvQ%~Os$bH zo@1+vHQF;hdM;wpv;jjKoPe~yg9apifxe+b1A*Ez@@IWF}s2sx|{b-uIV;E;^ zQUkw0pVx5;^fd+~sRjB*uGptX*V7SBiG{>B%`@D+NGPp99}tf#$zfjcXai%a%Gq9^ zuiNHR;-s3TA&Z}=eoof+g{=<^{+8j{yN~cwQ)dliL`H}73h;gBu2%( zT>YqlQEB#UF3?A++@O@=ig}WMw*?ET7CDxP!lXd%z~+}`wq3;WVNCaQK5OGGgS z=}#tp> z82bd0W6+%&RoI6g8Pgs1vkLS9DM`=pVS}Xxq|qkl$0GF{NU9*sB)q=;XI6s4>&2sG zcCY-imJULfo%DcYodKjI*m`@T%TB=N*T->Uq-ZaUwpFEG@atuA+ZGD+8N67auZ#O# zc08(wJ{oQ?IySX`=igbNFJ#Jn15uH>fV+4Brda$OpI3FCsMZX`G3=$>Xk5$8%o=## zatrj4g76CTnH=*1RPjMTQepEmm@6*glvl<CfZD z&o+Gx-RfQc65kj97k|gs#m~d0%;XO(89)*+C&t?DQCw033iQcJYG6pUI4(!lQ$6Dj za%HcGkpqFa_yziWzPKubtA5f;tFsKQjIq{r7U;v~7rCwW5ixI4#>Dd@DA@T^(yH?F zMRzk$o2E?Z8aIE_Ow27jz^v%ppjls*OBo$G?R%Kav~LFg@R$&Np?xu91&0Rx`m$R@ zBk)0izLRjm_5Z({-7VHb9h`8fYt}#-;P3Wd!}WbgTmJh2ASpOmc1Ul&UvU8mUnG@yPKV1}@biH=^NPj&yBJyVMv z#qysh@pBfZ6IBhK9rWJ!!9Y!gW?nD=^O|Pkv#jI=A{UFjbogT*U&JlYM@k}pVk}S4 z>f`@TH(8yG#W8I%(n$FQ`g}~i?6)!?2|E5fBrM$P^?-!;+-vEdYUydQV6y&+l=NUA z4&@ixz72oRfgLa@$ko5xyC-Dv$t^usH+ggGCce9D2E>3l*m zIcLiWNP?Ifr!zS?ZL3~qu9(7YTgorcC*KGx!kXUhvFa?)C%W8HP4*ScCraj6H*iQoKOi|&*H>PE3+$haS@tJ1Se^q&B4&X;-_x$#=>U>K z$zw?T0)70X22O%QaDK&j&b&A5*Aex`+E^foSOxmV8mqGuFowjEymZ?IcK%37A=SzNcHa{|Jx-oGd%AP6tvFY`x@V+3|@I(Wxu8zRF2s#(8TLPwqgHAj?kq z1^VO@`>QUgnSs}@Y5Vtg7U&!K{L%zs!q#n9&p zh9j$I2kS#O+LmKZQ#YV?Fbnkgo}sY(B#;FEgn3Bk%AbeCr@Hg;M18Ss3uE$RL&o}w z7br9PT%dMzzS+CR>fR(E8@kDUSpK zoz}Th0|!x;)Fr=N!^!vLzoyRQZw>9#<*^xkP zV6J87d)mA`RX`H3#*mPhG80Hi#9T7>y6pHUbYq{?rH)ms8y;lIB0FgSP+L%-Z?rNC z^m$(Y2`3WqK7LTtT6W8SW3OfB3)s4ZOt>aSzy8qs>D=X*_-eIg#|I&!FNkUF37l1+ z4@f~+1^N(p7x>4-gaElKK6k5_G|8!kS~ud!`5ytbfmxu>_cSZERRBrA%d#`s?^E7t z-{B$dXW8+^F8V$u!@|lKJCXF>XKw(tC6G~|Z>+KAI%Tc)&7Yr?@WWqIMCP5s3iKWK zU6vg`124L0`^EUoHsJ=^(+LlCdXxRj$eAyn-`;tC7R*CpOpIm7C@Rx)a_@0*+dk;J z`^E#cLh`pydDyt7+Xszsa+(VHaqJf z@uaNYJywq@&L|!4aBpsry#nQQ)}}7savqQr{}0H4O4dH%Z1(^F002ovPDHLkV1lv- BSV#Z> diff --git a/src/main/resources/static/images/osf-registries-banner.png b/src/main/resources/static/images/osf-registries-banner.png index f617af1c9790baf5e5944ec9d5365ef1035220ff..dbb5edd30d89655cd65d4974c8e220eb2d529d3c 100644 GIT binary patch literal 10787 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 K`5H5H-2VYYH+bOy literal 21349 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 Ef`=TVtN;K2 diff --git a/src/main/resources/templates/fragments/serviceui.html b/src/main/resources/templates/fragments/serviceui.html index 95118089..a63f7c1b 100644 --- a/src/main/resources/templates/fragments/serviceui.html +++ b/src/main/resources/templates/fragments/serviceui.html @@ -13,11 +13,21 @@

- -
-

-

+
+
+ + + + + + + +
+ + + +
From 22c4835b70d6a093f41d97c0d79de7aacccf9550 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Feb 2021 14:11:08 -0500 Subject: [PATCH 60/71] Clean up messages.properties --- src/main/resources/messages.properties | 64 +++++++++---------- .../templates/casAccountDisabledView.html | 4 +- .../casAccountNotConfirmedIdPView.html | 4 +- .../casAccountNotConfirmedOsfView.html | 4 +- .../templates/casGenericSuccessView.html | 4 +- .../templates/casInstitutionLoginView.html | 4 +- .../casInstitutionSsoFailedView.html | 4 +- .../templates/casInvalidUserStatusView.html | 4 +- .../casInvalidVerificationKeyView.html | 4 +- .../resources/templates/casLoginView.html | 2 +- .../resources/templates/casLogoutView.html | 2 +- .../templates/casServiceErrorView.html | 4 +- .../casTermsOfServiceConsentView.html | 2 +- .../templates/casTwoFactorLoginView.html | 2 +- src/main/resources/templates/error.html | 6 +- src/main/resources/templates/error/401.html | 2 +- src/main/resources/templates/error/403.html | 2 +- src/main/resources/templates/error/404.html | 2 +- src/main/resources/templates/error/405.html | 2 +- src/main/resources/templates/error/423.html | 2 +- .../templates/fragments/loginform.html | 2 +- .../templates/fragments/tosloginform.html | 2 +- .../templates/fragments/totploginform.html | 4 +- 23 files changed, 64 insertions(+), 68 deletions(-) diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 1aae209b..26958b69 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1,8 +1,7 @@ ######################################################################################################################## -# Default messages.properties as of 6.2.x, see: -# https://github.com/apereo/cas/blob/6.2.x/support/cas-server-support-thymeleaf/src/main/resources/messages.properties -# -# Note: customized messages are commented out and their respective customizations are added to the end of this file +# Default messages.properties as of 6.2.x, see: # +# https://github.com/apereo/cas/blob/6.2.x/support/cas-server-support-thymeleaf/src/main/resources/messages.properties # +# Note: customized messages are commented out and their respective customizations are added to the end of this file # ######################################################################################################################## # screen.welcome.welcome=Congratulations on bringing CAS online! To learn how to authenticate, please review the default authentication handler configuration. @@ -402,7 +401,7 @@ screen.mfaUnavailable.message=CAS was unable to reach your configured MFA provid # Login View ##################################################################### #Resources Labels -# cas.login.pagetitle=Login +cas.login.pagetitle=Login cas.login.resources.header=Resources cas.login.resources.wiki=Documentation cas.login.resources.endpoints=Actuator Endpoints @@ -485,17 +484,15 @@ passwordless.error.invalid.user=Provided username does not carry enough contact noop.message=This's a noop message. # -######################################################################################################################## -# -# End of default messages.properties -# -######################################################################################################################## +###################################### +# End of default messages.properties # +###################################### -######################################################################################################################## -# OSF CAS customized messages.properties -######################################################################################################################## +########################################## +# OSF CAS customized messages.properties # +########################################## # # Header # @@ -537,8 +534,8 @@ screen.generic.link.support=Need help signing in? # # Login page and login form submission # -cas.login.pagetitle=Sign in -screen.welcome.instructions=Sign in with your OSF account to continue +cas.login.title=Sign in +screen.welcome.tips=Sign in with your OSF account to continue screen.welcome.label.email=Email screen.welcome.label.email.accesskey=e screen.welcome.label.password=Password @@ -553,20 +550,20 @@ screen.defaultserviceredirect.heading=Redirecting to OSF login # # Two factor login form submission # -screen.twofactor.pagetitle=Sign in -screen.twofactor.instructions.top=Enter your one-time password to finish login +screen.twofactor.title=Sign in +screen.twofactor.tips.top=Enter your one-time password to finish login screen.twofactor.label.email=Your OSF account screen.twofactor.label.email.accesskey=a screen.twofactor.label.onetimepassword=One-time password (6-digit) screen.twofactor.label.onetimepassword.accesskey=o screen.twofactor.button.verify=Verify screen.twofactor.link.cancel=Cancel -screen.twofactor.instructions.bottom=Open the two-factor authentication app on your device to view your authentication code and verify your identity. +screen.twofactor.tips.bottom=Open the two-factor authentication app on your device to view your authentication code and verify your identity. # # Terms of service consent check login form submission # -screen.tosconsent.pagetitle=Terms of service -screen.tosconsent.instructions=Terms of use and privacy policy +screen.tosconsent.title=Terms of service +screen.tosconsent.tips=Terms of use and privacy policy screen.tosconsent.message.p1=You are seeing this page, either because this is your first-time signing into OSF via your \ institution, or because we have recently updated the terms that you need to review. screen.tosconsent.message.p2=You must agree to our \ @@ -580,8 +577,8 @@ screen.tosconsent.link.cancel=Cancel and go back to OSF # # Institution login page # -screen.institutionlogin.pagetitle=Institution SSO -screen.institutionlogin.instructions=Sign in through your institution +screen.institutionlogin.title=Institution SSO +screen.institutionlogin.tips=Sign in through your institution screen.institutionlogin.message.select=If your institution has partnered with OSF, please select its name below and sign in with your institutional credentials. If you do not currently have an OSF account, this will create one for you. screen.institutionlogin.message.auto=Your institution has partnered with OSF. Please continue to sign in with your institutional credentials. If you do not currently have an OSF account, this will create one for you. screen.institutionlogin.heading.select=Select your institution @@ -601,7 +598,7 @@ screen.generic.logoutsuccess.button.continue=Back to OSF screen.generic.logoutsuccess.link.login=Login again # screen.generic.loginsuccess.title=Signed-in -screen.generic.loginsuccess.tip=Oops! Redirection didn't happen ... +screen.generic.loginsuccess.tips=Oops! Redirection didn't happen ... screen.generic.loginsuccess.heading=Login successful screen.generic.loginsuccess.message=You have successfully logged into OSF! However, you are seeing this page because \ the automatic redirection somehow didn't happen. Please click the button below to continue to OSF. @@ -632,10 +629,11 @@ authenticationFailure.TermsOfServiceConsentRequiredException= # Authentication exception messages in stand-alone exception views # screen.error.page.loginagain=Log in again -screen.authnerror.instructions=Oops! Something went wrong ... -screen.authnerror.instructions.devmode=Developer mode only !!! +screen.authnerror.title=Login Error +screen.authnerror.tips=Oops! Something went wrong ... +screen.authnerror.tips.devmode=Developer mode only !!! screen.authnerror.button.resendosfconfirmation=Resend confirmation email -screen.authnerror.button.backtoosf=Exit and go back to OSF +screen.authnerror.button.backtoosf=Exit login screen.accountdisabled.heading=Account disabled screen.accountdisabled.message=The OSF account associated with the email has been disabled. Please contact
OSF Support to regain access. @@ -647,14 +645,14 @@ screen.accountnotconfirmedidp.message=The OSF account associated with the email screen.accountnotconfirmedosf.heading=Account not confirmed screen.accountnotconfirmedosf.message=The OSF account associated with the email has been registered but not confirmed. \ Please check your email (and spam folder) or click the button below to resend your confirmation email. -screen.unavailable.header=CAS Error +screen.servererror.title=Server Error screen.unavailable.heading=CAS unavailable screen.unavailable.message=Your request cannot be completed at this time. Please return to OSF and try again later. If \ this issue persists, please contact OSF Support with \ a copy of the error details below. screen.unavailable.button.viewdetails=View error details screen.unavailable.button.hidedetails=Hide error details -screen.service.error.header=Service Error +screen.service.error.title=Service Error screen.service.error.heading=Service not authorized screen.service.error.message=The application you attempted to authenticate to is not authorized to use OSF CAS. Please \ return to OSF and try again. If this issue persists, please contact OSF Support. -screen.institutionssofailed.pagetitle=Institution SSO Error +screen.institutionssofailed.title=Institution SSO Error screen.institutionssofailed.heading=Institution login failed screen.institutionssofailed.message=Your request cannot be completed at this time. Please \ return to OSF and try again later.

If the issue persists, \ check with your institution to verify your account is entitled to authenticate to OSF.

If you believe this \ is in error, please contact Support for help. -######################################################################################################################## -# -# Enf of OSF CAS customized messages.properties -# -######################################################################################################################## +################################################# +# Enf of OSF CAS customized messages.properties # +# ############################################### diff --git a/src/main/resources/templates/casAccountDisabledView.html b/src/main/resources/templates/casAccountDisabledView.html index 42562bc4..fe385864 100644 --- a/src/main/resources/templates/casAccountDisabledView.html +++ b/src/main/resources/templates/casAccountDisabledView.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casAccountNotConfirmedIdPView.html b/src/main/resources/templates/casAccountNotConfirmedIdPView.html index 2cf7a89c..6fcc69b9 100644 --- a/src/main/resources/templates/casAccountNotConfirmedIdPView.html +++ b/src/main/resources/templates/casAccountNotConfirmedIdPView.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casAccountNotConfirmedOsfView.html b/src/main/resources/templates/casAccountNotConfirmedOsfView.html index e1f9b250..d08f07d9 100644 --- a/src/main/resources/templates/casAccountNotConfirmedOsfView.html +++ b/src/main/resources/templates/casAccountNotConfirmedOsfView.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casGenericSuccessView.html b/src/main/resources/templates/casGenericSuccessView.html index c2cdaff9..47a4cbe7 100644 --- a/src/main/resources/templates/casGenericSuccessView.html +++ b/src/main/resources/templates/casGenericSuccessView.html @@ -20,7 +20,7 @@
- +

@@ -41,7 +41,7 @@


- +
- +
diff --git a/src/main/resources/templates/casInstitutionSsoFailedView.html b/src/main/resources/templates/casInstitutionSsoFailedView.html index e2071a1b..301e3161 100644 --- a/src/main/resources/templates/casInstitutionSsoFailedView.html +++ b/src/main/resources/templates/casInstitutionSsoFailedView.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casInvalidUserStatusView.html b/src/main/resources/templates/casInvalidUserStatusView.html index 41d5b641..b49c518c 100644 --- a/src/main/resources/templates/casInvalidUserStatusView.html +++ b/src/main/resources/templates/casInvalidUserStatusView.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casInvalidVerificationKeyView.html b/src/main/resources/templates/casInvalidVerificationKeyView.html index 05e4f727..2f17532f 100644 --- a/src/main/resources/templates/casInvalidVerificationKeyView.html +++ b/src/main/resources/templates/casInvalidVerificationKeyView.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casLoginView.html b/src/main/resources/templates/casLoginView.html index 4d01058a..db87cd5d 100644 --- a/src/main/resources/templates/casLoginView.html +++ b/src/main/resources/templates/casLoginView.html @@ -5,7 +5,7 @@ - + diff --git a/src/main/resources/templates/casLogoutView.html b/src/main/resources/templates/casLogoutView.html index 0bbc1de8..b473166b 100644 --- a/src/main/resources/templates/casLogoutView.html +++ b/src/main/resources/templates/casLogoutView.html @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casServiceErrorView.html b/src/main/resources/templates/casServiceErrorView.html index 6ad422a7..a9371528 100644 --- a/src/main/resources/templates/casServiceErrorView.html +++ b/src/main/resources/templates/casServiceErrorView.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

diff --git a/src/main/resources/templates/casTermsOfServiceConsentView.html b/src/main/resources/templates/casTermsOfServiceConsentView.html index f4533aa1..0dd71636 100644 --- a/src/main/resources/templates/casTermsOfServiceConsentView.html +++ b/src/main/resources/templates/casTermsOfServiceConsentView.html @@ -5,7 +5,7 @@ - + diff --git a/src/main/resources/templates/casTwoFactorLoginView.html b/src/main/resources/templates/casTwoFactorLoginView.html index ad20c2bc..c630bf1b 100644 --- a/src/main/resources/templates/casTwoFactorLoginView.html +++ b/src/main/resources/templates/casTwoFactorLoginView.html @@ -5,7 +5,7 @@ - + diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index ff828987..dac8ff11 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -5,7 +5,7 @@ - + @@ -20,7 +20,7 @@
- +

@@ -41,7 +41,7 @@


- +

diff --git a/src/main/resources/templates/error/401.html b/src/main/resources/templates/error/401.html
index e6ee834c..874b9378 100644
--- a/src/main/resources/templates/error/401.html
+++ b/src/main/resources/templates/error/401.html
@@ -21,7 +21,7 @@
                 
- +

diff --git a/src/main/resources/templates/error/403.html b/src/main/resources/templates/error/403.html index fa8cc7ed..b8a7a85e 100644 --- a/src/main/resources/templates/error/403.html +++ b/src/main/resources/templates/error/403.html @@ -21,7 +21,7 @@
- +

diff --git a/src/main/resources/templates/error/404.html b/src/main/resources/templates/error/404.html index 3c1b4b33..42b28141 100644 --- a/src/main/resources/templates/error/404.html +++ b/src/main/resources/templates/error/404.html @@ -21,7 +21,7 @@
- +

diff --git a/src/main/resources/templates/error/405.html b/src/main/resources/templates/error/405.html index 56202180..678257ea 100644 --- a/src/main/resources/templates/error/405.html +++ b/src/main/resources/templates/error/405.html @@ -21,7 +21,7 @@
- +

diff --git a/src/main/resources/templates/error/423.html b/src/main/resources/templates/error/423.html index ca5de1c9..1666cf25 100644 --- a/src/main/resources/templates/error/423.html +++ b/src/main/resources/templates/error/423.html @@ -21,7 +21,7 @@
- +

diff --git a/src/main/resources/templates/fragments/loginform.html b/src/main/resources/templates/fragments/loginform.html index 5bf198c9..3fdc20f4 100644 --- a/src/main/resources/templates/fragments/loginform.html +++ b/src/main/resources/templates/fragments/loginform.html @@ -23,7 +23,7 @@
- +
diff --git a/src/main/resources/templates/fragments/tosloginform.html b/src/main/resources/templates/fragments/tosloginform.html index 25166506..60b206ca 100644 --- a/src/main/resources/templates/fragments/tosloginform.html +++ b/src/main/resources/templates/fragments/tosloginform.html @@ -23,7 +23,7 @@
- +
diff --git a/src/main/resources/templates/fragments/totploginform.html b/src/main/resources/templates/fragments/totploginform.html index 9483d662..0b1c5f18 100644 --- a/src/main/resources/templates/fragments/totploginform.html +++ b/src/main/resources/templates/fragments/totploginform.html @@ -23,7 +23,7 @@
- +
@@ -120,7 +120,7 @@
-

+

From 14a91bd87b736d217f4216d03a87eba872ad4b3d Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Feb 2021 14:52:17 -0500 Subject: [PATCH 61/71] Rename both "at since" tags 20.2.0 and 21.1.0 to 21.0.0 --- .../authentication/exception/InstitutionSsoFailedException.java | 2 +- .../exception/TermsOfServiceConsentRequiredException.java | 2 +- .../cos/cas/osf/authentication/support/OsfInstitutionUtils.java | 2 +- .../io/cos/cas/osf/configuration/model/OsfApiProperties.java | 2 +- .../io/cos/cas/osf/configuration/model/OsfUrlProperties.java | 2 +- src/main/java/io/cos/cas/osf/model/OsfInstitution.java | 2 +- .../osf/web/flow/configurer/OsfCasLogoutWebFlowConfigurer.java | 2 +- .../cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java | 2 +- .../osf/web/support/OsfApiInstitutionAuthenticationResult.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java index d56e2244..3d6a673a 100644 --- a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java +++ b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoFailedException.java @@ -8,7 +8,7 @@ * Describes an authentication error condition where institution SSO has failed. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ @NoArgsConstructor public class InstitutionSsoFailedException extends AccountException { diff --git a/src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java b/src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java index 7cd576b2..59b88266 100644 --- a/src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java +++ b/src/main/java/io/cos/cas/osf/authentication/exception/TermsOfServiceConsentRequiredException.java @@ -8,7 +8,7 @@ * Describes an authentication error condition where a user account needs to agree to OSF's terms of service. * * @author Longze Chen - * @since 21.1.0 + * @since 21.0.0 */ @NoArgsConstructor public class TermsOfServiceConsentRequiredException extends AccountException { diff --git a/src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java b/src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java index 6e49e838..5f7d615c 100644 --- a/src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java +++ b/src/main/java/io/cos/cas/osf/authentication/support/OsfInstitutionUtils.java @@ -17,7 +17,7 @@ * This is {@link OsfInstitutionUtils}. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ @Slf4j public final class OsfInstitutionUtils { diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfApiProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfApiProperties.java index 07648776..51970e07 100644 --- a/src/main/java/io/cos/cas/osf/configuration/model/OsfApiProperties.java +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfApiProperties.java @@ -10,7 +10,7 @@ * This is {@link OsfApiProperties}. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ @Getter @Setter diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java index 04704c24..4a09772f 100644 --- a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java @@ -17,7 +17,7 @@ * staging servers) URLs need to be manually put into the flow context for the templates to access. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ @Getter @Setter diff --git a/src/main/java/io/cos/cas/osf/model/OsfInstitution.java b/src/main/java/io/cos/cas/osf/model/OsfInstitution.java index c2d6bc30..9c80ea43 100644 --- a/src/main/java/io/cos/cas/osf/model/OsfInstitution.java +++ b/src/main/java/io/cos/cas/osf/model/OsfInstitution.java @@ -14,7 +14,7 @@ * This is {@link OsfInstitution}. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ @Entity @Table(name = "osf_institution") diff --git a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLogoutWebFlowConfigurer.java b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLogoutWebFlowConfigurer.java index e192f031..97b4e651 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLogoutWebFlowConfigurer.java +++ b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLogoutWebFlowConfigurer.java @@ -15,7 +15,7 @@ * This is {@link OsfCasLogoutWebFlowConfigurer}. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ public class OsfCasLogoutWebFlowConfigurer extends DefaultLogoutWebflowConfigurer { diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java index ec84b4c8..4b6a18c0 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java @@ -17,7 +17,7 @@ * This is {@link OsfCasPreInitialFlowSetupAction}. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ @RequiredArgsConstructor @Slf4j diff --git a/src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java b/src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java index eefd5352..8e5b26bf 100644 --- a/src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java +++ b/src/main/java/io/cos/cas/osf/web/support/OsfApiInstitutionAuthenticationResult.java @@ -12,7 +12,7 @@ * This is {@link OsfApiInstitutionAuthenticationResult}. * * @author Longze Chen - * @since 20.2.0 + * @since 21.0.0 */ @AllArgsConstructor @Getter From eca56fdbcc82d2aaaee0e15e584796856becc581 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Feb 2021 14:59:07 -0500 Subject: [PATCH 62/71] Update cas.properties to be copied to charts templates * Remove unusde and / or deprecate settings * Use the old file location for instn authn attrs transformation: /etc/cas/config/instn-authn.xsl -> /etc/cas/institutions-auth.xsl --- etc/cas/config/cas.properties | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/etc/cas/config/cas.properties b/etc/cas/config/cas.properties index c1d152cb..c6206a97 100644 --- a/etc/cas/config/cas.properties +++ b/etc/cas/config/cas.properties @@ -15,12 +15,6 @@ cas.server.prefix=${cas.server.name} # Tomcat Server # cas.server.tomcat.server-name=OSF CAS -# Enable additional HTTP connections for the embedded Tomcat container (when SSL is enabled by default) -# cas.server.tomcat.http.port=${TOMCAT_HTTP_PORT:80} -# cas.server.tomcat.http.protocol=org.apache.coyote.http11.Http11NioProtocol -# cas.server.tomcat.http.enabled=true -# cas.server.tomcat.http.attributes= -# e.g. cas.server.tomcat.http.attributes.{attribute-name}={attributeValue} ######################################################################################################################## ######################################################################################################################## @@ -92,7 +86,7 @@ cas.authn.osf-api.instn-authn-jwe-secret=${OSF_JWE_SECRET} # # Path of the XSL file for parsing and transforming XML authentication responses # -cas.authn.osf-api.instn-authn-xsl-location=file:/etc/cas/config/instn-authn.xsl +cas.authn.osf-api.instn-authn-xsl-location=file:/etc/cas/institutions-auth.xsl ######################################################################################################################## ######################################################################################################################## @@ -122,8 +116,6 @@ cas.authn.osf-postgres.jpa.dialect=${OSF_DB_HIBERNATE_DIALECT:io.cos.cas.osf.hib cas.jdbc.show-sql=false cas.jdbc.gen-ddl=true cas.jdbc.case-insensitive=false -# cas.jdbc.physical-table-names= -# e.g. cas.jdbc.physical-table-names.{table-name}={new-table-name} # # General JPA Settings # From a2b2b91706e77a619a5cda2c486aa00d7a937aa7 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Feb 2021 15:48:02 -0500 Subject: [PATCH 63/71] Fix local casarxiv ID to avoid conflicts --- ...arxiv-203948234207241.json => casarxiv-203948234207239.json} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename etc/cas/services/local/{casarxiv-203948234207241.json => casarxiv-203948234207239.json} (97%) diff --git a/etc/cas/services/local/casarxiv-203948234207241.json b/etc/cas/services/local/casarxiv-203948234207239.json similarity index 97% rename from etc/cas/services/local/casarxiv-203948234207241.json rename to etc/cas/services/local/casarxiv-203948234207239.json index 9232feec..dbbc71ae 100644 --- a/etc/cas/services/local/casarxiv-203948234207241.json +++ b/etc/cas/services/local/casarxiv-203948234207239.json @@ -3,7 +3,7 @@ "serviceId" : "^https?://(localhost|127\\.0\\.0\\.1):5000/(login|logout)/?\\?next=https?(%3A|:)(%2F|/)(%2F|/)((local\\.casarxiv\\.org(%3A|:)4200)|((localhost|127\\.0\\.0\\.1)(%3A|:)5000(%2F|/)preprints(%2F|/)casarxiv))($|%2F|/).*", "name" : "CasArxiv Preprints", "description" : "", - "id" : 203948234207241, + "id" : 203948234207239, "evaluationOrder": 10, "logo" : "/images/branded/preprints-casarxiv-logo.png", "attributeReleasePolicy": { From 2fe5729f2c8fde0c92b24e5a3ed57aeca22d651b Mon Sep 17 00:00:00 2001 From: Matt Clark Date: Wed, 27 Jan 2021 12:03:21 -0500 Subject: [PATCH 64/71] Adds sonarqube plugin to gradle & github build workflow --- .github/workflows/build.yml | 36 ++++++++++++++++++++++++++++++++++++ build.gradle | 12 ++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..6adc6e6a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,36 @@ +name: Build +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache Gradle packages + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: ./gradlew build sonarqube --info diff --git a/build.gradle b/build.gradle index aae47336..666c7b3b 100644 --- a/build.gradle +++ b/build.gradle @@ -166,3 +166,15 @@ idea { downloadSources = true } } + +plugins { + id "org.sonarqube" version "3.0" +} + +sonarqube { + properties { + property "sonar.projectKey", "CenterForOpenScience_osf-cas" + property "sonar.organization", "centerforopenscience" + property "sonar.host.url", "https://sonarcloud.io" + } +} From 59f31eaa7081018c78de6cdf479c5e9f97369bcf Mon Sep 17 00:00:00 2001 From: Matt Clark Date: Thu, 28 Jan 2021 13:02:32 -0500 Subject: [PATCH 65/71] Adds sonarqube plugin to use older plugin style --- build.gradle | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 666c7b3b..8cc08cee 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,7 @@ buildscript { classpath "gradle.plugin.com.google.cloud.tools:jib-gradle-plugin:${project.jibVersion}" classpath "io.freefair.gradle:maven-plugin:${project.gradleMavenPluginVersion}" classpath "io.freefair.gradle:lombok-plugin:${project.gradleLombokPluginVersion}" + classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.1.1" } } @@ -167,9 +168,7 @@ idea { } } -plugins { - id "org.sonarqube" version "3.0" -} +apply plugin: "org.sonarqube" sonarqube { properties { From 566702879c4bdc338b9915f9ff1078687b53ac45 Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Tue, 2 Feb 2021 12:50:28 -0500 Subject: [PATCH 66/71] Organize plugins in build.gradle --- build.gradle | 55 +++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/build.gradle b/build.gradle index 8cc08cee..96ce29f7 100644 --- a/build.gradle +++ b/build.gradle @@ -59,8 +59,13 @@ def casWebApplicationBinaryName = "cas.war" project.ext."casServerVersion" = casServerVersion project.ext."casWebApplicationBinaryName" = casWebApplicationBinaryName +apply plugin: "war" apply plugin: "io.freefair.war-overlay" +apply from: rootProject.file("gradle/tasks.gradle") +apply from: rootProject.file("gradle/springboot.gradle") +apply from: rootProject.file("gradle/dockerjib.gradle") + apply plugin: "io.freefair.lombok" lombok { config["config.stopBubbling"] = "true" @@ -71,14 +76,30 @@ lombok { config["lombok.toString.doNotUseGetters"] = "true" } -apply from: rootProject.file("gradle/tasks.gradle") - -apply plugin: "war" apply plugin: "eclipse" +eclipse { + classpath { + downloadSources = true + downloadJavadoc = true + } +} + apply plugin: "idea" +idea { + module { + downloadJavadoc = true + downloadSources = true + } +} -apply from: rootProject.file("gradle/springboot.gradle") -apply from: rootProject.file("gradle/dockerjib.gradle") +apply plugin: "org.sonarqube" +sonarqube { + properties { + property "sonar.projectKey", "CenterForOpenScience_osf-cas" + property "sonar.organization", "centerforopenscience" + property "sonar.host.url", "https://sonarcloud.io" + } +} dependencies { // Other CAS dependencies/modules may be listed here... @@ -153,27 +174,3 @@ configurations.all { } } } - -eclipse { - classpath { - downloadSources = true - downloadJavadoc = true - } -} - -idea { - module { - downloadJavadoc = true - downloadSources = true - } -} - -apply plugin: "org.sonarqube" - -sonarqube { - properties { - property "sonar.projectKey", "CenterForOpenScience_osf-cas" - property "sonar.organization", "centerforopenscience" - property "sonar.host.url", "https://sonarcloud.io" - } -} From 3055e2c7be10ba08229884ff13a09f1fffd47f5b Mon Sep 17 00:00:00 2001 From: Fitz Elliott Date: Tue, 29 Dec 2020 14:09:40 -0500 Subject: [PATCH 67/71] Add migration path for users from deactivated institutions * Add "Can't find my institution" link to institution sign-on page. This links to a new page that allows the user to logon w/ pre-existing OSF credentials or to send a reset-password email to their current email account. [ENG-2448] --- etc/cas/config/cas.properties | 1 + .../configuration/model/OsfUrlProperties.java | 5 ++ .../OsfCasSupportActionsConfiguration.java | 15 ++++ .../OsfCasLoginWebflowConfigurer.java | 43 ++++++++++ .../OsfAbstractLoginPreparationAction.java | 2 + .../OsfDefaultLoginPreparationAction.java | 14 ++++ ...rtedInstitutionLoginPreparationAction.java | 39 +++++++++ .../flow/support/OsfCasWebflowConstants.java | 8 ++ .../osf/web/support/OsfCasLoginContext.java | 4 + src/main/resources/messages.properties | 13 +++ src/main/resources/static/css/cas.css | 23 ++++++ .../templates/casInstitutionLoginView.html | 5 ++ .../casUnsupportedInstitutionLoginView.html | 79 +++++++++++++++++++ 13 files changed, 251 insertions(+) create mode 100644 src/main/java/io/cos/cas/osf/web/flow/login/OsfUnsupportedInstitutionLoginPreparationAction.java create mode 100644 src/main/resources/templates/casUnsupportedInstitutionLoginView.html diff --git a/etc/cas/config/cas.properties b/etc/cas/config/cas.properties index c6206a97..7054e796 100644 --- a/etc/cas/config/cas.properties +++ b/etc/cas/config/cas.properties @@ -69,6 +69,7 @@ cas.authn.osf-url.login-with-next=https://{{ .Values.osfDomain }}/login?next= cas.authn.osf-url.logout=https://{{ .Values.osfDomain }}/logout/ cas.authn.osf-url.resend-confirmation=https://{{ .Values.osfDomain }}/resend/ cas.authn.osf-url.forgot-password=https://{{ .Values.osfDomain }}/forgotpassword/ +cas.authn.osf-url.forgot-password-institution=https://{{ .Values.osfDomain }}/forgotpassword-institution/ cas.authn.osf-url.register=https://{{ .Values.osfDomain }}/register/ ######################################################################################################################## diff --git a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java index 4a09772f..627ce7b4 100644 --- a/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java +++ b/src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java @@ -61,6 +61,11 @@ public class OsfUrlProperties implements Serializable { */ private String forgotPassword; + /** + * OSF forgot-password-institutions page URL + */ + private String forgotPasswordInstitution; + /** * Build the default service URL using OSF login endpoint with OSF home page as destination. */ diff --git a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java index 95df58bd..67ca44c0 100644 --- a/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java +++ b/src/main/java/io/cos/cas/osf/web/config/OsfCasSupportActionsConfiguration.java @@ -3,6 +3,7 @@ import io.cos.cas.osf.dao.JpaOsfDao; import io.cos.cas.osf.web.flow.login.OsfDefaultLoginPreparationAction; import io.cos.cas.osf.web.flow.login.OsfInstitutionLoginPreparationAction; +import io.cos.cas.osf.web.flow.login.OsfUnsupportedInstitutionLoginPreparationAction; import io.cos.cas.osf.web.flow.login.OsfCasPreInitialFlowSetupAction; import io.cos.cas.osf.web.flow.login.OsfPrincipalFromNonInteractiveCredentialsAction; @@ -125,4 +126,18 @@ public Action osfInstitutionLoginCheckAction() { casProperties.getAuthn().getOsfPostgres().getInstitutionClients() ); } + + /** + * Bean configuration for {@link OsfUnsupportedInstitutionLoginPreparationAction}. + * + * @return the initialized action + */ + @Bean + public Action osfUnsupportedInstitutionLoginCheckAction() { + return new OsfUnsupportedInstitutionLoginPreparationAction( + initialAuthenticationAttemptWebflowEventResolver.getObject(), + serviceTicketRequestWebflowEventResolver.getObject(), + adaptiveAuthenticationPolicy.getObject() + ); + } } diff --git a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java index 9028baeb..7826aeb7 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java +++ b/src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java @@ -82,6 +82,7 @@ protected void createDefaultViewStates(final Flow flow) { createTwoFactorLoginFormView(flow); createTermsOfServiceConsentLoginFormView(flow); createInstitutionLoginView(flow); + createUnsupportedInstitutionLoginView(flow); createOrcidLoginAutoRedirectView(flow); createDefaultServiceLoginAutoRedirectView(flow); createOsfCasAuthenticationExceptionViewStates(flow); @@ -139,6 +140,7 @@ protected void createDefaultActionStates(final Flow flow) { // Create the customized interactive login check actions createOsfDefaultLoginCheckAction(flow); createOsfInstitutionLoginCheckAction(flow); + createOsfUnsupportedInstitutionLoginCheckAction(flow); // Create the customized non-interactive authentication check action createOsfNonInteractiveAuthenticationCheckAction(flow); } @@ -327,6 +329,11 @@ private void createOsfDefaultLoginCheckAction(final Flow flow) { OsfCasWebflowConstants.TRANSITION_ID_INSTITUTION_LOGIN, OsfCasWebflowConstants.STATE_ID_OSF_INSTITUTION_LOGIN_CHECK ); + createTransitionForState( + action, + OsfCasWebflowConstants.TRANSITION_ID_UNSUPPORTED_INSTITUTION_LOGIN, + OsfCasWebflowConstants.STATE_ID_OSF_UNSUPPORTED_INSTITUTION_LOGIN_CHECK + ); createTransitionForState( action, OsfCasWebflowConstants.TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT, @@ -367,6 +374,29 @@ private void createOsfInstitutionLoginCheckAction(final Flow flow) { ); } + /** + * Create the unsupported institution login check / preparation action for OSF CAS. + * + * @param flow the flow + */ + private void createOsfUnsupportedInstitutionLoginCheckAction(final Flow flow) { + ActionState action = createActionState( + flow, + OsfCasWebflowConstants.STATE_ID_OSF_UNSUPPORTED_INSTITUTION_LOGIN_CHECK, + OsfCasWebflowConstants.ACTION_ID_OSF_UNSUPPORTED_INSTITUTION_LOGIN_CHECK + ); + createTransitionForState( + action, + CasWebflowConstants.TRANSITION_ID_ERROR, + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_FAILED + ); + createTransitionForState( + action, + CasWebflowConstants.TRANSITION_ID_SUCCESS, + OsfCasWebflowConstants.VIEW_ID_UNSUPPORTED_INSTITUTION_SSO_INIT + ); + } + /** * Create extra authentication exception view states for OSF CAS. * @@ -506,4 +536,17 @@ protected void createInstitutionLoginView(final Flow flow) { OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_INIT ); } + + /** + * Create the institution SSO init view state to support the OSF feature "sign-in via institutions". + * + * @param flow the flow + */ + protected void createUnsupportedInstitutionLoginView(final Flow flow) { + createViewState( + flow, + OsfCasWebflowConstants.VIEW_ID_UNSUPPORTED_INSTITUTION_SSO_INIT, + OsfCasWebflowConstants.VIEW_ID_UNSUPPORTED_INSTITUTION_SSO_INIT + ); + } } diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java index f337502d..9751e49f 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java @@ -33,6 +33,8 @@ public abstract class OsfAbstractLoginPreparationAction extends AbstractAuthenti protected static final String PARAMETER_CAMPAIGN_VALUE = "institution"; + protected static final String PARAMETER_CAMPAIGN_UNSUPPORTED_INSTITUTION_VALUE = "unsupportedinstitution"; + protected static final String PARAMETER_INSTITUTION_ID = "institutionId"; protected static final String PARAMETER_ORCID_CLIENT_TYPE = "orcid"; diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java index a084040e..588505ce 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfDefaultLoginPreparationAction.java @@ -52,6 +52,7 @@ protected Event doExecute(RequestContext context) { final boolean institutionLogin = isInstitutionLogin(context); final String institutionId = getInstitutionIdFromRequestContext(context); + final boolean unsupportedInstitutionLogin = isUnsupportedInstitutionLogin(context); final boolean orcidRedirect = isOrcidLoginAutoRedirect(context); final String orcidLoginUrl = getOrcidLoginUrlFromFlowScope(context); @@ -74,6 +75,7 @@ protected Event doExecute(RequestContext context) { encodedServiceUrl, institutionLogin, institutionId, + unsupportedInstitutionLogin, orcidRedirect, orcidLoginUrl, defaultService, @@ -83,6 +85,7 @@ protected Event doExecute(RequestContext context) { loginContext.setDefaultServiceUrl(encodedServiceUrl); loginContext.setInstitutionLogin(institutionLogin); loginContext.setInstitutionId(institutionId); + loginContext.setUnsupportedInstitutionLogin(unsupportedInstitutionLogin); loginContext.setOrcidLoginUrl(orcidLoginUrl); loginContext.setOrcidRedirect(false); loginContext.setDefaultService(defaultService); @@ -98,6 +101,8 @@ protected Event doExecute(RequestContext context) { return error(); } else if (loginContext.isInstitutionLogin()) { return switchToInstitutionLogin(); + } else if (loginContext.isUnsupportedInstitutionLogin()) { + return switchToUnsupportedInstitutionLogin(); } else if (loginContext.isOrcidRedirect()) { if (StringUtils.isNotBlank(orcidLoginUrl)) { return autoRedirectToOrcidLogin(); @@ -119,6 +124,11 @@ private String getInstitutionIdFromRequestContext(final RequestContext context) return StringUtils.isNotBlank(institutionId) ? institutionId : null; } + private boolean isUnsupportedInstitutionLogin(final RequestContext context) { + final String campaign = context.getRequestParameters().get(PARAMETER_CAMPAIGN); + return StringUtils.isNotBlank(campaign) && PARAMETER_CAMPAIGN_UNSUPPORTED_INSTITUTION_VALUE.equals(campaign.toLowerCase()); + } + private boolean isOrcidLoginAutoRedirect(final RequestContext context) { final String orcidRedirect = context.getRequestParameters().get(PARAMETER_ORCID_REDIRECT); return StringUtils.isNotBlank(orcidRedirect) @@ -159,6 +169,10 @@ private Event switchToInstitutionLogin() { return new Event(this, OsfCasWebflowConstants.TRANSITION_ID_INSTITUTION_LOGIN); } + private Event switchToUnsupportedInstitutionLogin() { + return new Event(this, OsfCasWebflowConstants.TRANSITION_ID_UNSUPPORTED_INSTITUTION_LOGIN); + } + private Event autoRedirectToOrcidLogin() { return new Event(this, OsfCasWebflowConstants.TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT); } diff --git a/src/main/java/io/cos/cas/osf/web/flow/login/OsfUnsupportedInstitutionLoginPreparationAction.java b/src/main/java/io/cos/cas/osf/web/flow/login/OsfUnsupportedInstitutionLoginPreparationAction.java new file mode 100644 index 00000000..96c25d9b --- /dev/null +++ b/src/main/java/io/cos/cas/osf/web/flow/login/OsfUnsupportedInstitutionLoginPreparationAction.java @@ -0,0 +1,39 @@ +package io.cos.cas.osf.web.flow.login; + +import lombok.extern.slf4j.Slf4j; + +import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy; +import org.apereo.cas.web.flow.resolver.CasDelegatingWebflowEventResolver; +import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver; + +import org.springframework.webflow.execution.Event; +import org.springframework.webflow.execution.RequestContext; + +/** + * This is {@link OsfUnsupportedInstitutionLoginPreparationAction}. + * + * Extends {@link OsfAbstractLoginPreparationAction} to prepare the unsupported institution login page. + * + * @author Longze Chen + * @since 20.1.0 + */ +@Slf4j +public class OsfUnsupportedInstitutionLoginPreparationAction extends OsfAbstractLoginPreparationAction { + + public OsfUnsupportedInstitutionLoginPreparationAction( + final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver, + final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, + final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy + ) { + super( + initialAuthenticationAttemptWebflowEventResolver, + serviceTicketRequestWebflowEventResolver, + adaptiveAuthenticationPolicy + ); + } + + @Override + protected Event doExecute(RequestContext context) { + return success(); + } +} diff --git a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java index fab9fc8c..e7d22051 100644 --- a/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java +++ b/src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java @@ -20,10 +20,14 @@ public interface OsfCasWebflowConstants { String ACTION_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheckAction"; + String ACTION_ID_OSF_UNSUPPORTED_INSTITUTION_LOGIN_CHECK = "osfUnsupportedInstitutionLoginCheckAction"; + String TRANSITION_ID_USERNAME_PASSWORD_LOGIN = "continueToUsernamePasswordLogin"; String TRANSITION_ID_INSTITUTION_LOGIN = "switchToInstitutionLogin"; + String TRANSITION_ID_UNSUPPORTED_INSTITUTION_LOGIN = "switchToUnsupportedInstitutionLogin"; + String TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT = "autoRedirectToOrcidLogin"; String TRANSITION_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT = "autoRedirectToDefaultServiceLogin"; @@ -34,8 +38,12 @@ public interface OsfCasWebflowConstants { String STATE_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheck"; + String STATE_ID_OSF_UNSUPPORTED_INSTITUTION_LOGIN_CHECK = "osfUnsupportedInstitutionLoginCheck"; + String VIEW_ID_INSTITUTION_SSO_INIT = "casInstitutionLoginView"; + String VIEW_ID_UNSUPPORTED_INSTITUTION_SSO_INIT = "casUnsupportedInstitutionLoginView"; + String VIEW_ID_ORCID_LOGIN_AUTO_REDIRECT = "casAutoRedirectToOrcidLoginView"; String VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT = "casAutoRedirectToDefaultServiceLoginView"; diff --git a/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java b/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java index da17380e..35bdd22b 100644 --- a/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java +++ b/src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java @@ -40,6 +40,8 @@ public class OsfCasLoginContext implements Serializable { private String institutionId; + private boolean unsupportedInstitutionLogin; + private boolean orcidRedirect; private String orcidLoginUrl; @@ -57,6 +59,7 @@ public OsfCasLoginContext ( final String encodedServiceUrl, final boolean institutionLogin, final String institutionId, + final boolean unsupportedInstitutionLogin, final boolean orcidRedirect, final String orcidLoginUrl, final boolean defaultService, @@ -66,6 +69,7 @@ public OsfCasLoginContext ( this.handleErrorName = null; this.institutionLogin = institutionLogin; this.institutionId = institutionId; + this.unsupportedInstitutionLogin = unsupportedInstitutionLogin; this.orcidRedirect = orcidRedirect; this.orcidLoginUrl = orcidLoginUrl; this.defaultService = defaultService; diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 26958b69..108be9d0 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -582,11 +582,24 @@ screen.institutionlogin.tips=Sign in through your institution screen.institutionlogin.message.select=If your institution has partnered with OSF, please select its name below and sign in with your institutional credentials. If you do not currently have an OSF account, this will create one for you. screen.institutionlogin.message.auto=Your institution has partnered with OSF. Please continue to sign in with your institutional credentials. If you do not currently have an OSF account, this will create one for you. screen.institutionlogin.heading.select=Select your institution +screen.institutionlogin.select.unsupported=I can't find my institution screen.institutionlogin.heading.auto=Your institution screen.institutionlogin.link.select=Not your institution? screen.institutionlogin.button.submit=Sign in screen.institutionlogin.osf=Sign in with your OSF account # +# Unsupported Institution +# +screen.unsupportedinstitutionlogin.heading=I can't find my institution +screen.unsupportedinstitutionlogin.message=Signing into the OSF with institutional credentials is enabled for OSF Institutions members. If your institution is not yet an OSFI member, choose one of the following sign-in methods. +screen.unsupportedinstitutionlogin.existing.heading=I already have an OSF account +screen.unsupportedinstitutionlogin.existing.osf.message=If you have already have an OSF password, you can sign in to the OSF +screen.unsupportedinstitutionlogin.existing.osf.button=Sign in with OSF +screen.unsupportedinstitutionlogin.existing.institution.message=If you have not yet set an OSF password for your account, create a password +screen.unsupportedinstitutionlogin.existing.institution.button=Set a password +screen.unsupportedinstitutionlogin.existing.institution.label.email=Email +screen.unsupportedinstitutionlogin.existing.institution.label.email.accesskey=e +# # Generic login and logout success page # screen.generic.logoutsuccess.title=Signed-out diff --git a/src/main/resources/static/css/cas.css b/src/main/resources/static/css/cas.css index ce73f61a..db48452f 100644 --- a/src/main/resources/static/css/cas.css +++ b/src/main/resources/static/css/cas.css @@ -945,6 +945,29 @@ body { margin: 0.25rem 0; } +#unknown-institution-login, #unknown-institution-login:active { + background-image: linear-gradient(to bottom, #2bc1f3 0, #337591 100%); + color: white; + font-weight: bold; +} + +#unknown-institution-login:hover { + cursor: pointer; + -webkit-box-shadow: 0px 0px 5px 0px #337591; + -moz-box-shadow: 0px 0px 5px 0px #337591; + box-shadow: 0px 0px 5px 0px #337591; +} + +#unknown-institution-login .label-login { + opacity: 0.9; + font-size: 1em; +} + +.unsupported-inst-body-header { + font-weight: bold; + font-size: 110%; +} + .cas-field-primary { margin-bottom: 1rem!important; margin-top: 0.5rem!important; diff --git a/src/main/resources/templates/casInstitutionLoginView.html b/src/main/resources/templates/casInstitutionLoginView.html index 5d133168..d86bdb0a 100644 --- a/src/main/resources/templates/casInstitutionLoginView.html +++ b/src/main/resources/templates/casInstitutionLoginView.html @@ -56,6 +56,11 @@
+
+ + +
+
From 71cc430a3df6e617a4ed12901eb4a7065f6dd2ec Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Tue, 2 Feb 2021 18:59:11 -0500 Subject: [PATCH 70/71] We are in 2021 --- src/main/resources/messages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 838b88d7..2a528982 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -516,7 +516,7 @@ cas.login.resources.osf.donate=Donate # # Footer # -copyright.cos=Copyright © 2011 – 2020 \ +copyright.cos=Copyright © 2011 – 2021 \ Center for Open Science | \ Terms of Use | \ Privacy Policy | \ From 9d3f224d699259b306e7b7ab07f1a8b84396b5fb Mon Sep 17 00:00:00 2001 From: longze chen Date: Wed, 3 Feb 2021 12:34:33 -0500 Subject: [PATCH 71/71] Update change log for release/21.0.0 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e67b06..510d48ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO. +21.0.0 (02-03-2020) +=================== + +OSF CAS third release with web flow updates, institution SSO, and FE rework + +* Login and logout web flow fixes and improvements +* Fully functional institution SSO, BE and FE +* FE rework and UI / UX improvements + +Extra features + +* Institution SSO migration +* TOS consent check +* SonarQube integraiton + 20.1.0 (11-05-2020) ===================