import React, { useState, useEffect } from 'react' import './assets/stylesheets/App.css'; import logo from './assets/images/IC-logo.svg' function App() { const [entityID, setEntityID] = useState(''); const [returnUrl, setReturnUrl] = useState(''); const [displayName, setDisplayName] = useState(''); const [entityLogo, setEntityLogo] = useState(''); const [error, setError] = useState(''); useEffect(() => { // Function to get query parameters from the URL const getQueryParams = () => { const queryParams = {}; window.location.search.substring(1).split('&').forEach(param => { const [key, value] = param.split('='); queryParams[key] = decodeURIComponent(value); }); return queryParams; }; // Get query parameters from the URL const queryParams = getQueryParams(); 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 ( <div className="app d-flex justify-content-center"> <div className="d-flex column justify-content-between align-items-center container"> <div className="d-flex column align-items-center"> <img src={logo} className="logo" alt="InCommon-Logo" /> {error ? ( <> <h1>{error}</h1> <p><a href="https://incommon.org/help/" target="_blank">Click Here</a> for more information.</p> </> ) : ( <div id="login" className="d-flex column align-items-center"> <p>You are accessing the following service: <strong>{displayName}</strong></p> <div className="d-flex column align-items-center"> <p className="bottom-0">Select your home organization:</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> <div id="menu"> <a href="https://incommon.org/federation/" target="_blank">About the InCommon Federation</a> <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 className="copyright">© Copyright 2024, InCommon, LLC | incommon.org | InCommon: Identity and Access for Research and Education</p> </div> </div> </div> ); } export default App;