Moving to GitHub.
[platal.git] / modules / openid.php
CommitLineData
24cfa984
AA
1<?php
2/***************************************************************************
c441aabe 3 * Copyright (C) 2003-2014 Polytechnique.org *
24cfa984
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
a1af4a99
AA
22
23/* Definitions for the OpenId Specification
24 * http://openid.net/specs/openid-authentication-2_0.html
7eaf07e9 25 *
a1af4a99
AA
26 * OP Endpoint URL: https://www.polytechnique.org/openid
27 * OP Identifier: https://www.polytechnique.org/openid
b21f0bb5
AA
28 * User Identifier: https://www.polytechnique.org/openid/{hruid}
29 * OP-Local Identifier: {hruid}
30 */
31
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
36 * header.
7eaf07e9 37 *
b21f0bb5
AA
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.
42 *
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.
a1af4a99
AA
46 */
47
33536353
AA
48/* Testing suite is here:
49 * http://openidenabled.com/resources/openid-test/
b21f0bb5
AA
50 * It only supports User Indentifiers.
51 *
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.
33536353
AA
56 */
57
33536353 58
24cfa984
AA
59class OpenidModule extends PLModule
60{
61 function handlers()
62 {
63 return array(
5ae3e9a9
SJ
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),
bfe9f4c7
SJ
67 'openid/trust' => $this->make_hook('trust', AUTH_PASSWD, 'user'),
68 'openid/trusted' => $this->make_hook('trusted', AUTH_PASSWD, 'user'),
69 'admin/openid/trusted' => $this->make_hook('admin_trusted', AUTH_PASSWD, 'admin'),
24cfa984
AA
70 );
71 }
72
26ba053e 73 function handler_openid($page, $login = null)
24cfa984 74 {
a1af4a99 75 $this->load('openid.inc.php');
34d91db6
VZ
76 $requested_user = User::getSilent($login);
77 $server = new OpenId();
b69727b4 78
a8e858d3 79 // Spec §4.1.2: if "openid.mode" is absent, we SHOULD assume that
34d91db6
VZ
80 // the request is not an OpenId message.
81 if (!$server->IsOpenIdRequest()) {
82 if ($requested_user) {
83 $server->RenderDiscoveryPage($page, $requested_user);
84 return;
85 } else {
86 pl_redirect('Xorg/OpenId');
87 }
88 exit;
24cfa984
AA
89 }
90
34d91db6
VZ
91 // Initializes the OpenId environment from the request.
92 $server->Initialize();
93
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());
101
102 if ($authorized) {
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);
109 } else {
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.
114 //
115 // The second case requires a special handling when the request
116 // was POSTed, as our current log in mechanism does not preserve
117 // POST arguments.
118 $openid_args = $server->GetQueryStringForRequest();
119 if (S::logged()) {
120 pl_redirect('openid/trust', $openid_args);
c1390811 121 } else if (Post::has('openid_mode')) {
34d91db6
VZ
122 pl_redirect('openid', $openid_args);
123 } else {
124 return PL_DO_AUTH;
125 }
126 }
127 } else {
128 $server->HandleRequest();
129 }
1bda7469 130
34d91db6
VZ
131 // All requests should have been answered at this point. The best here
132 // is to get the user back to a safe page.
133 pl_redirect('');
134 }
1bda7469 135
26ba053e 136 function handler_melix($page, $login = null)
34d91db6
VZ
137 {
138 $this->load('openid.inc.php');
1bda7469 139
34d91db6
VZ
140 global $globals;
141 $melix = ($login ? $login . '@' . $globals->mail->alias_dom : null);
a1af4a99 142
34d91db6
VZ
143 if ($melix && ($requested_user = User::getSilent($melix))) {
144 $server = new OpenId();
145 $server->RenderDiscoveryPage($page, $requested_user);
33536353 146 } else {
34d91db6 147 pl_redirect('Xorg/OpenId');
24cfa984 148 }
a1af4a99 149 }
b69727b4 150
26ba053e 151 function handler_xrds($page, $login = null)
a1af4a99
AA
152 {
153 $this->load('openid.inc.php');
34d91db6
VZ
154 $requested_user = User::getSilent($login);
155 $server = new OpenId();
24cfa984 156
34d91db6
VZ
157 if (!$login) {
158 $server->RenderMainXrdsPage($page);
159 } else if ($requested_user) {
160 $server->RenderUserXrdsPage($page, $requested_user);
161 } else {
162 return PL_NOT_FOUND;
a1af4a99 163 }
34d91db6 164 }
24cfa984 165
26ba053e 166 function handler_trust($page)
34d91db6
VZ
167 {
168 $this->load('openid.inc.php');
169 $server = new OpenId();
a1af4a99 170 $user = S::user();
b21f0bb5 171
34d91db6
VZ
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.");
a1af4a99
AA
175 }
176
34d91db6
VZ
177 // Prepares the SREG data, if any is required.
178 $sreg_response = $server->GetSRegDataForRequest($user);
12d4424c 179
34d91db6
VZ
180 // Asks the user about her trust level of the current request, if not
181 // done yet.
182 if (!Post::has('trust_accept') && !Post::has('trust_cancel')) {
a1af4a99 183 $page->changeTpl('openid/trust.tpl');
34d91db6
VZ
184 $page->assign('openid_query', $server->GetQueryStringForRequest());
185 $page->assign('relying_party', $server->GetEndpoint());
186 $page->assign('sreg_data', $sreg_response->contents());
2e5fbf5e 187
34d91db6 188 return;
2e5fbf5e
AA
189 }
190
34d91db6
VZ
191 // Interprets the form results, and updates the user whitelist.
192 S::assert_xsrf_token();
193 $trusted = $server->UpdateEndpointTrust(
194 $user,
195 Post::b('trust_accept') && !Post::b('trust_cancel'),
196 Post::b('trust_always'));
197
198 // Finally answers the request.
199 if ($server->IsUserAuthorized($user) && $trusted) {
80c1ab91 200 $server->AnswerRequest(true, Post::b('trust_sreg') ? $sreg_response : null);
34d91db6
VZ
201 } else {
202 $server->AnswerRequest(false);
a1af4a99 203 }
b69727b4
AA
204 }
205
26ba053e 206 function handler_trusted($page, $action = 'list', $id = null)
b8f1396f 207 {
b8f1396f
AA
208 $page->setTitle('Sites tiers de confiance');
209 $page->assign('title', 'Mes sites tiers de confiance pour OpenId');
864957c1
FB
210 $table_editor = new PLTableEditor('openid/trusted', 'account_auth_openid', 'id');
211 $table_editor->set_where_clause(XDB::format('uid = {?}', S::user()->id()));
47f51789
RB
212 $table_editor->vars['uid']['display_list'] = false;
213 $table_editor->vars['uid']['display_item'] = false;
b8f1396f
AA
214 $table_editor->describe('url', 'site tiers', true);
215 $page->assign('deleteonly', true);
51e5bc7d
AA
216 $table_editor->apply($page, $action, $id);
217 }
218
26ba053e 219 function handler_admin_trusted($page, $action = 'list', $id = null)
51e5bc7d
AA
220 {
221 $page->setTitle('Sites tiers de confiance');
222 $page->assign('title', 'Sites tiers de confiance globaux pour OpenId');
864957c1
FB
223 $table_editor = new PLTableEditor('admin/openid/trusted', 'account_auth_openid', 'id');
224 $table_editor->set_where_clause('uid IS NULL');
47f51789
RB
225 $table_editor->vars['uid']['display_list'] = false;
226 $table_editor->vars['uid']['display_item'] = false;
51e5bc7d
AA
227 $table_editor->describe('url', 'site tiers', true);
228 $page->assign('readonly', true);
b8f1396f
AA
229 $table_editor->apply($page, $action, $id);
230 }
24cfa984
AA
231}
232
448c8cdc 233// vim:set et sw=4 sts=4 sws=4 foldmethod=marker fenc=utf-8:
eb5a266d 234?>