From c93d5ada2e5a6c3ad47de096c76fc815a32c484c Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Sep 2025 15:59:06 -0400 Subject: [PATCH 1/3] Handle institution SSO multiple emails not supported error --- ...soMultipleEmailsNotSupportedException.java | 31 ++++++++++++ .../support/OsfApiPermissionDenied.java | 4 +- .../OsfCasCoreWebflowConfiguration.java | 2 + .../OsfCasLoginWebflowConfigurer.java | 11 +++++ ...alFromNonInteractiveCredentialsAction.java | 5 ++ .../flow/support/OsfCasWebflowConstants.java | 2 + src/main/resources/messages.properties | 5 ++ ...tionSsoMultipleEmailsNotSupportedView.html | 49 +++++++++++++++++++ 8 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java create mode 100644 src/main/resources/templates/casInstitutionSsoMultipleEmailsNotSupportedView.html diff --git a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java new file mode 100644 index 00000000..6d831de9 --- /dev/null +++ b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java @@ -0,0 +1,31 @@ +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 + * due to OSF API not supporting multiple SSO emails. + * + * @author Longze Chen + * @since 25.0.0 + */ +@NoArgsConstructor +public class InstitutionSsoMultipleEmailsNotSupportedException extends AccountException { + + /** + * Serialization metadata. + */ + + private static final long serialVersionUID = -7703550523317297865L; + + /** + * Instantiates a new {@link InstitutionSsoMultipleEmailsNotSupportedException}. + * + * @param msg the msg + */ + public InstitutionSsoMultipleEmailsNotSupportedException(final String msg) { + super(msg); + } +} diff --git a/src/main/java/io/cos/cas/osf/authentication/support/OsfApiPermissionDenied.java b/src/main/java/io/cos/cas/osf/authentication/support/OsfApiPermissionDenied.java index cf69beca..88b7d25a 100644 --- a/src/main/java/io/cos/cas/osf/authentication/support/OsfApiPermissionDenied.java +++ b/src/main/java/io/cos/cas/osf/authentication/support/OsfApiPermissionDenied.java @@ -10,9 +10,11 @@ public enum OsfApiPermissionDenied { DEFAULT("PermissionDenied"), + INSTITUTION_SSO_ACCOUNT_INACTIVE("InstitutionSsoAccountInactive"), + INSTITUTION_SSO_DUPLICATE_IDENTITY("InstitutionSsoDuplicateIdentity"), - INSTITUTION_SSO_ACCOUNT_INACTIVE("InstitutionSsoAccountInactive"), + INSTITUTION_SSO_MULTIPLE_EMAILS_NOT_SUPPORTED("InstitutionSsoMultipleEmailsNotSupported"), INSTITUTION_SSO_SELECTIVE_LOGIN_DENIED("InstitutionSsoSelectiveLoginDenied"); 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 cdfea1e7..7014d3d0 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 @@ -7,6 +7,7 @@ import io.cos.cas.osf.authentication.exception.InstitutionSsoAttributeParsingException; import io.cos.cas.osf.authentication.exception.InstitutionSsoDuplicateIdentityException; import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; +import io.cos.cas.osf.authentication.exception.InstitutionSsoMultipleEmailsNotSupportedException; import io.cos.cas.osf.authentication.exception.InstitutionSsoOsfApiFailedException; import io.cos.cas.osf.authentication.exception.InstitutionSsoSelectiveLoginDeniedException; import io.cos.cas.osf.authentication.exception.InvalidOneTimePasswordException; @@ -53,6 +54,7 @@ public Set> handledAuthenticationExceptions() { errors.add(InstitutionSsoAttributeParsingException.class); errors.add(InstitutionSsoDuplicateIdentityException.class); errors.add(InstitutionSsoFailedException.class); + errors.add(InstitutionSsoMultipleEmailsNotSupportedException.class); errors.add(InstitutionSsoOsfApiFailedException.class); errors.add(InstitutionSsoSelectiveLoginDeniedException.class); errors.add(InvalidOneTimePasswordException.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 8144ca74..d232f6db 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.InstitutionSsoAttributeParsingException; import io.cos.cas.osf.authentication.exception.InstitutionSsoDuplicateIdentityException; import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; +import io.cos.cas.osf.authentication.exception.InstitutionSsoMultipleEmailsNotSupportedException; import io.cos.cas.osf.authentication.exception.InstitutionSsoOsfApiFailedException; import io.cos.cas.osf.authentication.exception.InstitutionSsoSelectiveLoginDeniedException; import io.cos.cas.osf.authentication.exception.InvalidOneTimePasswordException; @@ -270,6 +271,11 @@ protected void createHandleAuthenticationFailureAction(final Flow flow) { InstitutionSsoSelectiveLoginDeniedException.class.getSimpleName(), OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_SELECTIVE_LOGIN_DENIED ); + createTransitionForState( + handler, + InstitutionSsoMultipleEmailsNotSupportedException.class.getSimpleName(), + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_MULTIPLE_EMAILS_NOT_SUPPORTED + ); createTransitionForState( handler, InvalidUserStatusException.class.getSimpleName(), @@ -470,6 +476,11 @@ private void createOsfCasAuthenticationExceptionViewStates(final Flow flow) { OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_SELECTIVE_LOGIN_DENIED, OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_SELECTIVE_LOGIN_DENIED ); + createViewState( + flow, + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_MULTIPLE_EMAILS_NOT_SUPPORTED, + OsfCasWebflowConstants.VIEW_ID_INSTITUTION_SSO_MULTIPLE_EMAILS_NOT_SUPPORTED + ); } /** 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 38b2742d..92eeca73 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 @@ -12,6 +12,7 @@ import io.cos.cas.osf.authentication.exception.InstitutionSsoAttributeParsingException; import io.cos.cas.osf.authentication.exception.InstitutionSsoDuplicateIdentityException; import io.cos.cas.osf.authentication.exception.InstitutionSsoFailedException; +import io.cos.cas.osf.authentication.exception.InstitutionSsoMultipleEmailsNotSupportedException; import io.cos.cas.osf.authentication.exception.InstitutionSsoSelectiveLoginDeniedException; import io.cos.cas.osf.authentication.exception.InstitutionSsoOsfApiFailedException; import io.cos.cas.osf.authentication.support.DelegationProtocol; @@ -791,6 +792,10 @@ private OsfApiInstitutionAuthenticationResult notifyOsfApiOfInstnAuthnSuccess( LOGGER.error("[OSF API] Failure - Inactive Account: {}", ssoUser); throw new InstitutionSsoAccountInactiveException("OSF API denies inactive account"); } + if (OsfApiPermissionDenied.INSTITUTION_SSO_MULTIPLE_EMAILS_NOT_SUPPORTED.getId().equals(errorDetail)) { + LOGGER.error("[OSF API] Failure - Multiple SSO Emails Error: {}", ssoUser); + throw new InstitutionSsoMultipleEmailsNotSupportedException("OSF API can't process multiple SSO emails"); + } } // Handle unidentified HTTP 403 FORBIDDEN failures LOGGER.error("[OSF API] Failure - HTTP 403 FORBIDDEN: {}, statusCode={}", ssoUser, statusCode); 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 43c4ad0d..6f938981 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 @@ -76,6 +76,8 @@ public interface OsfCasWebflowConstants { String VIEW_ID_INSTITUTION_SSO_SELECTIVE_LOGIN_DENIED = "casInstitutionSsoSelectiveLoginDeniedView"; + String VIEW_ID_INSTITUTION_SSO_MULTIPLE_EMAILS_NOT_SUPPORTED = "casInstitutionSsoMultipleEmailsNotSupportedView"; + // Exception Views for OAuth 2.0 Authorization Flow String VIEW_ID_OAUTH_20_ERROR_VIEW = "casOAuth20ErrorView"; diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 4e99c955..b051bb89 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -721,6 +721,11 @@ screen.institutionssoosfapifailed.message=\ Your request cannot be completed at this time due to an unexpected error. \ Please return to OSF and try again later. \ If the issue persists, contact Support for help. +screen.institutionssomultipleemailsnotsupported.message=\ + Your request cannot be completed at this time. \ + The system received multiple SSO emails from your institution. \ + Please return to OSF and try again later. \ + If the issue persists, contact Support for help. # # OAuth 2.0 Views and Error Views diff --git a/src/main/resources/templates/casInstitutionSsoMultipleEmailsNotSupportedView.html b/src/main/resources/templates/casInstitutionSsoMultipleEmailsNotSupportedView.html new file mode 100644 index 00000000..829a6cd5 --- /dev/null +++ b/src/main/resources/templates/casInstitutionSsoMultipleEmailsNotSupportedView.html @@ -0,0 +1,49 @@ + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ + + From 4073df1880ae52083ec52fb1178844ade5e5423d Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Sep 2025 16:28:29 -0400 Subject: [PATCH 2/3] Fix GitHub action version deprecation --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c60f2a65..631da93a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,13 +18,13 @@ jobs: with: java-version: 11 - name: Cache SonarCloud packages - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Gradle packages - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} From 54266d4805a273eec20ffcdafbd7d1d75b8aa8fc Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Mon, 1 Sep 2025 16:43:11 -0400 Subject: [PATCH 3/3] Fix linting --- .../InstitutionSsoMultipleEmailsNotSupportedException.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java index 6d831de9..d3283b04 100644 --- a/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java +++ b/src/main/java/io/cos/cas/osf/authentication/exception/InstitutionSsoMultipleEmailsNotSupportedException.java @@ -17,7 +17,6 @@ public class InstitutionSsoMultipleEmailsNotSupportedException extends AccountEx /** * Serialization metadata. */ - private static final long serialVersionUID = -7703550523317297865L; /**