3 * FusionForge authentication management
5 * Copyright 2011, Roland Mas
7 * This file is part of FusionForge.
9 * FusionForge is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License,
12 * or (at your option) any later version.
14 * FusionForge is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with FusionForge; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 // See for details http://lists.fusionforge.org/pipermail/fusionforge-general/2011-February/001335.html
27 define('FORGE_AUTH_AUTHORITATIVE_ACCEPT', 1);
28 define('FORGE_AUTH_AUTHORITATIVE_REJECT', 2);
29 define('FORGE_AUTH_NOT_AUTHORITATIVE', 3);
32 * Pluggable Authentication plugins base class
34 * By default, the session cookie is used
37 abstract class ForgeAuthPlugin extends Plugin {
39 * ForgeAuthPlugin() - constructor
42 function ForgeAuthPlugin() {
44 // Common hooks that can be enabled per plugin:
45 // check_auth_session - is there a valid session?
46 // fetch_authenticated_user - what GFUser is logged in?
47 // display_auth_form - display a form to input credentials
48 // display_create_user_form - display a form to create a user from external auth
49 // sync_account_info - sync identity from external source (realname, email, etc.)
50 // get_extra_roles - add new roles not necessarily stored in the database
51 // restrict_roles - filter out unwanted roles
52 // close_auth_session - terminate an authentication session
54 $this->saved_user = NULL;
58 function CallHook ($hookname, &$params) {
60 case 'check_auth_session':
61 $this->checkAuthSession($params);
63 case 'fetch_authenticated_user':
64 $this->fetchAuthUser($params);
66 case 'display_auth_form':
67 // no default implementation, but see AuthBuiltinPlugin::displayAuthForm()
68 // $params can be passed with a 'return_to' attribute
69 // it should return an HTML dialog appened to passed $params['html_snippets']
70 // it may return a redirection URL appened to $params['transparent_redirect_urls']
71 $this->displayAuthForm($params);
73 case 'display_create_user_form':
74 // no default implementation
75 $this->displayCreateUserForm($params);
77 case 'sync_account_info':
78 // no default implementation
79 $this->syncAccountInfo($params);
81 case 'get_extra_roles':
82 $this->getExtraRoles($params);
84 case 'restrict_roles':
85 $this->restrictRoles($params);
87 case 'close_auth_session':
88 $this->closeAuthSession($params);
103 protected $saved_user;
106 * Is there a valid session?
108 * @param unknown_type $params
109 * @return FORGE_AUTH_AUTHORITATIVE_ACCEPT, FORGE_AUTH_AUTHORITATIVE_REJECT or FORGE_AUTH_NOT_AUTHORITATIVE
110 * TODO : document 'auth_token' param
112 function checkAuthSession(&$params) {
113 // check the session cookie/token to get a user_id
114 if (isset($params['auth_token']) && $params['auth_token'] != '') {
115 $user_id = $this->checkSessionToken($params['auth_token']);
117 $user_id = $this->checkSessionCookie();
120 $this->saved_user = user_get_object($user_id);
121 if ($this->isSufficient()) {
122 $params['results'][$this->name] = FORGE_AUTH_AUTHORITATIVE_ACCEPT;
124 $params['results'][$this->name] = FORGE_AUTH_NOT_AUTHORITATIVE;
127 $this->saved_user = NULL;
128 if ($this->isRequired()) {
129 $params['results'][$this->name] = FORGE_AUTH_AUTHORITATIVE_REJECT;
131 $params['results'][$this->name] = FORGE_AUTH_NOT_AUTHORITATIVE;
137 * What GFUser is logged in?
139 * This will generate a valid forge user (by default, it was generated and cached already in saved_user)
141 * @param unknown_type $params
142 * @return array $params['results'] containing user object
144 function fetchAuthUser(&$params) {
145 if ($this->saved_user && $this->isSufficient()) {
146 $params['results'] = $this->saved_user;
151 * Terminate an authentication session
152 * @param unknown_type $params
155 function closeAuthSession($params) {
156 if ($this->isSufficient() || $this->isRequired()) {
157 $this->unsetSessionCookie();
164 * Add new roles not necessarily stored in the database
165 * @param unknown_type $params
167 function getExtraRoles(&$params) {
168 // $params['new_roles'][] = RBACEngine::getInstance()->getRoleById(123);
172 * Filter out unwanted roles
173 * @param unknown_type $params
175 function restrictRoles(&$params) {
176 // $params['dropped_roles'][] = RBACEngine::getInstance()->getRoleById(123);
179 // Helper functions for individual plugins
180 // FIXME : where is $this->cookie_name set ?
181 protected $cookie_name;
184 * Returns the session cookie name for the auth plugin (by default forge_session_AUTHPLUGINNAME)
188 protected function getCookieName() {
189 if ($this->cookie_name) {
190 return $this->cookie_name;
192 return 'forge_session_'.$this->name;
195 protected function checkSessionToken($token) {
196 return session_check_session_token($token);
199 protected function checkSessionCookie() {
200 $token = getStringFromCookie($this->getCookieName());
201 return $this->checkSessionToken($token);
205 * Sets the session cookie according to the user in $this->saved_user
207 protected function setSessionCookie() {
208 if($this->saved_user) {
209 $cookie = session_build_session_token($this->saved_user->getID());
210 session_set_cookie($this->getCookieName(), $cookie, "", forge_get_config('session_expire'));
215 * Start a new session for a user
216 * @param string $username
219 function startSession($username) {
220 if ($this->isSufficient() || $this->isRequired()) {
222 $params['username'] = $username;
223 $params['event'] = 'login';
224 plugin_hook('sync_account_info', $params);
225 $user = user_get_object_by_name($username);
226 $this->saved_user = $user;
227 $this->setSessionCookie();
234 protected function unsetSessionCookie() {
235 session_set_cookie($this->getCookieName(), '');
239 * TODO: Enter description here ...
240 * @return Ambigous <Ambigous, NULL, boolean>
242 public function isRequired() {
243 return forge_get_config('required', $this->name);
247 * TODO: Enter description here ...
248 * @return Ambigous <Ambigous, NULL, boolean>
250 public function isSufficient() {
251 return forge_get_config('sufficient', $this->name);
255 * TODO: Enter description here ...
256 * @param unknown_type $event
259 public function syncDataOn($event) {
260 $configval = forge_get_config('sync_data_on', $this->name);
263 switch ($configval) {
265 $events = array('every-page','login','user-creation');
268 $events = array('login','user-creation');
270 case 'user-creation':
271 $events = array('user-creation');
278 return in_array($event, $events);
282 * TODO: Enter description here ...
284 protected function declareConfigVars() {
285 forge_define_config_item ('required', $this->name, 'yes');
286 forge_set_config_item_bool ('required', $this->name) ;
288 forge_define_config_item ('sufficient', $this->name, 'yes');
289 forge_set_config_item_bool ('sufficient', $this->name) ;
291 forge_define_config_item ('sync_data_on', $this->name, 'never');
297 // c-file-style: "bsd"