From df8a84cbc9f24f3b75342d5b19db97f8f52395d8 Mon Sep 17 00:00:00 2001 From: jgiwinski <juliaiwinski@gmail.com> Date: Mon, 5 Feb 2024 12:07:36 -0700 Subject: [PATCH] add queries for display name and entity logo --- src/App.js | 116 +++++++++++++++++++++++++++++---- src/assets/stylesheets/App.css | 18 +++++ 2 files changed, 123 insertions(+), 11 deletions(-) diff --git a/src/App.js b/src/App.js index 8506281..e29d757 100644 --- a/src/App.js +++ b/src/App.js @@ -6,6 +6,8 @@ function App() { const [entityID, setEntityID] = useState(''); const [returnUrl, setReturnUrl] = useState(''); + const [displayName, setDisplayName] = useState(''); + const [entityLogo, setEntityLogo] = useState(''); const [error, setError] = useState(''); useEffect(() => { @@ -24,12 +26,97 @@ function App() { const entityIdParam = queryParams.entityID || ''; const returnUrlParam = queryParams.return || ''; + // Encode entityID from URL + const URLencodedEntityID = encodeURIComponent(entityIdParam) + if (!entityIdParam || !returnUrlParam) { setError('Both Entity ID and return URL are required.'); } else { setEntityID(entityIdParam); setReturnUrl(returnUrlParam); } + + // Fetch metadata for display name and logo + fetch(`https://mdq.incommon.org/entities/${URLencodedEntityID}`) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.text(); + }) + .then(metadata => { + const parser = new DOMParser(); + const xmlDoc = parser.parseFromString(metadata, "application/xml"); + + const displayNameNSxPath = "//*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:metadata' and local-name()='EntityDescriptor']//*[namespace-uri()='urn:oasis:names:tc:SAML:metadata:ui' and local-name()='UIInfo'][1]//*[namespace-uri()='urn:oasis:names:tc:SAML:metadata:ui' and local-name()='DisplayName'][1]"; + const logoNSxPath = "//*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:metadata' and local-name()='EntityDescriptor']//*[namespace-uri()='urn:oasis:names:tc:SAML:metadata:ui' and local-name()='UIInfo'][1]//*[namespace-uri()='urn:oasis:names:tc:SAML:metadata:ui' and local-name()='Logo'][1]"; + + let displayNameResult = xmlDoc.evaluate(displayNameNSxPath, xmlDoc, null, XPathResult.ANY_TYPE, null); + let logoResult = xmlDoc.evaluate(logoNSxPath, xmlDoc, null, XPathResult.ANY_TYPE, null); + + let extractedDisplayName; + let extractedLogo; + + // Check display name + switch (displayNameResult.resultType) { + case XPathResult.STRING_TYPE: + extractedDisplayName = displayNameResult.stringValue; + break; + case XPathResult.NUMBER_TYPE: + extractedDisplayName = displayNameResult.numberValue; + break; + case XPathResult.BOOLEAN_TYPE: + extractedDisplayName = displayNameResult.booleanValue; + break; + case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: + const firstNode = displayNameResult.iterateNext(); + if (firstNode) { + extractedDisplayName = firstNode.textContent; + } + break; + case XPathResult.ORDERED_NODE_ITERATOR_TYPE: + const node = displayNameResult.iterateNext(); + if (node) { + extractedDisplayName = node.textContent; + } + break; + default: + break; + } + + // Check logo + switch (logoResult.resultType) { + case XPathResult.STRING_TYPE: + extractedLogo = logoResult.stringValue; + break; + case XPathResult.NUMBER_TYPE: + extractedLogo = logoResult.numberValue; + break; + case XPathResult.BOOLEAN_TYPE: + extractedLogo = logoResult.booleanValue; + break; + case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: + const firstNode = logoResult.iterateNext(); + if (firstNode) { + extractedLogo = firstNode.textContent; + } + break; + case XPathResult.ORDERED_NODE_ITERATOR_TYPE: + const node = logoResult.iterateNext(); + if (node) { + extractedLogo = node.textContent; + } + break; + default: + break; + } + + setDisplayName(extractedDisplayName) + setEntityLogo(extractedLogo) + }) + .catch(error => { + console.error("Error fetching metadata:", error); + }); }, []); return ( @@ -43,16 +130,23 @@ function App() { <p><a href="https://incommon.org/help/" target="_blank">Click Here</a> for more information.</p> </> ) : ( - <> - <a href={`https://service.seamlessaccess.org/ds/?entityID=${entityID}&return=${returnUrl}`} className="d-flex sa-button"> - <div className="sa-button-logo-wrap"> - <img src="https://service.seamlessaccess.org/sa-white.svg" alt="Seamless Access Logo" className="sa-button-logo"/> - </div> - <div className="d-flex justify-content-center align-items-center sa-button-text text-truncate"> - <div className="sa-button-text-primary text-truncate">Access through your institution</div> - </div> - </a> - </> + <div id="login" className="d-flex column align-items-center"> + <div> + <p>You are being asked to login to the following service: {displayName}</p> + <img src={entityLogo} className="entity-logo" alt={`${displayName} Logo`} /> + </div> + <div className="d-flex column align-items-center"> + <p>Please select your home organization using the button below.</p> + <a href={`https://service.seamlessaccess.org/ds/?entityID=${entityID}&return=${returnUrl}`} className="d-flex sa-button"> + <div className="sa-button-logo-wrap"> + <img src="https://service.seamlessaccess.org/sa-white.svg" alt="Seamless Access Logo" className="sa-button-logo"/> + </div> + <div className="d-flex justify-content-center align-items-center sa-button-text text-truncate"> + <div className="sa-button-text-primary text-truncate">Access through your institution</div> + </div> + </a> + </div> + </div> )} </div> <div> @@ -61,7 +155,7 @@ function App() { <a href="https://internet2.edu/community/about-us/policies/privacy/" className="last" target="_blank">Data Privacy</a> <a href="https://incommon.org/help/" className="last" target="_blank">Help</a> </div> - <p>© Copyright 2020, InCommon, LLC | incommon.org | InCommon: Identity and Access for Research and Education</p> + <p className="copyright">© Copyright 2020, InCommon, LLC | incommon.org | InCommon: Identity and Access for Research and Education</p> </div> </div> </div> diff --git a/src/assets/stylesheets/App.css b/src/assets/stylesheets/App.css index a6d966a..c71ada9 100644 --- a/src/assets/stylesheets/App.css +++ b/src/assets/stylesheets/App.css @@ -24,6 +24,12 @@ html, body { margin: 100px 0; } +.entity-logo { + height: 20px; + margin-top: 20px; + margin-bottom: 50px; +} + .container { width: 75%; height: 100%; @@ -32,6 +38,10 @@ html, body { padding: 0 40px; } +.copyright { + font-size: small; +} + /* Flexbox properties */ .d-flex { display: flex; @@ -287,6 +297,10 @@ header { text-align: center; } +#login p { + margin-bottom: 0; +} + footer { width: 100%; display: flex; @@ -404,4 +418,8 @@ footer { float: left; list-style: none; } + .logo { + height: 35px; + margin: 50px 0; + } }