mirror of https://github.com/jacekkow/uphpCAS

Jacek Kowalski
2015-08-17 90ae5be93ebf5ff2ecee7efc9a6b49717798b4a7
commit | author | age
64d82d 1 <?php
JK 2 // Thrown when internal error occurs
3 class JasigException extends Exception {}
4 // Thrown when CAS server return authentication error
5 class JasigAuthException extends JasigException {}
6
7 class JasigUser {
8     public $user;
9     public $attributes = array();
10 }
11
12 class uphpCAS {
13     const VERSION = '1.0';
14     protected $serverUrl = '';
15     protected $serviceUrl;
16     
17     function __construct($serverUrl = NULL, $serviceUrl = NULL) {
18         if($serverUrl != NULL) {
19             $this->serverUrl = rtrim($serverUrl, '/');
20         }
21         
22         if($serviceUrl != NULL) {
23             $this->serviceUrl = $serviceUrl;
24         } else {
25             $url = 'http://';
26             $port = 0;
27             if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
28                 $url = 'https://';
90ae5b 29                 if(isset($_SERVER['SERVER_PORT'])
JK 30                         && $_SERVER['SERVER_PORT'] != '443') {
64d82d 31                     $port = $_SERVER['SERVER_PORT'];
JK 32                 }
90ae5b 33             } elseif(isset($_SERVER['SERVER_PORT'])
JK 34                     && $_SERVER['SERVER_PORT'] != '80') {
64d82d 35                 $port = $_SERVER['SERVER_PORT'];
JK 36             }
37             
38             $url .= $_SERVER['SERVER_NAME'];
39             
40             if($port != 0) {
41                 $url .= ':'.$port;
42             }
43             $url .= $_SERVER['REQUEST_URI'];
44             
45             $this->serviceUrl = $url;
46         }
47     }
48     
49     public function setServerUrl($serverUrl) {
50         $this->serverUrl = $serverUrl;
51     }
52     
53     public function setServiceUrl($serviceUrl) {
54         $this->serviceUrl = $serviceUrl;
55     }
56     
57     public function loginUrl() {
2092d3 58         return $this->serverUrl.'/login?method=POST&service='.urlencode($this->serviceUrl);
64d82d 59     }
JK 60     
61     public function logoutUrl() {
62         return $this->serverUrl.'/logout';
63     }
64     
65     public function logout() {
66         session_start();
67         if(isset($_SESSION['uphpCAS-user'])) {
68             unset($_SESSION['uphpCAS-user']);
69         }
70         header('Location: '.$this->logoutUrl());
71         die();
72     }
73     
74     public function authenticate() {
75         session_start();
76         if(isset($_SESSION['uphpCAS-user'])) {
77             return $_SESSION['uphpCAS-user'];
2092d3 78         } elseif(isset($_REQUEST['ticket'])) {
JK 79             $user = $this->verifyTicket($_REQUEST['ticket']);
64d82d 80             $_SESSION['uphpCAS-user'] = $user;
JK 81             return $user;
82         } else {
83             header('Location: '.$this->loginUrl());
84             die();
85         }
86     }
87     
88     public function verifyTicket($ticket) {
89         $context = array(
90             'http' => array(
91                 'method' => 'GET',
92                 'user_agent' => 'uphpCAS/'.self::VERSION,
93                 'max_redirects' => 3,
94             ),
95             'ssl' => array(
96                 'verify_peer' => TRUE,
90ae5b 97                 'verify_peer_name' => TRUE,
64d82d 98                 'verify_depth' => 5,
90ae5b 99                 'allow_self_signed' => FALSE,
JK 100                 'disable_compression' => TRUE,
64d82d 101             ),
JK 102         );
103         
90ae5b 104         $data = file_get_contents($this->serverUrl
JK 105                     .'/serviceValidate?service='.urlencode($this->serviceUrl)
106                     .'&ticket='.urlencode($ticket),
64d82d 107                 FALSE, stream_context_create($context));
JK 108         if($data === FALSE) {
109             throw new JasigException('Authentication error: CAS server is unavailable');
110         }
111         
112         $xmlEntityLoader = libxml_disable_entity_loader(TRUE);
113         $xmlInternalErrors = libxml_use_internal_errors(TRUE);
114         try {
115             $xml = new DOMDocument();
116             $xml->loadXML($data);
117             
118             foreach(libxml_get_errors() as $error) {
90ae5b 119                 $e = new ErrorException($error->message, $error->code, 1,
JK 120                         $error->file, $error->line);
64d82d 121                 switch ($error->level) {
JK 122                     case LIBXML_ERR_ERROR:
123                     case LIBXML_ERR_FATAL:
90ae5b 124                         throw new Exception('Fatal error during XML parsing',
JK 125                                 0, $e);
64d82d 126                         break;
JK 127                 }
128             }
129         }
130         catch(Exception $e) {
90ae5b 131             throw new JasigException('Authentication error: CAS server'
JK 132                     .' response invalid - parse error', 0, $e);
64d82d 133         } finally {
JK 134             libxml_clear_errors();
135             libxml_disable_entity_loader($xmlEntityLoader);
136             libxml_use_internal_errors($xmlInternalErrors);
137         }
138         
139         $failure = $xml->getElementsByTagName('authenticationFailure');
140         $success = $xml->getElementsByTagName('authenticationSuccess');
141         
142         if($failure->length > 0) {
143             $failure = $failure->item(0);
144             if(!($failure instanceof DOMElement)) {
90ae5b 145                 throw new JasigException('Authentication error: CAS server'
JK 146                         .' response invalid - authenticationFailure');
64d82d 147             }
90ae5b 148             throw new JasigAuthException('Authentication error: '
JK 149                     .$failure->textContent);
64d82d 150         } elseif($success->length > 0) {
JK 151             $success = $success->item(0);
152             if(!($success instanceof DOMElement)) {
90ae5b 153                 throw new JasigException('Authentication error: CAS server'
JK 154                         .' response invalid - authenticationSuccess');
64d82d 155             }
JK 156             
157             $user = $success->getElementsByTagName('user');
158             if($user->length == 0) {
90ae5b 159                 throw new JasigException('Authentication error: CAS server'
JK 160                         .' response invalid - user');
64d82d 161             }
JK 162             
163             $user = trim($user->item(0)->textContent);
164             if(strlen($user)<1) {
90ae5b 165                 throw new JasigException('Authentication error: CAS server'
JK 166                         .' response invalid - user value');
64d82d 167             }
JK 168             
169             $jusr = new JasigUser();
170             $jusr->user = $user;
171             
172             $attrs = $success->getElementsByTagName('attributes');
173             if($attrs->length > 0) {
174                 $attrs = $attrs->item(0);
175                 foreach($attrs->childNodes as $node) {
176                     $jusr->attributes[$node->localName] = $node->textContent;
177                 }
178             }
179             
180             return $jusr;
181         }
182         else
183         {
90ae5b 184             throw new JasigException('Authentication error: CAS server'
JK 185                     .' response invalid - required tag not found');
64d82d 186         }
JK 187     }
188 }