├── .gitignore ├── Strategy ├── .gitignore └── README.md ├── .gitmodules ├── Config ├── routes.php └── bootstrap.php ├── Controller ├── OpauthController.php └── OpauthAppController.php ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /Strategy/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore strategies 2 | */ 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Vendor/Opauth"] 2 | path = Vendor/Opauth 3 | url = git://github.com/opauth/opauth.git 4 | -------------------------------------------------------------------------------- /Config/routes.php: -------------------------------------------------------------------------------- 1 | 'Opauth', 'controller' => 'Opauth', 'action' => 'callback')); 6 | Router::connect('/auth/*', array('plugin' => 'Opauth', 'controller' => 'Opauth', 'action' => 'index')); 7 | -------------------------------------------------------------------------------- /Controller/OpauthController.php: -------------------------------------------------------------------------------- 1 | modelClass = null; 7 | } 8 | 9 | public function beforeFilter() { 10 | // Allow access to Opauth methods for users of AuthComponent 11 | if (is_object($this->Auth) && method_exists($this->Auth, 'allow')) { 12 | $this->Auth->allow(); 13 | } 14 | 15 | //Disable Security for the plugin actions in case that Security Component is active 16 | if (is_object($this->Security)) { 17 | $this->Security->validatePost = false; 18 | $this->Security->csrfCheck = false; 19 | } 20 | // allow parent (e.g. AppController) to have a say! 21 | parent::beforeFilter(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Strategy/README.md: -------------------------------------------------------------------------------- 1 | # Place individual specific strategies here. 2 | 3 | How 4 | ------ 5 | ### Download and unzip 6 | Download additional [strategies](https://github.com/uzyn/opauth/wiki/List-of-strategies) and place them in directories here. 7 | Remember to name the directory name as the actual name of the strategy. For example, place [Facebook strategy](https://github.com/opauth/facebook) files in `./Facebook/` so that `FacebookStrategy.php` can be found at `./Facebook/FacebookStrategy.php`. 8 | 9 | ### Git clone 10 | If you prefer `git clone`, you can simply run the following at this dir without worrying about renaming: 11 | 12 | ```bash 13 | git clone git://github.com/opauth/facebook.git Facebook 14 | ``` 15 | 16 | More strategies 17 | --------------- 18 | Check out the wiki for [more strategies](https://github.com/uzyn/opauth/wiki/List-of-strategies). -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Opauth plugin for CakePHP (http://opauth.org) 4 | Copyright © 2012-2013 U-Zyn Chua (http://uzyn.com) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a 7 | copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Config/bootstrap.php: -------------------------------------------------------------------------------- 1 | true, 'bootstrap' => true)); 8 | */ 9 | 10 | 11 | /** 12 | * Path where Opauth is accessed. 13 | * 14 | * Begins and ends with / 15 | * eg. if Opauth is reached via http://example.org/auth/, path is '/auth/' 16 | */ 17 | Configure::write('Opauth.path', '/auth/'); 18 | 19 | /** 20 | * Whether to view Opauth debug messages 21 | * Value is automatically set according to CakePHP's app debug value. 22 | */ 23 | Configure::write('Opauth.debug', (Configure::read('debug') !== 0)); 24 | 25 | /** 26 | * Callback URL: redirected to after authentication, successful or otherwise 27 | */ 28 | Configure::write('Opauth.callback_url', Configure::read('Opauth.path').'callback'); 29 | 30 | /** 31 | * Callback transport, for sending of $auth response 32 | * 33 | * 'session': Works best unless callback_url is on a different domain than Opauth 34 | * 'post' : Works cross-domain, but relies on availability of client-side JavaScript. 35 | * : Default for CakePHP plugin contrary to Opauth core as session may cause issues on some 36 | * : cases of CakePHP's session handling 37 | * 'get' : Works cross-domain, but may be limited or corrupted by browser URL length limit 38 | * (eg. IE8/IE9 has 2083-char limit) 39 | */ 40 | Configure::write('Opauth.callback_transport', 'post'); 41 | 42 | /** 43 | * A random string used for signing of $auth response. 44 | * 45 | * Sets to Security.salt's value by default 46 | */ 47 | Configure::write('Opauth.security_salt', Configure::read('Security.salt')); 48 | 49 | /** 50 | * Higher value, better security, slower hashing; 51 | * Lower value, lower security, faster hashing. 52 | */ 53 | //Configure::write('Opauth.security_iteration', 300); 54 | 55 | /** 56 | * Time limit for valid $auth response, starting from $auth response generation to validation. 57 | */ 58 | //Configure::write('Opauth.security_timeout', '2 minutes'); 59 | 60 | /** 61 | * Directory where Opauth strategies reside 62 | */ 63 | Configure::write('Opauth.strategy_dir', dirname(dirname(__FILE__)).'/Strategy/'); 64 | 65 | /** 66 | * Strategy 67 | * Refer to individual strategy's documentation on configuration requirements. 68 | * 69 | * Add strategy configurations in your app's bootstrap.php in the following format: 70 | * 71 | * Configure::write('Opauth.Strategy.Facebook', array( 72 | * 'app_id' => 'YOUR FACEBOOK APP ID', 73 | * 'app_secret' => 'YOUR FACEBOOK APP SECRET' 74 | * )); 75 | * 76 | */ 77 | Configure::write('Opauth.Strategy', array()); -------------------------------------------------------------------------------- /Controller/OpauthAppController.php: -------------------------------------------------------------------------------- 1 | autoRender = false; 24 | } 25 | 26 | /** 27 | * Catch all for Opauth 28 | */ 29 | public function index(){ 30 | $this->_loadOpauth(); 31 | $this->Opauth->run(); 32 | 33 | return; 34 | } 35 | 36 | /** 37 | * Receives auth response and does validation 38 | */ 39 | public function callback(){ 40 | $response = null; 41 | 42 | /** 43 | * Fetch auth response, based on transport configuration for callback 44 | */ 45 | switch(Configure::read('Opauth.callback_transport')){ 46 | case 'session': 47 | if (!session_id()){ 48 | session_start(); 49 | } 50 | 51 | if(isset($_SESSION['opauth'])) { 52 | $response = $_SESSION['opauth']; 53 | unset($_SESSION['opauth']); 54 | } 55 | break; 56 | case 'post': 57 | $response = unserialize(base64_decode( $_POST['opauth'] )); 58 | break; 59 | case 'get': 60 | $response = unserialize(base64_decode( $_GET['opauth'] )); 61 | break; 62 | default: 63 | echo 'Error: Unsupported callback_transport.'."
\n"; 64 | break; 65 | } 66 | 67 | /** 68 | * Check if it's an error callback 69 | */ 70 | if (isset($response) && is_array($response) && array_key_exists('error', $response)) { 71 | // Error 72 | $response['validated'] = false; 73 | } 74 | 75 | /** 76 | * Auth response validation 77 | * 78 | * To validate that the auth response received is unaltered, especially auth response that 79 | * is sent through GET or POST. 80 | */ 81 | else{ 82 | $this->_loadOpauth(); 83 | 84 | if (empty($response['auth']) || empty($response['timestamp']) || empty($response['signature']) || empty($response['auth']['provider']) || empty($response['auth']['uid'])){ 85 | $response['error'] = array( 86 | 'provider' => $response['auth']['provider'], 87 | 'code' => 'invalid_auth_missing_components', 88 | 'message' => 'Invalid auth response: Missing key auth response components.' 89 | ); 90 | $response['validated'] = false; 91 | } 92 | elseif (!($this->Opauth->validate(sha1(print_r($response['auth'], true)), $response['timestamp'], $response['signature'], $reason))){ 93 | $response['error'] = array( 94 | 'provider' => $response['auth']['provider'], 95 | 'code' => 'invalid_auth_failed_validation', 96 | 'message' => 'Invalid auth response: '.$reason 97 | ); 98 | $response['validated'] = false; 99 | } 100 | else{ 101 | $response['validated'] = true; 102 | } 103 | } 104 | 105 | /** 106 | * Redirect user to /opauth-complete 107 | * with validated response data available as POST data 108 | * retrievable at $this->data at your app's controller 109 | */ 110 | $completeUrl = Configure::read('Opauth._cakephp_plugin_complete_url'); 111 | if (empty($completeUrl)) $completeUrl = Router::url('/opauth-complete'); 112 | 113 | 114 | $CakeRequest = new CakeRequest('/opauth-complete'); 115 | $CakeRequest->data = $response; 116 | 117 | $Dispatcher = new Dispatcher(); 118 | $Dispatcher->dispatch( $CakeRequest, new CakeResponse() ); 119 | exit(); 120 | } 121 | 122 | /** 123 | * Instantiate Opauth 124 | * 125 | * @param array $config User configuration 126 | * @param boolean $run Whether Opauth should auto run after initialization. 127 | */ 128 | protected function _loadOpauth($config = null, $run = false){ 129 | // Update dependent config in case the dependency is overwritten at app-level 130 | if (Configure::read('Opauth.callback_url') == '/auth/callback') { 131 | Configure::write('Opauth.callback_url', Configure::read('Opauth.path').'callback'); 132 | } 133 | 134 | if (is_null($config)){ 135 | $config = Configure::read('Opauth'); 136 | } 137 | 138 | App::import('Vendor', 'Opauth.Opauth/lib/Opauth/Opauth'); 139 | $this->Opauth = new Opauth( $config, $run ); 140 | } 141 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CakePHP plugin for Opauth 2 | ========================= 3 | 4 | CakePHP 2.x plugin for [Opauth](https://github.com/uzyn/opauth). 5 | 6 | Opauth is a multi-provider authentication framework. 7 | 8 | Requirements 9 | --------- 10 | CakePHP v2.x 11 | Opauth >= v0.2 _(submoduled with this package)_ 12 | 13 | Using [Composer](http://getcomposer.org/)? 14 | ----------- 15 | You can install CakePHP-Opauth plugin directly from Composer at [uzyn/cakephp-opauth](http://packagist.org/packages/uzyn/cakephp-opauth). 16 | It works for Opauth strategies too! 17 | 18 | View notes and Composer-enabled plugin code at [composer branch](https://github.com/uzyn/cakephp-opauth/tree/composer). 19 | 20 | Tutorial & sample app 21 | ---------- 22 | Check out [CakePHP bakery](http://bakery.cakephp.org/articles/uzyn/2012/06/25/simple_3rd-party_provider_authentication_with_opauth_plugin) for tutorial and the [sample branch](https://github.com/uzyn/cakephp-opauth/tree/sample) for a quick sample app. 23 | 24 | How to use 25 | ---------- 26 | 1. Install this plugin for your CakePHP app. 27 | Assuming `APP` is the directory where your CakePHP app resides, it's usually `app/` from the base of CakePHP. 28 | 29 | ```bash 30 | cd APP/Plugin 31 | git clone git://github.com/uzyn/cakephp-opauth.git Opauth 32 | ``` 33 | 34 | 2. Download Opauth library as a submodule. 35 | 36 | ```bash 37 | git submodule init 38 | git submodule update 39 | ``` 40 | 41 | 3. Add this line to the bottom of your app's `Config/bootstrap.php`: 42 | 43 | ```php 44 | true, 'bootstrap' => true)); 46 | ``` 47 | Overwrite any Opauth configurations you want after the above line. 48 | 49 | 4. Load [strategies](https://github.com/uzyn/opauth/wiki/list-of-strategies) onto `Strategy/` directory. 50 | 51 | Append configuration for strategies at your app's `Config/bootstrap.php` as follows: 52 | ```php 53 | true, 'bootstrap' => true)); 55 | 56 | // Using Facebook strategy as an example 57 | Configure::write('Opauth.Strategy.Facebook', array( 58 | 'app_id' => 'YOUR FACEBOOK APP ID', 59 | 'app_secret' => 'YOUR FACEBOOK APP SECRET' 60 | )); 61 | ``` 62 | 63 | 5. Go to `http://path_to_your_cake_app/auth/facebook` to authenticate with Facebook, and similarly for other strategies that you have loaded. 64 | 65 | 6. After validation, user will be redirected to `Router::url('/opauth-complete')` with validated auth response data retrievable available at `$this->data`. 66 | 67 | To route a controller to handle the response, at your app's `Config/routes.php`, add a connector, for example: 68 | 69 | ```php 70 | 'users', 'action' => 'opauth_complete') 74 | ); 75 | ``` 76 | 77 | You can then work with the authentication data at, say `APP/Controller/UsersController.php` as follows: 78 | 79 | ```php 80 | data); 84 | } 85 | } 86 | ``` 87 | 88 | Note that this CakePHP Opauth plugin already does auth response validation for you with its results available as a boolean value at `$this->data['validated']`. 89 | 90 | 7. _(optional)_ The submoduled Opauth core library may not be of the latest build, to update to the latest: 91 | ```bash 92 | git submodule foreach git pull origin master 93 | ``` 94 | 95 | ### Note: 96 | If your CakePHP app **does not** reside at DocumentRoot (eg. `http://localhost`), but at a directory below DocumentRoot (eg. `http://localhost/your-cake-app`), 97 | add this line to your app's `APP/Config/bootstrap.php`, replacing `your-cake-app` with your actual path : 98 | 99 | ```php 100 | Used this plugin in your CakePHP project? Let us know!

114 | 115 | License 116 | --------- 117 | The MIT License 118 | Copyright © 2012-2013 U-Zyn Chua (http://uzyn.com) 119 | 120 | Package building instructions 121 | -------------- 122 | Instructions for making into a nice zipped package for download. 123 | 124 | ```bash 125 | git checkout master 126 | git submodule update --init --recursive 127 | 128 | rm -rf `find . -type d -name .git` 129 | 130 | cd .. 131 | mv cakephp-opauth Opauth 132 | 133 | zip -mr Opauth-CakePHP-plugin-X.Y.Z.zip Opauth 134 | ``` 135 | 136 | 137 | 138 | Consultation 139 | --------- 140 | U-Zyn Chua is the Principal Consultant at [Zynesis Consulting](http://zynesis.com), specializing in CakePHP. 141 | Looking for PHP web development solutions or consultation? [Drop me a mail](mailto:chua@uzyn.com). 142 | --------------------------------------------------------------------------------