3 /*-------------------------------------------------------------------------------------
5 * Filename : Authentication_Delegated.php
6 * Date : 11th July 2012
8 * Copyright (C) 2012 Melvin Carvalho, Akbar Hossain, László Török
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is furnished
15 * to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in all
18 * copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Everything should be made as simple as possible, but no simpler."
30 //-------------------------------------------------------------------------------------
31 require_once(dirname(__FILE__)."/Authentication_URL.php");
32 require_once(dirname(__FILE__)."/Authentication_X509CertRepo.php");
33 require_once(dirname(__FILE__)."/Authentication_Session.php");
35 * Implements WebID Delegated Authentication using an Identity Provider
37 * @author Akbar Hossain
38 * @modified Andrei Sambra
40 class Authentication_Delegated {
42 * After succesful authentication contains the webid
43 * (e.g. http://foaf.me/tl73#me)
47 public $isAuthenticated = 0;
49 * Always contains the diagnostic message for the last authentication attempt
52 public $authnDiagnostic = NULL;
53 /** @var Authentication_SignedURL */
54 private $requestURI = NULL;
55 /** @var Authentication_URL */
56 private $referer = NULL;
58 private $allowedTimeWindow = 0;
59 private $elapsedTime = 0;
61 const STATUS_AUTH_VIA_SESSION =
62 "Authenticated via a session";
64 const STATUS_DELEGATED_LOGIN_OK =
65 "Delegated WebID Login response has been authenticated";
67 const STATUS_SIGNATURE_VERIFICATION_ERR =
68 "Signature on response could not be verified";
70 const STATUS_UNSUPPORTED_SIGNATURE_ALG_ERR =
71 "Unsupported signature algorithm";
73 const STATUS_IDP_RESPONSE_TIMEOUT_ERR =
74 "Response from delegate IdP was outside of the allowed time window";
76 const STATUS_OPENSSL_VERIFICATION_ERR =
77 "Openssl verification error";
79 const STATUS_IDP_CERTIFICATE_MISSING =
80 "Signing IdP's certificate not found";
82 const SIG_ALG_RSA_SHA1 = 'rsa-sha1';
84 * Perform delegated WebID authentication relying on an Identity Provider
85 * @param Authentication_SignedURL $request (if not specified infered from _GET)
86 * @param Authentication_X509CertRepo $certRepository (if not default is used)
87 * @param bool $createSession
88 * @param string $sigAlg
89 * @param int $allowedTimeWindow
91 public function __construct($createSession = TRUE,
92 Authentication_SignedURL $request = NULL,
93 Authentication_URL $referer = NULL,
94 Authentication_X509CertRepo $certRepository = NULL,
95 $sigAlg = self::SIG_ALG_RSA_SHA1,
96 $allowedTimeWindow = 300)
100 $session = new Authentication_Session();
101 if ($session->isAuthenticated)
103 $this->webid = $session->webid;
104 $this->isAuthenticated = $session->isAuthenticated;
105 $this->authnDiagnostic = self::STATUS_AUTH_VIA_SESSION;
110 if ( ! $certRepository)
111 $certRepository = new Authentication_X509CertRepo();
114 $request = Authentication_SignedURL::parse(
115 ((isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on")) ? "https" : "http")
116 . "://".$_SERVER["SERVER_NAME"]
117 . ($_SERVER["SERVER_PORT"] != ((isset($_SERVER["HTTPS"])
118 && ($_SERVER["HTTPS"] == "on")) ? 443 : 80) ? ":"
119 .$_SERVER["SERVER_PORT"] : "")
120 . $_SERVER["REQUEST_URI"]
128 isset($_GET["error"]) and $error = $_GET["error"];
130 isset($_GET["sig"]) and $sig = $_GET["sig"];
132 isset($_GET["ts"]) and $ts = $_GET["ts"];
134 $error = $request->getQueryParameter('error', $error);
135 $sig = $request->getQueryParameter('sig', $sig);
136 $ts = $request->getQueryParameter('ts', $ts);
138 $this->requestURI = $request;
139 if (NULL != $referer)
141 $this->referer = $referer;
143 else if (isset($_GET["referer"]))
145 $this->referer = Authentication_URL::parse($_GET["referer"]);
149 $this->referer = new Authentication_URL();
154 isset($_GET["webid"]) and $webid = $_GET["webid"];
156 $this->webid = $request->getQueryParameter('webid', $webid);
157 $this->allowedTimeWindow = $allowedTimeWindow;
158 $this->elapsedTime = time() - strtotime($ts);
161 * Loads the trusted certificate of the IdP: its public key is used to
162 * verify the integrity of the signed assertion.
164 $idpCertificate = $certRepository->getIdpCertificate($this->referer->host);
165 if ( ! $idpCertificate)
167 $this->isAuthenticated = 0;
168 $this->authnDiagnostic = self::STATUS_IDP_CERTIFICATE_MISSING;
171 else if (($this->elapsedTime < $this->allowedTimeWindow) && ( ! isset($error)))
174 $signedInfo = $this->requestURI->urlWithoutSignature();
175 // Extracts the signature
176 $signature = $this->requestURI->digitalSignature();
177 // TODO this may be removed in the future
181 // Only rsa-sha1 is supported at the moment.
182 if ($sigAlg == self::SIG_ALG_RSA_SHA1)
184 $pubKeyId = openssl_get_publickey($idpCertificate);
186 // Verifies the signature
187 $verified = openssl_verify($signedInfo, $signature, $pubKeyId);
190 // The verification was successful.
191 $this->isAuthenticated = 1;
192 $this->authnDiagnostic = self::STATUS_DELEGATED_LOGIN_OK;
194 else if ($verified == 0)
196 // The signature didn't match.
197 $this->isAuthenticated = 0;
198 $this->authnDiagnostic = self::STATUS_SIGNATURE_VERIFICATION_ERR;
202 // Error during the verification.
203 $this->isAuthenticated = 0;
204 $this->authnDiagnostic = self::STATUS_OPENSSL_VERIFICATION_ERR;
207 openssl_free_key($pubKeyId);
212 // Unsupported signature algorithm.
213 $this->isAuthenticated = 0;
214 $this->authnDiagnostic = self::STATUS_UNSUPPORTED_SIGNATURE_ALG_ERR;
219 $this->isAuthenticated = 0;
221 $this->authnDiagnostic = $error;
223 $this->authnDiagnostic = self::STATUS_IDP_RESPONSE_TIMEOUT_ERR;
228 if ($this->isAuthenticated)
229 $session->setAuthenticatedWebid($this->webid);
231 $session->unsetAuthenticatedWebid();
236 * Is the current user authenticated?
239 public function isAuthenticated()
241 return $this->isAuthenticated;
244 * Leave the authenticated session
246 public function logout()
248 $this->isAuthenticated = 0;
249 $this->session->unsetAuthenticatedWebid();