2 /***************************************************************************
3 * Copyright (C) 2003-2009 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
22 require_once 'Auth/OpenID/Discover.php';
24 // An helper class for using plat/al as an OpenId Identity Provider.
27 private $base_url; // Base url for all OpenId operations.
28 private $spool_store; // Location of the spool storage for OpenID.
30 private $server = null
; // Auth::OpenId::Server object.
31 private $request = null
; // Request extracted by the Server object.
33 public function __construct()
37 $this->base_url
= $globals->baseurl
. '/openid';
38 $this->spool_store
= $globals->spoolroot
. '/spool/openid/store';
41 // Initializes an OpenId Server object; it will use a defined spool-based
42 // directory to store OpenID secrets. Returns true on success.
43 public function Initialize()
45 require_once 'Auth/OpenID/FileStore.php';
46 require_once 'Auth/OpenID/Server.php';
48 $store = new Auth_OpenID_FileStore($this->spool_store
);
49 $this->server
= new Auth_OpenID_Server($store, $this->base_url
);
50 $this->request
= $this->server
->decodeRequest();
52 return !is_a($this->request
, 'Auth_OpenID_ServerError');
55 // Authorization logic helpers ---------------------------------------------
57 // Returns true iff the current request is a valid openid request.
58 public function IsOpenIdRequest()
60 return Env
::has('openid_mode');
63 // Returns true iff the request needs to be handled directly by the calling
64 // code (ie. the current user needs to be authorized).
65 public function IsAuthorizationRequest()
67 return $this->request
->mode
== 'checkid_immediate' ||
68 $this->request
->mode
== 'checkid_setup';
71 // Returns true iff the request requires an immediate answer (no user
72 // interaction is allowed).
73 public function IsImmediateRequest()
75 return $this->request
->mode
== 'checkid_immediate';
78 // Returns true iff the logged-in user is authorized for the current request.
79 // It checks that the user is logged in, and has the authorization to use
81 public function IsUserAuthorized(User
$user)
83 return $user && ($user->login() == $this->request
->identity ||
84 $this->request
->idSelect());
87 // SimpleRegistration helpers ----------------------------------------------
89 // Determines which SREG data are requested by the endpoint, and returns them.
90 public function GetSRegDataForRequest(User
&$user)
92 require_once 'Auth/OpenID/SReg.php';
94 // Other common SReg fields we could fill are:
95 // dob, country, language, timezone.
96 $sreg_request = Auth_OpenID_SRegRequest
::fromOpenIDRequest($this->request
);
97 return Auth_OpenID_SRegResponse
::extractResponse($sreg_request, array(
98 'fullname' => $user->fullName(),
99 'nickname' => $user->displayName(),
100 'email' => $user->bestEmail(),
101 'gender' => $user->isFemale() ?
'F' : 'M',
105 // Handling and answering helpers ------------------------------------------
107 // Answers the current request, and renders the response. Appends the |sreg|
108 // data when not null.
109 public function AnswerRequest($is_authorized, $sreg_data = null
)
111 // Creates the response.
112 if ($is_authorized && $this->request
->idSelect()) {
114 $response = $this->request
->answer(
115 $is_authorized, null
, $user->login(), $this->GetUserUrl($user));
117 $response = $this->request
->answer($is_authorized);
120 // Clobbers response, and get it back to the Relaying Party.
122 $sreg_data->toMessage($response->fields
);
124 $this->RenderResponse($response);
127 // Automatically handles the request without any user interaction.
128 public function HandleRequest()
130 $response = $this->server
->handleRequest($this->request
);
131 $this->RenderResponse($response);
134 // Trust management helpers ------------------------------------------------
136 // Returns true iff the current endpoint is currently trusted by |user|.
137 public function IsEndpointTrusted(User
$user)
142 WHERE (user_id = {?} OR user_id IS NULL) AND url = {?}",
143 $user->id(), $this->request
->trust_root
);
144 return ($res->fetchOneCell() > 0);
147 // Updates the trust level for the given endpoint, based on the value pf
148 // |trusted| and |permanent_trust| (the latter is ignored when the former
149 // value is false). Returns true iff the current endpoint is trusted.
150 public function UpdateEndpointTrust(User
&$user, $trusted, $permanent_trust) {
151 $initial_trust = $this->IsEndpointTrusted($user);
152 if (!$initial_trust && $trusted && $permanent_trust) {
154 "INSERT IGNORE INTO openid_trusted
155 SET user_id = {?}, url = {?}",
156 $user->id(), $this->request
->trust_root
);
159 return ($initial_trust ||
$trusted);
162 // Page renderers ----------------------------------------------------------
164 // Renders the OpenId discovery page for |user|.
165 public function RenderDiscoveryPage(&$page, User
&$user)
167 $page->changeTpl('openid/openid.tpl');
168 $page->setTitle($user->fullName());
169 $page->addLink('openid.server openid2.provider', $this->base_url
);
170 $page->addLink('openid.delegate openid2.local_id', $user->login());
171 $page->assign_by_ref('user', $user);
173 // Include the X-XRDS-Location header for Yadis discovery.
174 header('X-XRDS-Location: ' . $this->GetUserXrdsUrl($user));
177 // Renders the main XRDS page.
178 public function RenderMainXrdsPage(&$page)
180 header('Content-type: application/xrds+xml');
181 $page->changeTpl('openid/idp_xrds.tpl', NO_SKIN
);
182 $page->assign('type2', Auth_OpenID_TYPE_2_0_IDP
);
183 $page->assign('sreg', Auth_OpenID_SREG_URI
);
184 $page->assign('provider', $this->base_url
);
187 // Renders the XRDS page of |user|.
188 public function RenderUserXrdsPage(&$page, User
&$user)
190 header('Content-type: application/xrds+xml');
191 $page->changeTpl('openid/user_xrds.tpl', NO_SKIN
);
192 $page->assign('type2', Auth_OpenID_TYPE_2_0
);
193 $page->assign('type1', Auth_OpenID_TYPE_1_1
);
194 $page->assign('sreg', Auth_OpenID_SREG_URI
);
195 $page->assign('provider', $this->base_url
);
196 $page->assign('local_id', $user->login());
199 // Renders the OpenId response for the HTTP client.
200 public function RenderResponse($response)
203 $web_response = $this->server
->encodeResponse($response);
204 header(sprintf('%s %d', $_SERVER['SERVER_PROTOCOL'], $web_response->code
),
205 true
, $web_response->code
);
207 if (is_a($response, 'Auth_OpenID_ServerError')) {
208 print "Erreur lors de l'authentification OpenId: " . $response->toString();
210 foreach ($web_response->headers
as $key => $value) {
211 header(sprintf('%s: %s', $key, $value));
214 header('Connection: close');
215 print $web_response->body
;
221 // URL providers -----------------------------------------------------------
223 // Returns the OpenId identity URL of the requested user.
224 private function GetUserUrl(User
&$user)
226 return $this->base_url
. '/' . $user->login();
229 // Returns the private XRDS page of a user.
230 private function GetUserXrdsUrl(User
&$user)
232 return $this->base_url
. '/xrds/' . $user->login();
235 // Returns the endpoint in the current request.
236 public function GetEndpoint()
238 return $this->request
->trust_root
;
241 // Extracts the OpenId arguments available in the current request, and
242 // builds a query string with them.
243 public function GetQueryStringForRequest()
245 foreach (Auth_OpenID
::getQuery() as $key => $value) {
246 if (strpos($key, 'openid.') === 0) {
247 $args[$key] = $value;
251 return http_build_query($args);
255 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: