Commit | Line | Data |
---|---|---|
a1af4a99 AA |
1 | <?php |
2 | /*************************************************************************** | |
12262f13 | 3 | * Copyright (C) 2003-2011 Polytechnique.org * |
a1af4a99 AA |
4 | * http://opensource.polytechnique.org/ * |
5 | * * | |
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. * | |
10 | * * | |
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. * | |
15 | * * | |
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 * | |
18 | * Foundation, Inc., * | |
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * | |
20 | ***************************************************************************/ | |
21 | ||
34d91db6 | 22 | require_once 'Auth/OpenID/Discover.php'; |
a1af4a99 | 23 | |
34d91db6 VZ |
24 | // An helper class for using plat/al as an OpenId Identity Provider. |
25 | class OpenId | |
a1af4a99 | 26 | { |
34d91db6 VZ |
27 | private $base_url; // Base url for all OpenId operations. |
28 | private $spool_store; // Location of the spool storage for OpenID. | |
a1af4a99 | 29 | |
34d91db6 VZ |
30 | private $server = null; // Auth::OpenId::Server object. |
31 | private $request = null; // Request extracted by the Server object. | |
32 | ||
33 | public function __construct() | |
34 | { | |
35 | global $globals; | |
a1af4a99 | 36 | |
34d91db6 VZ |
37 | $this->base_url = $globals->baseurl . '/openid'; |
38 | $this->spool_store = $globals->spoolroot . '/spool/openid/store'; | |
a1af4a99 | 39 | } |
a1af4a99 | 40 | |
34d91db6 VZ |
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() | |
44 | { | |
45 | require_once 'Auth/OpenID/FileStore.php'; | |
46 | require_once 'Auth/OpenID/Server.php'; | |
a1af4a99 | 47 | |
34d91db6 VZ |
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(); | |
2d8779e2 | 51 | |
34d91db6 VZ |
52 | return !is_a($this->request, 'Auth_OpenID_ServerError'); |
53 | } | |
2d8779e2 | 54 | |
34d91db6 VZ |
55 | // Authorization logic helpers --------------------------------------------- |
56 | ||
57 | // Returns true iff the current request is a valid openid request. | |
58 | public function IsOpenIdRequest() | |
59 | { | |
60 | return Env::has('openid_mode'); | |
a1af4a99 | 61 | } |
a1af4a99 | 62 | |
34d91db6 VZ |
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() | |
66 | { | |
67 | return $this->request->mode == 'checkid_immediate' || | |
68 | $this->request->mode == 'checkid_setup'; | |
69 | } | |
ab66bf7f | 70 | |
34d91db6 VZ |
71 | // Returns true iff the request requires an immediate answer (no user |
72 | // interaction is allowed). | |
73 | public function IsImmediateRequest() | |
74 | { | |
75 | return $this->request->mode == 'checkid_immediate'; | |
a1af4a99 | 76 | } |
a1af4a99 | 77 | |
34d91db6 VZ |
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 | |
80 | // that identity. | |
81 | public function IsUserAuthorized(User $user) | |
82 | { | |
83 | return $user && ($user->login() == $this->request->identity || | |
84 | $this->request->idSelect()); | |
85 | } | |
a1af4a99 | 86 | |
34d91db6 | 87 | // SimpleRegistration helpers ---------------------------------------------- |
a1af4a99 | 88 | |
34d91db6 | 89 | // Determines which SREG data are requested by the endpoint, and returns them. |
26ba053e | 90 | public function GetSRegDataForRequest(User $user) |
34d91db6 VZ |
91 | { |
92 | require_once 'Auth/OpenID/SReg.php'; | |
93 | ||
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', | |
102 | )); | |
103 | } | |
104 | ||
105 | // Handling and answering helpers ------------------------------------------ | |
106 | ||
107 | // Answers the current request, and renders the response. Appends the |sreg| | |
108 | // data when not null. | |
80c1ab91 | 109 | public function AnswerRequest($is_authorized, $sreg_data = null) |
34d91db6 VZ |
110 | { |
111 | // Creates the response. | |
80c1ab91 VZ |
112 | if ($is_authorized && $this->request->idSelect()) { |
113 | $user = S::user(); | |
34d91db6 VZ |
114 | $response = $this->request->answer( |
115 | $is_authorized, null, $user->login(), $this->GetUserUrl($user)); | |
116 | } else { | |
117 | $response = $this->request->answer($is_authorized); | |
118 | } | |
119 | ||
120 | // Clobbers response, and get it back to the Relaying Party. | |
121 | if ($sreg_data) { | |
122 | $sreg_data->toMessage($response->fields); | |
123 | } | |
124 | $this->RenderResponse($response); | |
125 | } | |
126 | ||
127 | // Automatically handles the request without any user interaction. | |
128 | public function HandleRequest() | |
129 | { | |
130 | $response = $this->server->handleRequest($this->request); | |
131 | $this->RenderResponse($response); | |
132 | } | |
133 | ||
134 | // Trust management helpers ------------------------------------------------ | |
135 | ||
136 | // Returns true iff the current endpoint is currently trusted by |user|. | |
137 | public function IsEndpointTrusted(User $user) | |
138 | { | |
139 | $res = XDB::query( | |
140 | "SELECT COUNT(*) | |
864957c1 FB |
141 | FROM account_auth_openid |
142 | WHERE (uid = {?} OR uid IS NULL) AND url = {?}", | |
34d91db6 VZ |
143 | $user->id(), $this->request->trust_root); |
144 | return ($res->fetchOneCell() > 0); | |
145 | } | |
146 | ||
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. | |
26ba053e | 150 | public function UpdateEndpointTrust(User $user, $trusted, $permanent_trust) { |
34d91db6 VZ |
151 | $initial_trust = $this->IsEndpointTrusted($user); |
152 | if (!$initial_trust && $trusted && $permanent_trust) { | |
153 | XDB::execute( | |
864957c1 FB |
154 | "INSERT IGNORE INTO account_auth_openid |
155 | SET uid = {?}, url = {?}", | |
34d91db6 VZ |
156 | $user->id(), $this->request->trust_root); |
157 | } | |
158 | ||
159 | return ($initial_trust || $trusted); | |
160 | } | |
161 | ||
162 | // Page renderers ---------------------------------------------------------- | |
163 | ||
164 | // Renders the OpenId discovery page for |user|. | |
26ba053e | 165 | public function RenderDiscoveryPage($page, User $user) |
34d91db6 VZ |
166 | { |
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); | |
172 | ||
173 | // Include the X-XRDS-Location header for Yadis discovery. | |
174 | header('X-XRDS-Location: ' . $this->GetUserXrdsUrl($user)); | |
175 | } | |
176 | ||
177 | // Renders the main XRDS page. | |
26ba053e | 178 | public function RenderMainXrdsPage($page) |
34d91db6 | 179 | { |
3cb500d5 | 180 | pl_content_headers("application/xrds+xml"); |
34d91db6 VZ |
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); | |
185 | } | |
186 | ||
187 | // Renders the XRDS page of |user|. | |
26ba053e | 188 | public function RenderUserXrdsPage($page, User $user) |
34d91db6 | 189 | { |
3cb500d5 | 190 | pl_content_headers("application/xrds+xml"); |
34d91db6 VZ |
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()); | |
197 | } | |
198 | ||
199 | // Renders the OpenId response for the HTTP client. | |
200 | public function RenderResponse($response) | |
201 | { | |
202 | if ($response) { | |
203 | $web_response = $this->server->encodeResponse($response); | |
c1390811 VZ |
204 | header(sprintf('%s %d', $_SERVER['SERVER_PROTOCOL'], $web_response->code), |
205 | true, $web_response->code); | |
34d91db6 | 206 | |
80c1ab91 VZ |
207 | if (is_a($response, 'Auth_OpenID_ServerError')) { |
208 | print "Erreur lors de l'authentification OpenId: " . $response->toString(); | |
209 | } else { | |
ddb3df45 VZ |
210 | foreach ($web_response->headers as $key => $value) { |
211 | header(sprintf('%s: %s', $key, $value)); | |
212 | } | |
34d91db6 | 213 | |
80c1ab91 VZ |
214 | header('Connection: close'); |
215 | print $web_response->body; | |
216 | } | |
34d91db6 VZ |
217 | } |
218 | exit; | |
219 | } | |
220 | ||
221 | // URL providers ----------------------------------------------------------- | |
222 | ||
223 | // Returns the OpenId identity URL of the requested user. | |
26ba053e | 224 | private function GetUserUrl(User $user) |
34d91db6 VZ |
225 | { |
226 | return $this->base_url . '/' . $user->login(); | |
227 | } | |
228 | ||
229 | // Returns the private XRDS page of a user. | |
26ba053e | 230 | private function GetUserXrdsUrl(User $user) |
34d91db6 VZ |
231 | { |
232 | return $this->base_url . '/xrds/' . $user->login(); | |
233 | } | |
234 | ||
235 | // Returns the endpoint in the current request. | |
236 | public function GetEndpoint() | |
237 | { | |
238 | return $this->request->trust_root; | |
239 | } | |
240 | ||
241 | // Extracts the OpenId arguments available in the current request, and | |
242 | // builds a query string with them. | |
243 | public function GetQueryStringForRequest() | |
244 | { | |
245 | foreach (Auth_OpenID::getQuery() as $key => $value) { | |
246 | if (strpos($key, 'openid.') === 0) { | |
247 | $args[$key] = $value; | |
248 | } | |
249 | } | |
250 | ||
251 | return http_build_query($args); | |
252 | } | |
2e5fbf5e AA |
253 | } |
254 | ||
a1af4a99 | 255 | // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: |
34d91db6 | 256 | ?> |