Skip to content
Snippets Groups Projects
Select Git revision
  • fa1bd39b280ad4162f42b4fd8c77ba8f56a1a1c0
  • main default protected
2 results

shibd_discofeed.class.php

Blame
  • shibd_discofeed.class.php 5.52 KiB
    <?php
    /**
     * ======================================================================
     * 
     * AAI LOGIN WITH SHIBBOLETH HANDLING MULTIPLE ORGANIZATIONS
     * 
     * included functions
     * License: GNU GPL 3.0
     * Source: https://git-repo.iml.unibe.ch/iml-open-source/login-aai
     * ======================================================================
     */
    class shibd_discofeed
    {
        /**
         * Url to the discofeed that returns a json with al idps
         * @var string
         */
        protected string $_sDiscofeedUrl = '/Shibboleth.sso/DiscoFeed';
    
        /**
         * Url to generate a static Shibboleth login url
         * @var string
         */
        protected string $_sShibLoginUrl = '/Shibboleth.sso/Login';
    
        /**
         * Language to search for in the discofeed; a 2 letter code
         * @var string
         */
        protected string $lang = 'en';
    
        // caching of discofeed
    
        /**
         * Filename of the cache file for the Shibboleth discofeed
         * @var string
         */
        protected string $_sCachefile = 'discofeed.json';
    
        /**
         * Caching time for the discofeed cache in seconds
         * @var int
         */
        protected int $_iCacheTtl;
    
        /**
         * Self base URL of the current app tu build Shibboleth links
         * @var string
         */
        protected string $SELFURL = '';
        // protected array $aConfig = [];
    
        // ----------------------------------------------------------------------
    
        /**
         * Constructor
         * @param array $aConfig  config array; the following keys are required:
         *                        idps        array   IDP poositive list
         *                        return-url  string  return URL
         *                        cache-ttl   int     caching time in seconds
         *                        cachefile   string  caching filename
         * @param string $SELFURL
         */
        public function __construct(array $aConfig, string $SELFURL = '')
        {
            $SELFURL = $SELFURL ?: (
                isset($_SERVER['SERVER_NAME']) ? "https://" . $_SERVER['SERVER_NAME'] : ''
            );
    
            if(!$SELFURL) {
                die("ERROR: SELFURL is not set. \$_SERVER['SERVER_NAME'] is not available.");
            }
            $this->SELFURL = $SELFURL;
    
            $this->_sDiscofeedUrl = "$SELFURL$this->_sDiscofeedUrl";
            $this->_sShibLoginUrl = "$SELFURL$this->_sShibLoginUrl";
    
            $this->_sCachefile = dirname(__DIR__).'/'
                .($aConfig['cachefile']??'discofeed.json')
                ;
            $this->_iCacheTtl = $aConfig['cachettl']??60*60;
    
            $this->lang = $aConfig['lang']??'en';
    
            $this->aConfig = $aConfig;
        }
    
        /**
         * Get List if IDPs from cache file if possible 
         * or from Shibboleth Disco feed and write a cache file
         * @return array
         */
        function getAllIdps(): array
        {
            if (!file_exists($this->_sCachefile) || filemtime($this->_sCachefile) < time() - $this->_iCacheTtl) {
                // echo "DEBUG: IDP - reading from Shibboleth<br>";
                $aReturn = json_decode(file_get_contents($this->_sDiscofeedUrl), 1);
        
                if ($aReturn && is_array($aReturn)) {
                    // echo "DEBUG: IDP - storing cache<br>";
                    file_put_contents($this->_sCachefile, json_encode($aReturn));
                }
            } else {
                // echo "DEBUG: IDP - reading cache<br>";
                $aReturn = json_decode(file_get_contents($this->_sCachefile), 1);
            }
        
            return isset($aReturn) && is_array($aReturn) ? $aReturn : [];
        }
    
        /**
         * Get list of active IDPs
         * @return array
         */
        public function getIdps(): array
        {
            $aAllIdps = $this->getAllIdps();
    
            $aReturn = [];
            if (is_array($aAllIdps) && count($aAllIdps)) {
                foreach ($aAllIdps as $aEntry) {
                    $sEntityId = $aEntry['entityID'];
                    $sIdpDomain = parse_url($sEntityId, PHP_URL_HOST);
                    $sIdpTld = preg_filter('/^.*?\.([^\.]+)$/', '$1', $sIdpDomain);
        
                    if (in_array($sEntityId, $this->aConfig['idps'])) {
        
                        $idxText=0;
                        foreach($aEntry['DisplayNames'] as $i=>$aLangitem){
                            if($aLangitem['lang']==$this->lang){
                                $idxText=$i;
                            }
                        }
    
                        $sLabel = $aEntry['DisplayNames'][$idxText]['value'] ?? parse_url($sEntityId, PHP_URL_HOST);
                        $sDescription = $aEntry['Descriptions'][$idxText]['value'] ?? '';
                        $sKeywords = $aEntry['Keywords'][$idxText]['value'] ?? '';
    
                        $sImage = $aEntry['Logos'][1]['value'] ?? ($aEntry['Logos'][0]['value'] ?? '');
        
                        // see also https://help.switch.ch/aai/guides/discovery/login-link-composer/
                        $sUrl = $this->_sShibLoginUrl
                            . '?entityID='. urlencode($sEntityId) 
                            . "&target=" . urlencode($sEntityId) 
                            . "&target=" . urlencode($this->SELFURL.($aConfig['return-url']??''))
                            ;
        
                        $sKey=$sLabel;
                        $aReturn[$sKey] = array_merge([
                            '_label' => $sLabel,
                            '_description' => $sDescription,
                            '_keywords' => $sKeywords,
                            '_image' => $sImage,
                            '_url' => $sUrl,
                            '_idpdomain' => $sIdpDomain,
                            '_tld' => $sIdpTld,
                            ], 
                            $aEntry
                        );
                    }
                }
            }
            ksort($aReturn);
            return array_values($aReturn);
        }
    }