├── .gitignore
├── application
├── config
│ ├── ddauth_site.example.php
│ └── ddauth.php
└── libraries
│ └── Ddauth.php
├── INSTALL
├── dd-p2.xml
├── README
├── LICENSE
└── phpdoc.ini
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | docs
3 |
--------------------------------------------------------------------------------
/application/config/ddauth_site.example.php:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/INSTALL:
--------------------------------------------------------------------------------
1 | ddauth - Dragonfly Development CodeIgniter Auth Add-on
2 | http://code.google.com/p/dd-ci-ddauth
3 |
4 | Copy the ddauth distribution files:
5 |
6 | cp dd-ci-ddauth/application/libraries/Ddauth.php \
7 | system/application/libraries/
8 |
9 | cp dd-ci-ddauth/application/config/ddauth.php \
10 | system/application/config/
11 |
12 | It is recommended to update the 'ddauth_ticket_secret' configuration value in
13 | the ddauth.php file located in path/to/your/system/application/config/.
14 | Setting this value ensures that the authentication tickets generated by ddauth
15 | are more secure.
16 |
17 | Optionally add ddauth to application's autoload. To do so, modify
18 | system/application/config/autoload.php to include the ddauth library:
19 |
20 | $autoload['libraries'] = array('Ddauth');
21 |
22 |
--------------------------------------------------------------------------------
/dd-p2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0.1.2
4 | ddauth - Dragonfly Development CodeIgniter Auth Add-on
5 | http://code.google.com/p/dd-ci-ddauth/
6 | Copyright (c) 2010 Dragonfly Development
7 | Licensed under the New BSD License.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | ddauth - Dragonfly Development CodeIgniter Auth Add-on
2 | http://code.google.com/p/dd-ci-ddauth
3 |
4 |
5 | The ddauth add-on for CodeIgniter is intended to be a flexible authentication
6 | library focussing almost entirely on the problem of creating a secure
7 | authentication ticket and attempts to place as few restrictions as possible
8 | on the application using it.
9 |
10 | The primary purpose for writing this library was the fact that many of the
11 | existing CodeIgniter authentication systems were either too complicated to
12 | implement easily, required too much integration into the application itself
13 | or focused solely on cookies and did not support fallback authentication
14 | methods for when cookies are not available.
15 |
16 | The latter is particularly important when using any sort of application with
17 | a web application that requires authentication as Flash cannot be assumed to
18 | send the browser's cookies reliably. In this case, it is beneficial to be able
19 | to pass the authentication ticket to the Flash movie and instruct it to pass
20 | the ticket along as a GET or POST param.
21 |
22 |
23 | The core security principles were inspired by the "Dos and Don'ts of Client
24 | Authentication on the Web" document found here:
25 |
26 | http://cookies.lcs.mit.edu/pubs/webauth:tr.pdf
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, Dragonfly Development Inc
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of Dragonfly Development Inc nor the names of its
13 | contributors may be used to endorse or promote products derived from
14 | this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/phpdoc.ini:
--------------------------------------------------------------------------------
1 | [Parse Data]
2 | title = ddauth Manual
3 |
4 | ;; parse files that start with a . like .bash_profile
5 | ;; legal values: true, false
6 | hidden = false
7 |
8 | ;; show elements marked @access private in documentation by setting this to on
9 | ;; legal values: on, off
10 | parseprivate = off
11 |
12 | ;; parse with javadoc-like description (first sentence is always the short description)
13 | ;; legal values: on, off
14 | javadocdesc = off
15 |
16 | ;; add any custom @tags separated by commas here
17 | ;; legal values: any legal tagname separated by commas.
18 | ;customtags = mytag1,mytag2
19 |
20 | ;; This is only used by the XML:DocBook/peardoc2 converter
21 | defaultcategoryname = Documentation
22 |
23 | ;; what is the main package?
24 | ;; legal values: alphanumeric string plus - and _
25 | defaultpackagename = ddauth
26 |
27 | ;; output any parsing information? set to on for cron jobs
28 | ;; legal values: on
29 | ;quiet = on
30 |
31 | ;; parse a PEAR-style repository. Do not turn this on if your project does
32 | ;; not have a parent directory named "pear"
33 | ;; legal values: on/off
34 | pear = on
35 |
36 | ;; where should the documentation be written?
37 | ;; legal values: a legal path
38 | ;target = /home/cellog/output
39 | target = docs
40 |
41 | ;; Which files should be parsed out as special documentation files, such as README,
42 | ;; INSTALL and CHANGELOG? This overrides the default files found in
43 | ;; phpDocumentor.ini (this file is not a user .ini file, but the global file)
44 | readmeinstallchangelog = README, INSTALL, FAQ, LICENSE, Release-1.4.0, LICENSE.txt
45 |
46 | ;; limit output to the specified packages, even if others are parsed
47 | ;; legal values: package names separated by commas
48 | ;packageoutput = package1,package2
49 | packageoutput = ddauth
50 |
51 | ;; comma-separated list of files to parse
52 | ;; legal values: paths separated by commas
53 | ;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
54 |
55 | ;; comma-separated list of directories to parse
56 | ;; legal values: directory paths separated by commas
57 | ;directory = /path1,/path2,.,..,subdirectory
58 | ;directory = /home/jeichorn/cvs/pear
59 | ;directory = /home/cellog/workspace/phpdoc
60 | directory = application/libraries
61 |
62 | ;; template base directory (the equivalent directory of /phpDocumentor)
63 | ;templatebase = /path/to/my/templates
64 |
65 | ;; directory to find any example files in through @example and {@example} tags
66 | ;examplesdir = /path/to/my/templates
67 |
68 | ;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
69 | ;; legal values: any wildcard strings separated by commas
70 | ;; remember, this pathing is RELATIVE to the top-most directory in your "directory" value
71 | ;ignore = path/to/ignore*,*list.php,myfile.php,subdirectory/
72 |
73 | ;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
74 | ;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,
75 | ;; HTML:frames:earthli,
76 | ;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,
77 | ;; HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli
78 | ;; HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS
79 | ;; PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default
80 | output=HTML:frames:earthli
81 |
82 | ;; turn this option on if you want highlighted source code for every file
83 | ;; legal values: on/off
84 | sourcecode = on
85 |
--------------------------------------------------------------------------------
/application/config/ddauth.php:
--------------------------------------------------------------------------------
1 |
220 |
--------------------------------------------------------------------------------
/application/libraries/Ddauth.php:
--------------------------------------------------------------------------------
1 | load->helper('url');
183 |
184 | $config = $CI->config;
185 |
186 | if ( ! $config->load('ddauth', false, true) ) {
187 | // Support legacy configuration file... for now.
188 | if ( ! $config->load('dd_ci_ddauth', false, true) ) {
189 | show_error('The ddauth configuration file does not exist.');
190 | }
191 | }
192 |
193 | $this->configurationMethodName = $config->item(
194 | 'ddauth_configurationMethodName'
195 | );
196 |
197 | $this->validateCredentialsMethodName = $config->item(
198 | 'ddauth_validateCredentialsMethodName'
199 | );
200 |
201 | $this->authSuccessMethodName = $config->item(
202 | 'ddauth_authSuccessMethodName'
203 | );
204 |
205 | $this->executeCompleteMethodName = $config->item(
206 | 'ddauth_executeCompleteMethodName'
207 | );
208 |
209 | $this->errorMethodName = $config->item(
210 | 'ddauth_errorMethodName'
211 | );
212 |
213 | // Redirects
214 | $this->signinRedirectPath = $config->item(
215 | 'ddauth_redirects_signin_redirectPath'
216 | );
217 |
218 | // Ticket
219 | $this->ticketSecret = $config->item('ddauth_ticket_secret');
220 | $this->ticketParamName = $config->item('ddauth_ticket_paramName');
221 | $this->ticketExpiration = $config->item('ddauth_ticket_expiration');
222 | $this->ticketKeepalive = $this->_sanitizeBool(
223 | $config->item('ddauth_ticket_keepalive')
224 | );
225 | $this->ticketKeepaliveThreshold = $config->item(
226 | 'ddauth_ticket_keepaliveThreshold'
227 | );
228 |
229 | $this->ticketCookieDomain = $config->item(
230 | 'ddauth_ticket_cookie_domain'
231 | );
232 | $this->ticketCookiePath = $config->item(
233 | 'ddauth_ticket_cookie_path'
234 | );
235 | $this->ticketCookiePrefix = $config->item(
236 | 'ddauth_ticket_cookie_prefix'
237 | );
238 |
239 | // Session
240 | $this->sessionHandler = $config->item('ddauth_session_handler');
241 | $this->allowFlash = $config->item('ddauth_session_allowFlash');
242 |
243 | }
244 |
245 | /**
246 | * Redirect to sign in page
247 | *
248 | * Adds the current URL to the session as the requested URL if
249 | * a requested URL is not already specified and then redirects
250 | * to the sign in page.
251 | */
252 | function redirectToSignin() {
253 |
254 | $CI =& get_instance();
255 | $CI->load->helper('url');
256 |
257 | if ( ! $this->_getSessionData('ddauth.requestedUrl') ) {
258 | $this->_setSessionData('ddauth.requestedUrl', current_url());
259 | }
260 |
261 | redirect($this->signinRedirectPath);
262 |
263 | }
264 |
265 | /**
266 | * Perform login
267 | *
268 | * Performs login for specified username and password. If the
269 | * credentials validate, the ticket is set and the user identification
270 | * is returned.
271 | *
272 | * @param string $username Username
273 | * @param string $password Password
274 | * @return mixed Null or user identification
275 | */
276 | function performLogin($username = null, $password = null) {
277 | if ( $id = $this->_validateCredentials($username, $password) ) {
278 | return $this->setAuthenticatedId($id, true);
279 | }
280 | return null;
281 | }
282 |
283 | /**
284 | * Force set the authenticated user ID.
285 | * @param string $id User ID
286 | * @param bool $isLogin Is this from a login?
287 | * @param bool $sendAuthTicketCookie Should an auth ticket cookie be sent?
288 | * @param int $expires Length of time in seconds that the ticket is valid
289 | */
290 | function setAuthenticatedId($id = null, $isLogin = null, $sendAuthTicketCookie = true, $expires = null) {
291 | $this->id = $id;
292 | $this->isLoggedIn = true;
293 | if ( $sendAuthTicketCookie ) {
294 | $this->_sendAuthTicketCookie(
295 | $this->generateAuthTicket($id, $expires)
296 | );
297 | }
298 | $this->reportAuthSuccess($isLogin);
299 | return $this->id;
300 | }
301 |
302 | /**
303 | * Invalidate an auth ticket cookie
304 | */
305 | function invalidateAuthTicketCookie() {
306 | $this->_sendAuthTicketCookie(null);
307 | }
308 |
309 | /**
310 | * Generate an auth ticket for a user ID
311 | *
312 | * This method allows for the generation of a valid authentication ticket
313 | * for the specified ID.
314 | *
315 | * @param mixed $id User ID
316 | * @param int $expires Length of time in seconds that the ticket is valid
317 | * @return string
318 | */
319 | function generateAuthTicket($id = null, $expires = null) {
320 | if ( $expires === null ) $expires = $this->ticketExpiration;
321 | $data = array('u' => $id, 'tt' => 'auth');
322 | $time = time() + $expires;
323 | $serializedData = serialize($data);
324 | $digest = $this->_generateDigest($serializedData, $time);
325 | return base64_encode('e=' . urlencode($time) . '&d=' . urlencode($serializedData) . '&h=' . urlencode($digest));
326 | }
327 |
328 | /**
329 | * Validate an auth ticket
330 | *
331 | * Decodes the specified authentication ticket and returns an array
332 | * containing information about the ticket.
333 | *
334 | * @param mixed $rawInput Suspected authentication ticket
335 | * @return string Authenticated user ID
336 | */
337 | function decodeAuthTicket($rawInput = null) {
338 |
339 | if ( $rawInput === null ) return null;
340 |
341 | $parts = array();
342 |
343 | foreach ( explode('&', base64_decode($rawInput)) as $pair ) {
344 | $keyValuePair = explode('=', $pair);
345 | if ( count($keyValuePair) == 2 ) {
346 | list($key, $value) = $keyValuePair;
347 | $parts[$key] = urldecode($value);
348 | }
349 | }
350 |
351 | foreach ( array('e', 'h', 'd') as $k ) {
352 | if ( ! array_key_exists($k, $parts) ) return NULL;
353 | }
354 |
355 | $expired = $parts['e'] < time() ? true : false;
356 |
357 | if ( $parts['h'] == $this->_generateDigest($parts['d'], $parts['e']) ) {
358 | return array(
359 | 'token' => $parts,
360 | 'data' => unserialize($parts['d']),
361 | 'expired' => $expired
362 | );
363 | } else {
364 | return NULL;
365 | }
366 |
367 | }
368 |
369 | /**
370 | * Handle authentication success
371 | * @param bool $isLogin Is this a login success?
372 | */
373 | function reportAuthSuccess($isLogin = null) {
374 | return $this->_controllerMethodCallback(
375 | $this->authSuccessMethodName,
376 | $this->authSuccessCb,
377 | array($isLogin)
378 | );
379 | }
380 |
381 | /**
382 | * Handle execute complete
383 | */
384 | function reportExecuteComplete() {
385 | return $this->_controllerMethodCallback(
386 | $this->executeCompleteMethodName,
387 | $this->executeCompleteCb,
388 | array()
389 | );
390 | }
391 |
392 | /**
393 | * Report errors.
394 | *
395 | * Will attempt to execute error callback or call the error method on
396 | * the controller.
397 | * @param string $key Short key identifying the error
398 | * @param string $description Detailed texual description of the error
399 | */
400 | function reportError($key, $description) {
401 | return $this->_controllerMethodCallback(
402 | $this->errorMethodName,
403 | $this->errorCb,
404 | array($key, $description)
405 | );
406 | }
407 |
408 | /**
409 | * Execute authentication
410 | *
411 | * Attempts to handle all of the specified automated auth related tasks
412 | * in one go. Once this method has completed, ddauth should know whether
413 | * or not the end user has been successfully authenticated or not.
414 | *
415 | * Accepts an optional configuration array that will be passed to
416 | * _configure().
417 | *
418 | * @param array $config Additional configuration
419 | * @return bool Was authentication successful?
420 | */
421 | function execute($config = array()) {
422 |
423 | $this->_configure($config);
424 |
425 | $loggedIn = false;
426 |
427 | $loggedOut = $this->_attemptLogout();
428 |
429 | if ( $this->_attemptLogin() ) {
430 | $loggedIn = true;
431 | $loggedOut = false;
432 | }
433 |
434 | if ( $loggedOut ) {
435 |
436 | // If user is logged out, invalidate our ticket.
437 | $this->invalidateAuthTicketCookie();
438 |
439 | } elseif ( ! $loggedIn ) {
440 |
441 | // If we are not already listed as having logged in, we should
442 | // check to see if we are still logged in from before.
443 | if ( ! $this->_attemptContinuation() ) {
444 | // If we failed the continuation attempt we should
445 | // invalidate the ticket.
446 | $this->invalidateAuthTicketCookie();
447 | }
448 |
449 | }
450 |
451 | $this->reportExecuteComplete();
452 | return $this->isLoggedIn;
453 |
454 | }
455 |
456 | /**
457 | * Attempt logging out
458 | *
459 | * If `ddauth_params_logout_paramName` exists in the input specified by
460 | * `ddauth_params_logout_source` the visitor is logged out.
461 | * @return bool Was log this a log out attempt?
462 | */
463 | function _attemptLogout() {
464 |
465 | $CI =& get_instance();
466 | $config = $CI->config;
467 |
468 | $logoutValue = $this->_getLogoutParam();
469 |
470 | if ( $logoutValue ) {
471 | // We have asked to log out! We use this state
472 | // later when we are trying to read auth data.
473 | return true;
474 | }
475 |
476 | return false;
477 |
478 | }
479 |
480 | /**
481 | * Attempt logging in
482 | *
483 | * If `ddauth_params_login_paramName` exists in the input specified by
484 | * `ddauth_params_login_source` the visitor's credentials as specified by
485 | * `ddauth_params_login_usernameParamName` and
486 | * `ddauth_params_login_passwordParamName` are tested.
487 | * @return bool Was log in attempt a success?
488 | */
489 | function _attemptLogin() {
490 |
491 | $loginValue = $this->_getLoginParam();
492 |
493 | if ( $loginValue ) {
494 |
495 | $username = $this->_getLoginUsernameParam();
496 | $password = $this->_getLoginPasswordParam();
497 |
498 | if ( $id = $this->performLogin($username, $password) ) {
499 | if ( $requestedUrl = $this->_getSessionData('ddauth.requestedUrl') ) {
500 | $this->_unsetSessionData('ddauth.requestedUrl');
501 | redirect($requestedUrl);
502 | }
503 | return true;
504 | } else {
505 | $this->reportError(
506 | 'attemptLogin.invalid',
507 | 'Login attempt failure, unknown user or incorrect password'
508 | );
509 | $this->invalidateAuthTicketCookie();
510 | $this->redirectToSignin();
511 | }
512 |
513 | }
514 |
515 | return false;
516 |
517 | }
518 |
519 | /**
520 | * Attempt continuation of an existing ticket
521 | *
522 | * Checks to see if a ticket already exists and validates the ticket and
523 | * ensures that the ticket has not already expired.
524 | * @return bool Was continuation attempt a success?
525 | */
526 | function _attemptContinuation() {
527 |
528 | $authData = $this->_findAndDecodeAuthTicket();
529 |
530 | // If there was no auth data, this is still a success case since
531 | // we are going to assume that this is a "continuation" of a
532 | // non-logged in session.
533 | if ( $authData === null ) { return true; }
534 |
535 | // If the ticket has expired, this is a failure.
536 | if ( $authData['expired'] ) { return false; }
537 |
538 | // TODO Do we need to make the ticket type configurable?
539 | if ( isset($authData['data']['tt']) and $authData['data']['tt'] == 'auth' ) {
540 |
541 | $this->id = $authData['data']['u'];
542 | $this->isLoggedIn = true;
543 | $this->reportAuthSuccess(false);
544 |
545 | if ( $this->ticketKeepalive ) {
546 | $e = $authData['token']['e'];
547 | $timeRunning = $this->ticketExpiration - ( $e - time() );
548 | if ( $timeRunning > $this->ticketKeepaliveThreshold ) {
549 | $this->_sendAuthTicketCookie(
550 | $this->generateAuthTicket($this->id)
551 | );
552 | }
553 |
554 | }
555 |
556 | return true;
557 |
558 | }
559 |
560 | return false;
561 |
562 | }
563 |
564 | /**
565 | * Send the auth ticket cookie
566 | * @input mixed $value Value
567 | * @param int $expires Length of time in seconds that the ticket is valid
568 | */
569 | function _sendAuthTicketCookie($value = null, $expires = null) {
570 | if ( $expires === null ) $expires = $this->ticketExpiration;
571 | $this->reportError('setCookie', $value);
572 | if ( $this->shouldSendAuthTicketCookie ) {
573 | $CI =& get_instance();
574 | $CI->load->helper('cookie');
575 | set_cookie(array(
576 | 'name' => $this->ticketParamName,
577 | 'value' => $value,
578 | 'expire' => time() + $expires,
579 | 'domain' => $this->ticketCookieDomain,
580 | 'path' => $this->ticketCookiePath,
581 | 'prefix' => $this->ticketCookiePrefix
582 | ));
583 | }
584 | }
585 |
586 | /**
587 | * Get the value for the logout paramater.
588 | * @return string
589 | */
590 | function _getLogoutParam() {
591 | return $this->_getConfigParam(
592 | 'ddauth_params_logout_source',
593 | 'ddauth_params_logout_paramName'
594 | );
595 | }
596 |
597 | /**
598 | * Get the value for the login paramater.
599 | * @return string
600 | */
601 | function _getLoginParam() {
602 | return $this->_getConfigParam(
603 | 'ddauth_params_login_source',
604 | 'ddauth_params_login_paramName'
605 | );
606 | }
607 |
608 | /**
609 | * Get the value for the login username paramater.
610 | * @return string
611 | */
612 | function _getLoginUsernameParam() {
613 | return $this->_getConfigParam(
614 | 'ddauth_params_login_source',
615 | 'ddauth_params_login_usernameParamName'
616 | );
617 | }
618 |
619 | /**
620 | * Get the value for the login password paramater.
621 | * @return string
622 | */
623 | function _getLoginPasswordParam() {
624 | return $this->_getConfigParam(
625 | 'ddauth_params_login_source',
626 | 'ddauth_params_login_passwordParamName'
627 | );
628 | }
629 |
630 | /**
631 | * Get a config param from the request
632 | *
633 | * ddauth receives information from the request enviornment and
634 | * depending on the security requirements, the params may be
635 | * retrieved by either GET, POST or EITHER.
636 | *
637 | * This method ensures that the requested param specified by $configName
638 | * is only retrieved from the sources described by $sourceName.
639 | *
640 | * @param string $sourceName Config name of allowed source
641 | * @param string $configName Config name of the param
642 | */
643 | function _getConfigParam($sourceName, $paramName) {
644 |
645 | if ( isset($this->_configParamCache[$sourceName][$paramName]) ) {
646 | return $this->_configParamCache[$sourceName][$paramName];
647 | }
648 |
649 | if ( ! isset($this->_configParamCache[$sourceName]) ) {
650 | $this->_configParamCache[$sourceName] = array();
651 | }
652 |
653 | $CI =& get_instance();
654 | $config = $CI->config;
655 | $input = $CI->input;
656 |
657 | $source = $this->_sanitizeSource($config->item($sourceName));
658 | $param = $config->item($paramName);
659 |
660 | $rv = null;
661 |
662 | if ( $source == 'either') {
663 | $rv = $input->get_post($param);
664 | }
665 | elseif ( $source == 'post' ) {
666 | $rv = $input->post($param);
667 | }
668 | elseif ( $source == 'get' ) {
669 | $rv = $input->get($param);
670 | }
671 |
672 | $this->_configParamCache[$sourceName][$paramName] = $rv;
673 |
674 | return $rv;
675 |
676 | }
677 |
678 | /**
679 | * Sanitize a bool value
680 | * @param mixed $value Input
681 | * @return bool
682 | */
683 | function _sanitizeBool($value = null) {
684 | if ( $value === true ) return true;
685 | if ( strtolower($value) == 'true' ) return true;
686 | if ( $value == 1 ) return true;
687 | return false;
688 | }
689 |
690 | /**
691 | * Sanitize a source value
692 | * @param mixed $value Input
693 | * @return string
694 | */
695 | function _sanitizeSource($sourceValue) {
696 | if ( preg_match('/^\s*(either|get|post)\s*$/i', $sourceValue, $matches) ) {
697 | return strtolower($matches[1]);
698 | }
699 | return null;
700 | }
701 |
702 | /**
703 | * Call a method on a controller or execute a callback
704 | *
705 | * Order of operations is as follows: $cb then controller method
706 | * @param string $methodName Name of method that should exist on controller
707 | * @param callback $cb Callback to execute
708 | * @param array $args Arguments to send to method
709 | */
710 | function _controllerMethodCallback($methodName, $cb = null, $args = null) {
711 | if ( $args === null ) $args = array();
712 | if ( $cb === null ) {
713 | $CI =& get_instance();
714 | if ( method_exists($CI, $methodName) ) {
715 | $cb = array($CI, $methodName);
716 | }
717 | }
718 | if ( $cb !== null ) { return call_user_func_array($cb, $args); }
719 | }
720 |
721 | /**
722 | * Configure.
723 | *
724 | * Will attempt to execute configuration callback or call the configuration
725 | * method on the controller.
726 | *
727 | * Optional configuration array can be used to set a select number
728 | * of options at configuration time. Currently supports:
729 | *
730 | * 'shouldSendAuthTicketCookie'
731 | * 'configurationMethodName'
732 | * 'validateCredentialsMethodName'
733 | * 'authSuccessMethodName'
734 | * 'executeCompleteMethodName'
735 | * 'errorMethodName'
736 | * 'configurationCb'
737 | * 'validateCredentialsCb'
738 | * 'authSuccessCb'
739 | * 'executeCompleteCb'
740 | * 'errorCb'
741 | *
742 | * @param array $config Configuration array
743 | */
744 | function _configure($config = array()) {
745 | foreach ( $config as $key => $value ) {
746 | switch($key) {
747 | case 'shouldSendAuthTicketCookie':
748 | case 'configurationMethodName':
749 | case 'validateCredentialsMethodName':
750 | case 'authSuccessMethodName':
751 | case 'executeCompleteMethodName':
752 | case 'errorMethodName':
753 | case 'configurationCb':
754 | case 'validateCredentialsCb':
755 | case 'authSuccessCb':
756 | case 'executeCompleteCb':
757 | case 'errorCb':
758 | $this->$key = $value;
759 | break;
760 | }
761 | }
762 | return $this->_controllerMethodCallback(
763 | $this->configurationMethodName,
764 | $this->configurationCb,
765 | array($config)
766 | );
767 | }
768 |
769 | /**
770 | * Validate credentials.
771 | *
772 | * Will attempt to validate credentials using the credential validation
773 | * callback or call the credential validation method on the controller.
774 | * @param string $username Username to validate
775 | * @param string $password Password to validate
776 | */
777 | function _validateCredentials($username = null, $password = null) {
778 | return $this->_controllerMethodCallback(
779 | $this->validateCredentialsMethodName,
780 | $this->validateCredentialsCb,
781 | array($username, $password)
782 | );
783 | }
784 |
785 | /**
786 | * Initialize session handling.
787 | *
788 | * Session handling can be very specific to an application so we need
789 | * to be flexible in how we handle sessions. Setting and getting have
790 | * been abstracted out such that this library only directly refers to
791 | * _setSessionFlashData(), _setSessionData(), _unsetSessionData() and
792 | * _getSessionData().
793 | *
794 | * These methods will call the appropriate implementation based on
795 | * how the session handling has been setup and initialized here.
796 | */
797 | function _initSession() {
798 | if ( ! $this->isSessionInitialized ) {
799 | switch($this->sessionHandler) {
800 | case 'ci':
801 | // Native CodeIgnither sessions are what
802 | // we prefer so the interface resembles
803 | // it a great deal. However, the system
804 | // should hopefully be flexible enough
805 | // to accommodate many types of session
806 | // handling.
807 | $CI =& get_instance();
808 | $CI->load->library('session');
809 | $this->_setSessionFlashDataCb = array(
810 | $this, '_setSessionFlashDataCi'
811 | );
812 | $this->_setSessionDataCb = array(
813 | $this, '_setSessionDataCi'
814 | );
815 | $this->_unsetSessionDataCb = array(
816 | $this, '_unsetSessionDataCi'
817 | );
818 | $this->_getSessionDataCb = array(
819 | $this, '_getSessionDataCi'
820 | );
821 | break;
822 | case 'php':
823 | // Native PHP sessions are going to be
824 | // supported eventually.
825 | $this->_setSessionFlashDataCb = array(
826 | $this, '_setSessionFlashDataPhp'
827 | );
828 | $this->_setSessionDataCb = array(
829 | $this, '_setSessionDataPhp'
830 | );
831 | $this->_unsetSessionDataCb = array(
832 | $this, '_unsetSessionDataPhp'
833 | );
834 | $this->_getSessionDataCb = array(
835 | $this, '_getSessionDataPhp'
836 | );
837 | break;
838 | case 'callbacks':
839 | // Callbacks for each of these three functions
840 | // will be supported eventually.
841 | $this->_setSessionFlashDataCb = array(
842 | $this, '_setSessionFlashDataCallbacks'
843 | );
844 | $this->_setSessionDataCb = array(
845 | $this, '_setSessionDataCallbacks'
846 | );
847 | $this->_unsetSessionDataCb = array(
848 | $this, '_unsetSessionDataCallbacks'
849 | );
850 | $this->_getSessionDataCb = array(
851 | $this, '_getSessionDataCallbacks'
852 | );
853 | break;
854 | case 'methods':
855 | // Method names to be called on the controller for
856 | // each of these three functions will be
857 | // supported eventually.
858 | $this->_setSessionFlashDataCb = array(
859 | $this, '_setSessionFlashDataMethods'
860 | );
861 | $this->_setSessionDataCb = array(
862 | $this, '_setSessionDataMethods'
863 | );
864 | $this->_unsetSessionDataCb = array(
865 | $this, '_unsetSessionDataMethods'
866 | );
867 | $this->_getSessionDataCb = array(
868 | $this, '_getSessionDataMethods'
869 | );
870 | break;
871 | default:
872 | $this->reportError(
873 | 'session.unsupported',
874 | 'Unsupported session handler specified: "' .
875 | $this->sessionHandler .
876 | '"'
877 | );
878 | break;
879 | }
880 | $this->isSessionInitialized = true;
881 | }
882 | }
883 |
884 | /**
885 | * Set session flash data
886 | *
887 | * Routes to the appropriate underlying session handler implementation.
888 | */
889 | function _setSessionFlashData($key, $value = null) {
890 | if ( ! $this->allowFlash ) {
891 | return $this->_setSessionData($key, $value);
892 | }
893 | $this->_initSession();
894 | return call_user_func($this->_setSessionFlashDataCb, $key, $value);
895 | }
896 | /**
897 | * Set session data
898 | *
899 | * Routes to the appropriate underlying session handler implementation.
900 | */
901 | function _setSessionData($key, $value = null) {
902 | $this->_initSession();
903 | return call_user_func($this->_setSessionDataCb, $key, $value);
904 | }
905 |
906 | /**
907 | * Unset session data
908 | *
909 | * Routes to the appropriate underlying session handler implementation.
910 | */
911 | function _unsetSessionData($key) {
912 | $this->_initSession();
913 | return call_user_func($this->_unsetSessionDataCb, $key);
914 | }
915 |
916 | /**
917 | * Get session data
918 | *
919 | * Routes to the appropriate underlying session handler implementation.
920 | */
921 | function _getSessionData($key) {
922 | $this->_initSession();
923 | return call_user_func($this->_getSessionDataCb, $key);
924 | }
925 |
926 | /**
927 | * CodeIgniter implementation of _setSessionFlashData
928 | */
929 | function _setSessionFlashDataCi($key, $value = null) {
930 | $CI =& get_instance();
931 | return $CI->session->set_flashdata($key, $value);
932 | }
933 |
934 | /**
935 | * CodeIgniter implementation of _setSessionData
936 | */
937 | function _setSessionDataCi($key, $value = null) {
938 | $CI =& get_instance();
939 | return $CI->session->set_userdata($key, $value);
940 | }
941 |
942 | /**
943 | * CodeIgniter implementation of _unsetSessionData
944 | */
945 | function _unsetSessionDataCi($key) {
946 | $CI =& get_instance();
947 | return $CI->session->unset_userdata($key);
948 | }
949 |
950 | /**
951 | * CodeIgniter implementation of _getSessionData
952 | */
953 | function _getSessionDataCi($key) {
954 | $CI =& get_instance();
955 | return $CI->session->userdata($key);
956 | }
957 |
958 | /**
959 | * PHP Session implementation of _setSessionFlashData
960 | */
961 | function _setSessionFlashDataPhp($key, $value = null) {
962 | throw new Exception('Set Session Flash Data for PHP not implemented.');
963 | }
964 |
965 | /**
966 | * PHP Session implementation of _setSessionData
967 | */
968 | function _setSessionDataPhp($key, $value = null) {
969 | throw new Exception('Set Session Data for PHP not implemented.');
970 | }
971 |
972 | /**
973 | * PHP Session implementation of _unsetSessionData
974 | */
975 | function _unsetSessionDataPhp($key) {
976 | throw new Exception('Unset Session Data for PHP not implemented.');
977 | }
978 |
979 | /**
980 | * PHP Session implementation of _getSessionData
981 | */
982 | function _getSessionDataPhp($key) {
983 | throw new Exception('Get Session Data for PHP not implemented.');
984 | }
985 |
986 | /**
987 | * Callbacks Session implementation of _setSessionFlashData
988 | */
989 | function _setSessionFlashDataCallbacks($key, $value = null) {
990 | throw new Exception(
991 | 'Set Session Flash Data for Callbacks not implemented.'
992 | );
993 | }
994 |
995 | /**
996 | * Callbacks Session implementation of _setSessionData
997 | */
998 | function _setSessionDataCallbacks($key, $value = null) {
999 | throw new Exception('Set Session Data for Callbacks not implemented.');
1000 | }
1001 |
1002 | /**
1003 | * Callbacks Session implementation of _unsetSessionData
1004 | */
1005 | function _unsetSessionDataCallbacks($key) {
1006 | throw new Exception(
1007 | 'Unset Session Data for Callbacks not implemented.'
1008 | );
1009 | }
1010 |
1011 | /**
1012 | * Callbacks Session implementation of _getSessionData
1013 | */
1014 | function _getSessionDataCallbacks($key) {
1015 | throw new Exception('Get Session Data for Callbacks not implemented.');
1016 | }
1017 |
1018 | /**
1019 | * Methods Session implementation of _setSessionFlashData
1020 | */
1021 | function _setSessionFlashDataMethods($key, $value = null) {
1022 | throw new Exception(
1023 | 'Set Session Flash Data for Methods not implemented.'
1024 | );
1025 | }
1026 |
1027 | /**
1028 | * Methods Session implementation of _setSessionData
1029 | */
1030 | function _setSessionDataMethods($key, $value = null) {
1031 | throw new Exception('Set Session Data for Methods not implemented.');
1032 | }
1033 |
1034 | /**
1035 | * Methods Session implementation of _unsetSessionData
1036 | */
1037 | function _unsetSessionDataMethods($key) {
1038 | throw new Exception('Unset Session Data for Methods not implemented.');
1039 | }
1040 |
1041 | /**
1042 | * Methods Session implementation of _getSessionData
1043 | */
1044 | function _getSessionDataMethods($key) {
1045 | throw new Exception('Get Session Data for Methods not implemented.');
1046 | }
1047 |
1048 | /**
1049 | * Find and decode auth ticket from request
1050 | */
1051 | function _findAndDecodeAuthTicket() {
1052 |
1053 | $CI =& get_instance();
1054 |
1055 | $input = $CI->input;
1056 |
1057 | $key = $this->ticketParamName;
1058 |
1059 | // This little IF block is designed to find the first
1060 | // place that the specified key exists and then break.
1061 | // If we get through all three input sources and still
1062 | // do not have any auth string, we return NULL so that
1063 | // the calller knows that we were not able to validate
1064 | // auth.
1065 | if ( ! (
1066 | ( ( $authString = $input->get($key) ) != "" ) or
1067 | ( ( $authString = $input->post($key) ) != "" ) or
1068 | ( ( $authString = $input->cookie($key) ) != "" )
1069 | ) ) {
1070 | return NULL;
1071 | }
1072 |
1073 | $authTicket = $this->decodeAuthTicket($authString);
1074 | if ( $authTicket === null ) {
1075 | // We found an auth string but it is invalid! We should
1076 | // make sure that nobody tries this funny business
1077 | // again!
1078 | $this->invalidateAuthTicketCookie();
1079 | }
1080 | return $authTicket;
1081 |
1082 | }
1083 |
1084 | /**
1085 | * Generate a digest for the specified data and expiration time
1086 | * @param string $data Data
1087 | * @param int $time Expiration time
1088 | * @return string
1089 | */
1090 | function _generateDigest($data, $time) {
1091 | return sha1( $time . $data . $this->ticketSecret );
1092 | }
1093 |
1094 | }
1095 |
1096 | ?>
1097 |
--------------------------------------------------------------------------------