2 /***************************************************************************
3 * Copyright (C) 2003-2011 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 ***************************************************************************/
23 /* Definitions for the OpenId Specification
24 * http://openid.net/specs/openid-authentication-2_0.html
26 * OP Endpoint URL: https://www.polytechnique.org/openid
27 * OP Identifier: https://www.polytechnique.org/openid
28 * User Identifier: https://www.polytechnique.org/openid/{hruid}
29 * OP-Local Identifier: {hruid}
32 /* This implementation supports two modes:
33 * - entering the OP Identifier, which can simply be 'polytechnique.org'
34 * - entering the User Identifier, or some URL that resolves there
35 * In both cases, Yadis discovery is made possible through the X-XRDS-Location
38 * In the former case, Yadis discovery is performed on /, or where it redirects;
39 * see platal.php. It resolves to the XRDS for this OP, and User Identifier
40 * selection is performed after forcing the user to log in. This only works for
41 * version 2.0 of the OpenId protocol.
43 * In the latter cas, Yadis discovery is performed on /openid/{hruid}. It
44 * resolves ta a user-specific XRDS. This page also features HTML-based
45 * discovery. This works with any version of the protocol.
48 /* Testing suite is here:
49 * http://openidenabled.com/resources/openid-test/
50 * It only supports User Indentifiers.
52 * To test OP Identifiers, download the JanRain PHP library and use the
53 * consumer provided as an example (although it appears that a failure is
54 * mistakenly reported: 'Server denied check_authentication').
55 * Reading the source of the server can also help understanding the code below.
59 class OpenidModule
extends PLModule
64 'openid' => $this->make_hook('openid', AUTH_PUBLIC
),
65 'openid/melix' => $this->make_hook('melix', AUTH_PUBLIC
),
66 'openid/xrds' => $this->make_hook('xrds', AUTH_PUBLIC
),
67 'openid/trust' => $this->make_hook('trust', AUTH_MDP
),
68 'openid/trusted' => $this->make_hook('trusted', AUTH_MDP
),
69 'admin/openid/trusted' => $this->make_hook('admin_trusted', AUTH_MDP
, 'admin'),
73 function handler_openid($page, $login = null
)
75 $this->load('openid.inc.php');
76 $requested_user = User
::getSilent($login);
77 $server = new OpenId();
79 // Spec §4.1.2: if "openid.mode" is absent, we SHOULD assume that
80 // the request is not an OpenId message.
81 if (!$server->IsOpenIdRequest()) {
82 if ($requested_user) {
83 $server->RenderDiscoveryPage($page, $requested_user);
86 pl_redirect('Xorg/OpenId');
91 // Initializes the OpenId environment from the request.
92 $server->Initialize();
94 // In modes 'checkid_immediate' and 'checkid_setup', we need to check
95 // by ourselves that we want to allow the user to be authenticated.
96 // Otherwise it can simply be forwarded to the Server object.
97 if ($server->IsAuthorizationRequest()) {
98 $authorized = S
::logged() &&
99 $server->IsUserAuthorized(S
::user()) &&
100 $server->IsEndpointTrusted(S
::user());
103 // TODO(vzanotti): SReg requests are currently not honored if
104 // the website is already trusted. We may want to redirect SReg
105 // requests to /openid/trust, to allow the user to choose.
106 $server->AnswerRequest(true
);
107 } else if ($server->IsImmediateRequest()) {
108 $server->AnswerRequest(false
);
110 // The user is currently not authorized to get her authorization
111 // request approved. Two possibilities:
112 // * the endpoint is not yet trusted => redirect to openid/trust
113 // * the user is not logged in => log in the user.
115 // The second case requires a special handling when the request
116 // was POSTed, as our current log in mechanism does not preserve
118 $openid_args = $server->GetQueryStringForRequest();
120 pl_redirect('openid/trust', $openid_args);
121 } else if (Post
::has('openid_mode')) {
122 pl_redirect('openid', $openid_args);
128 $server->HandleRequest();
131 // All requests should have been answered at this point. The best here
132 // is to get the user back to a safe page.
136 function handler_melix($page, $login = null
)
138 $this->load('openid.inc.php');
141 $melix = ($login ?
$login . '@' . $globals->mail
->alias_dom
: null
);
143 if ($melix && ($requested_user = User
::getSilent($melix))) {
144 $server = new OpenId();
145 $server->RenderDiscoveryPage($page, $requested_user);
147 pl_redirect('Xorg/OpenId');
151 function handler_xrds($page, $login = null
)
153 $this->load('openid.inc.php');
154 $requested_user = User
::getSilent($login);
155 $server = new OpenId();
158 $server->RenderMainXrdsPage($page);
159 } else if ($requested_user) {
160 $server->RenderUserXrdsPage($page, $requested_user);
166 function handler_trust($page)
168 $this->load('openid.inc.php');
169 $server = new OpenId();
172 // Initializes the OpenId environment from the request.
173 if (!$server->Initialize() ||
!$server->IsAuthorizationRequest()) {
174 $page->kill("Ta requête OpenID a échoué, merci de réessayer.");
177 // Prepares the SREG data, if any is required.
178 $sreg_response = $server->GetSRegDataForRequest($user);
180 // Asks the user about her trust level of the current request, if not
182 if (!Post
::has('trust_accept') && !Post
::has('trust_cancel')) {
183 $page->changeTpl('openid/trust.tpl');
184 $page->assign('openid_query', $server->GetQueryStringForRequest());
185 $page->assign('relying_party', $server->GetEndpoint());
186 $page->assign('sreg_data', $sreg_response->contents());
191 // Interprets the form results, and updates the user whitelist.
192 S
::assert_xsrf_token();
193 $trusted = $server->UpdateEndpointTrust(
195 Post
::b('trust_accept') && !Post
::b('trust_cancel'),
196 Post
::b('trust_always'));
198 // Finally answers the request.
199 if ($server->IsUserAuthorized($user) && $trusted) {
200 $server->AnswerRequest(true
, Post
::b('trust_sreg') ?
$sreg_response : null
);
202 $server->AnswerRequest(false
);
206 function handler_trusted($page, $action = 'list', $id = null
)
208 $page->setTitle('Sites tiers de confiance');
209 $page->assign('title', 'Mes sites tiers de confiance pour OpenId');
210 $table_editor = new PLTableEditor('openid/trusted', 'account_auth_openid', 'id');
211 $table_editor->set_where_clause(XDB
::format('uid = {?}', S
::user()->id()));
212 $table_editor->vars
['uid']['display'] = false
;
213 $table_editor->describe('url', 'site tiers', true
);
214 $page->assign('deleteonly', true
);
215 $table_editor->apply($page, $action, $id);
218 function handler_admin_trusted($page, $action = 'list', $id = null
)
220 $page->setTitle('Sites tiers de confiance');
221 $page->assign('title', 'Sites tiers de confiance globaux pour OpenId');
222 $table_editor = new PLTableEditor('admin/openid/trusted', 'account_auth_openid', 'id');
223 $table_editor->set_where_clause('uid IS NULL');
224 $table_editor->vars
['uid']['display'] = false
;
225 $table_editor->describe('url', 'site tiers', true
);
226 $page->assign('readonly', true
);
227 $table_editor->apply($page, $action, $id);
231 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: