-
Notifications
You must be signed in to change notification settings - Fork 533
Login page and Shibboleth auth refactored to work with new InCommon services #11502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
64281c7
409f98d
dbced9e
16c0055
b48a228
a490c39
fbc1187
c0ecc47
888cd15
5315252
902a6e5
4ecb090
daf1b1d
8eac72b
b61e09c
8227650
ae9e59a
4b50330
44390ff
055f32f
4b156c1
8fbef19
ec397eb
1a967b8
b43f889
a507380
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| ### For Dataverse instances that use Shibboleth as members of InCommon federation | ||
|
|
||
| Please note that most of the known Dataverse instances that support Shibboleth logins do so without being part of InCommon, and therefore are not affected. All such instances will be able to continue using the old login workflow without needing to make any configuration changes. | ||
|
|
||
| For the relatively few instances using InCommon: Since InCommon discontinued their old-style federation metadata feed, a new Shibboleth implementation have been added to utilize the recommended replacements: the MDQ protocol and the WayFinder service. In order to continue using InCommon, such instances will need to modify their shibd configuration and their registration with Incommon, plus set a new feature flag. See the upgrade instruction for details. | ||
|
|
||
|
|
||
| ### New Settings | ||
|
|
||
| - dataverse.feature.shibboleth-use-wayfinder | ||
| - dataverse.feature.shibboleth-use-localhost | ||
|
|
||
| ### For the Upgrade Instruction: | ||
|
|
||
| [(strip this from the real release note) this should be the very last of the optional upgrade steps; as it's been pointed out to me that there may be not be any instances affected by this aside from Harvard and UNC, both of which have been active participants in the development of the underlying code and the upgrade process below. ... which kind of makes including them in the release note somewhat unnecessary (?). but I figure we should include them anyway, in case there's an instance out there we are not aware of. - L.A.] | ||
ofahimIQSS marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| If your instance is offering institutional Shibboleth logins as part of the InCommon federation, you must make some changes to your service configuration: | ||
|
|
||
| Note that if your Dataverse instance is using Shibboleth outside of InCommon, your login workflow should continue working unchanged, so please skip this section. | ||
|
|
||
| a. Configure your Service Provider (SP) in the InCommon Federation Manager to use WayFinder following [their instructions](https://spaces.at.internet2.edu/display/federation/how-to-configure-service-to-use-wayfinder). | ||
|
|
||
| b. Reconfigure your locally-running `shibd` service to use WayFinder and the new MDQ metadata retrieval protocol. | ||
| Download and place the new [production signing key](https://spaces.at.internet2.edu/display/MDQ/production-mdq-signing-key) in `/etc/shibboleth` and name it `inc-md-cert-mdq.pem`. | ||
| Change the `SSO` and `MetadataProvider` sections of the `/etc/shibboleth/shibboleth2.xml` configuration file as follows: | ||
|
|
||
| ``` | ||
| <SSO discoveryProtocol="SAMLDS" discoveryURL="https://wayf.incommonfederation.org/DS/WAYF"> | ||
| SAML2 SAML1 | ||
| </SSO> | ||
| ``` | ||
| and | ||
| ``` | ||
| <MetadataProvider type="MDQ" id="incommon" ignoreTransport="true" cacheDirectory="inc-mdq-cache" | ||
| maxCacheDuration="86400" minCacheDuration="60" baseUrl="https://mdq.incommon.org/"> | ||
| <MetadataFilter type="Signature" certificate="inc-md-cert-mdq.pem"/> | ||
| <MetadataFilter type="RequireValidUntil" maxValidityInterval="1209600"/> | ||
| </MetadataProvider> | ||
| ``` | ||
| See [How to configure a Shibboleth service provider (SP) to use MDQ](https://spaces.at.internet2.edu/display/MDQ/how-to-configure-shib-sp-to-use-mdq) for more information. | ||
|
|
||
| c. Set the feature flag `dataverse.feature.shibboleth-use-wayfinder=true`. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,8 +17,12 @@ | |
| import edu.harvard.iq.dataverse.authorization.providers.oauth2.OAuth2AuthenticationProviderFactory; | ||
| import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.OrcidOAuth2AP; | ||
| import edu.harvard.iq.dataverse.authorization.providers.oauth2.oidc.OIDCAuthenticationProviderFactory; | ||
| import edu.harvard.iq.dataverse.authorization.providers.shib.ShibAuthenticationProvider; | ||
| import edu.harvard.iq.dataverse.authorization.providers.shib.ShibAuthenticationProviderFactory; | ||
| import edu.harvard.iq.dataverse.settings.FeatureFlags; | ||
| import edu.harvard.iq.dataverse.settings.JvmSettings; | ||
| import edu.harvard.iq.dataverse.settings.SettingsServiceBean; | ||
| import edu.harvard.iq.dataverse.util.SystemConfig; | ||
| import edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
@@ -33,6 +37,16 @@ | |
| import jakarta.inject.Named; | ||
| import jakarta.persistence.EntityManager; | ||
| import jakarta.persistence.PersistenceContext; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.io.InputStreamReader; | ||
| import java.net.HttpURLConnection; | ||
| import java.net.MalformedURLException; | ||
| import java.net.URL; | ||
| import javax.xml.stream.XMLInputFactory; | ||
| import javax.xml.stream.XMLStreamConstants; | ||
| import javax.xml.stream.XMLStreamException; | ||
| import javax.xml.stream.XMLStreamReader; | ||
|
|
||
| /** | ||
| * | ||
|
|
@@ -63,6 +77,9 @@ public class AuthenticationProvidersRegistrationServiceBean { | |
| @EJB | ||
| AuthenticationServiceBean authenticationService; | ||
|
|
||
| @EJB | ||
| SettingsServiceBean settingsService; | ||
|
|
||
| /** | ||
| * The maps below (the objects themselves) are "final", but the | ||
| * values will be populated in @PostConstruct (see below) during | ||
|
|
@@ -117,7 +134,32 @@ public void startup() { | |
| .getResultList().forEach((row) -> { | ||
| if(row.isEnabled()) { | ||
| try { | ||
| registerProvider( loadProvider(row) ); | ||
| AuthenticationProvider authProvider = loadProvider(row); | ||
|
|
||
| registerProvider( authProvider ); | ||
|
|
||
| // For production Shibboleth instances that are not using | ||
| // the legacy DiscoFeed-based workflow, we need to call | ||
| // shibd to look up and cache its entityID, since it will | ||
| // be needed in order to issue WayFinder service redirects. | ||
|
|
||
| if ("shib".equals(authProvider.getId()) | ||
| && FeatureFlags.SHIBBOLETH_USE_WAYFINDER.enabled()) { | ||
| // ... is this a prod. shibboleth instance? | ||
| String shibTypeSetting = settingsService.getValueForKey(SettingsServiceBean.Key.DebugShibAccountType, null); | ||
| boolean isProduction = shibTypeSetting == null || shibTypeSetting.equals("PRODUCTION"); | ||
|
|
||
| if (isProduction) { | ||
| String spEntityId = lookupShibbolethEntityId(); | ||
| logger.info("Looked up the entityId of the shibboleth service provider (via a call to shibd): " | ||
| + spEntityId); | ||
| if (spEntityId == null) { | ||
| // we'll make this educated guess - it may or may not help us later on: | ||
| spEntityId = SystemConfig.getDataverseSiteUrlStatic() + "/sp"; | ||
| } | ||
| ((ShibAuthenticationProvider) authProvider).setServiceProviderEntityId(spEntityId); | ||
| } | ||
| } | ||
|
|
||
| } catch ( AuthenticationProviderFactoryNotFoundException e ) { | ||
| logger.log(Level.SEVERE, "Cannot find authentication provider factory with alias '" + e.getFactoryAlias() + "'",e); | ||
|
|
@@ -307,5 +349,75 @@ public boolean isOrcidEnabled() { | |
| return oAuth2authenticationProviders.values().stream().anyMatch( s -> s.getId().toLowerCase().contains("orcid") ); | ||
| } | ||
| */ | ||
|
|
||
| private String lookupShibbolethEntityId() { | ||
|
|
||
| String baseUrl; | ||
| if (FeatureFlags.SHIBBOLETH_USE_LOCALHOST.enabled()) { | ||
| baseUrl = "http://localhost"; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It actually needs to be |
||
| } else { | ||
| baseUrl = SystemConfig.getDataverseSiteUrlStatic(); | ||
| } | ||
|
|
||
| String urlString = baseUrl + "/Shibboleth.sso/Metadata"; | ||
|
|
||
| URL url = null; | ||
| try { | ||
| url = new URL(urlString); | ||
| } catch (MalformedURLException ex) { | ||
| logger.warning(ex.toString()); | ||
| return null; | ||
| } | ||
|
|
||
| if (url == null) { | ||
| logger.warning("url object was null after parsing " + urlString); | ||
| return null; | ||
| } | ||
|
|
||
| HttpURLConnection metadataRequest = null; | ||
| try { | ||
| metadataRequest = (HttpURLConnection) url.openConnection(); | ||
| } catch (IOException ex) { | ||
| logger.warning(ex.toString()); | ||
| return null; | ||
| } | ||
| if (metadataRequest == null) { | ||
| logger.warning("http request was null for a local /Shibboleth.sso/Metadata call"); | ||
| return null; | ||
| } | ||
| try { | ||
| metadataRequest.connect(); | ||
| } catch (IOException ex) { | ||
| logger.warning(ex.toString()); | ||
| return null; | ||
| } | ||
|
|
||
| XMLStreamReader xmlr = null; | ||
|
|
||
| try { | ||
| XMLInputFactory xmlFactory = javax.xml.stream.XMLInputFactory.newInstance(); | ||
| xmlr = xmlFactory.createXMLStreamReader(new InputStreamReader((InputStream) metadataRequest.getInputStream())); | ||
github-advanced-security[bot] marked this conversation as resolved.
Dismissed
Show dismissed
Hide dismissed
|
||
|
|
||
| while ( xmlr.next() == XMLStreamConstants.COMMENT); | ||
| xmlr.require(XMLStreamConstants.START_ELEMENT, null, "EntityDescriptor"); | ||
|
|
||
| return xmlr.getAttributeValue(null, "entityID"); | ||
|
|
||
| } catch (IOException ioex) { | ||
| logger.warning("IOException instantiating a stream reader of the /Shibboleth.sso/Metadata output" + ioex.getMessage()); | ||
| } catch (XMLStreamException xsex) { | ||
| logger.warning("Failed to parse the xml output of the /Shibboleth.sso/Metadata; " + xsex.getMessage()); | ||
| } finally { | ||
| if (xmlr != null) { | ||
| try { | ||
| logger.fine("closing xml reader"); | ||
| xmlr.close(); | ||
| } catch (XMLStreamException xsex) { | ||
| // we don't care | ||
| } | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -213,7 +213,7 @@ public String init() { | |
| } else { | ||
| return permissionsWrapper.notAuthorized(); | ||
| } | ||
|
|
||
| return ""; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.