├── README ├── class ├── Consumer.class.php ├── Db.class.php ├── Provider.class.php ├── Token.class.php └── User.class.php ├── client ├── apicall.php ├── callback.php └── index.php ├── interfaces ├── IConsumer.php ├── IToken.php └── IUser.php ├── oauth ├── .htaccess ├── index.php └── login.php └── sql └── schema.sql /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djpate/OAuthProviderExample/251bc14715c7933490caf58c167a2a76cb47ce64/README -------------------------------------------------------------------------------- /class/Consumer.class.php: -------------------------------------------------------------------------------- 1 | query("select id from consumer where consumer_key = '".$key."'"); // this is not safe ! 20 | if($info->rowCount()==1){ 21 | $info = $info->fetch(); 22 | $consumer = new Consumer($info['id']); 23 | } 24 | return $consumer; 25 | } 26 | 27 | public function __construct($id = 0){ 28 | $this->pdo = Db::singleton(); 29 | if($id != 0){ 30 | $this->id = $id; 31 | $this->load(); 32 | } 33 | } 34 | 35 | private function load(){ 36 | $info = $this->pdo->query("select * from consumer where id = '".$this->id."'")->fetch(); 37 | $this->id = $this->id; 38 | $this->key = $info['consumer_key']; 39 | $this->secret = $info['consumer_secret']; 40 | $this->active = $info['active']; 41 | } 42 | 43 | public static function create($key,$secret){ 44 | $pdo = Db::singleton(); 45 | $pdo->exec("insert into consumer (consumer_key,consumer_secret,active) values ('".$key."','".$secret."',1)"); 46 | $consumer = new Consumer($pdo->lastInsertId()); 47 | return $consumer; 48 | } 49 | 50 | public function isActive(){ 51 | return $this->active; 52 | } 53 | 54 | public function getKey(){ 55 | return $this->key; 56 | } 57 | 58 | public function getSecretKey(){ 59 | return $this->secret; 60 | } 61 | 62 | public function getId(){ 63 | return $this->id; 64 | } 65 | 66 | public function hasNonce($nonce,$timestamp){ 67 | $check = $this->pdo->query("select count(*) as cnt from consumer_nonce where timestamp = '".$timestamp."' and nonce = '".$nonce."' and consumer_id = ".$this->id)->fetch(); 68 | if($check['cnt']==1){ 69 | return true; 70 | } else { 71 | return false; 72 | } 73 | } 74 | 75 | public function addNonce($nonce){ 76 | $check = $this->pdo->exec("insert into consumer_nonce (consumer_id,timestamp,nonce) values (".$this->id.",".time().",'".$nonce."')"); 77 | } 78 | 79 | /* setters */ 80 | 81 | public function setKey($key){ 82 | $this->key = $key; 83 | } 84 | 85 | public function setSecret($secret){ 86 | $this->secret = $secret; 87 | } 88 | 89 | public function setActive($active){ 90 | $this->active = $active; 91 | } 92 | 93 | public function setId($id){ 94 | $this->id = $id; 95 | } 96 | 97 | } 98 | 99 | ?> 100 | -------------------------------------------------------------------------------- /class/Db.class.php: -------------------------------------------------------------------------------- 1 | pdoInstance = new PDO("mysql:host=localhost;dbname=oauthProvider","oauth","oauth"); 11 | $this->pdoInstance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 12 | $this->pdoInstance->exec("set names 'utf8'"); 13 | } 14 | 15 | private function __clone() {} 16 | 17 | public static function singleton() { 18 | 19 | if (!isset(self::$instance)) { 20 | $c = __CLASS__; 21 | self::$instance = new $c; 22 | } 23 | 24 | return self::$instance; 25 | 26 | } 27 | 28 | /* pdo functions */ 29 | 30 | public function quote($str){ 31 | return $this->pdoInstance->quote($str); 32 | } 33 | 34 | public function lastInsertId(){ 35 | return $this->pdoInstance->lastInsertId(); 36 | } 37 | 38 | public function query($str){ 39 | try { 40 | return $this->pdoInstance->query($str); 41 | } catch (PDOException $e) { 42 | echo "Error :
".$str."
". $e->getMessage() . "
".$e->getTraceAsString(); 43 | exit; 44 | } 45 | } 46 | 47 | public function exec($str){ 48 | try { 49 | return $this->pdoInstance->exec($str); 50 | } catch (PDOException $e) { 51 | echo "Error :
".$str."
". $e->getMessage() . "
".$e->getTraceAsString(); 52 | exit; 53 | } 54 | } 55 | 56 | } 57 | ?> 58 | -------------------------------------------------------------------------------- /class/Provider.class.php: -------------------------------------------------------------------------------- 1 | oauth = new OAuthProvider(); 21 | 22 | /* setup check functions */ 23 | $this->oauth->consumerHandler(array($this,'checkConsumer')); 24 | $this->oauth->timestampNonceHandler(array($this,'checkNonce')); 25 | $this->oauth->tokenHandler(array($this,'checkToken')); 26 | 27 | } 28 | 29 | /** 30 | * This function check the handlers that we added in the constructor 31 | * and then checks for a valid signature 32 | */ 33 | public function checkRequest(){ 34 | /* now that everything is setup we run the checks */ 35 | try{ 36 | $this->oauth->checkOAuthRequest(); 37 | } catch(OAuthException $E){ 38 | echo OAuthProvider::reportProblem($E); 39 | $this->oauth_error = true; 40 | } 41 | } 42 | 43 | /** 44 | * This function is called when you are requesting a request token 45 | * Basicly it disabled the tokenHandler check and force the oauth_callback parameter 46 | */ 47 | public function setRequestTokenQuery(){ 48 | $this->oauth->isRequestTokenEndpoint(true); 49 | $this->oauth->addRequiredParameter("oauth_callback"); 50 | } 51 | 52 | /** 53 | * This function generates a Request token 54 | * and save it in the db 55 | * then returns the oauth_token, oauth_token_secret & the authentification url 56 | * Please note that the authentification_url is not part of the oauth protocol but I added it to show you how to add extra parameters 57 | */ 58 | public function generateRequestToken(){ 59 | 60 | if($this->oauth_error){ 61 | return false; 62 | } 63 | 64 | $token = sha1(OAuthProvider::generateToken(20,true)); 65 | $token_secret = sha1(OAuthProvider::generateToken(20,true)); 66 | 67 | $callback = $this->oauth->callback; 68 | 69 | Token::createRequestToken($this->consumer, $token, $token_secret, $callback); 70 | 71 | return "authentification_url=".$this->authentification_url."&oauth_token=".$token."&oauth_token_secret=".$token_secret."&oauth_callback_confirmed=true"; 72 | 73 | } 74 | 75 | /** 76 | * This function generates a Access token saves it in the DB and return it 77 | * In that process it also removes the request token used to get that access token 78 | */ 79 | public function generateAccesstoken(){ 80 | 81 | if($this->oauth_error){ 82 | return false; 83 | } 84 | 85 | $access_token = sha1(OAuthProvider::generateToken(20,true)); 86 | $secret = sha1(OAuthProvider::generateToken(20,true)); 87 | 88 | $token = Token::findByToken($this->oauth->token); 89 | 90 | $token->changeToAccessToken($access_token,$secret); 91 | return "oauth_token=".$access_token."&oauth_token_secret=".$secret; 92 | } 93 | 94 | /** 95 | * This function generates a verifier and returns it 96 | */ 97 | public function generateVerifier(){ 98 | $verifier = sha1(OAuthProvider::generateToken(20,true)); 99 | return $verifier; 100 | } 101 | 102 | /* handlers */ 103 | 104 | /** 105 | * This function checks if the consumer exist in the DB and that it is active 106 | * You can modify it at your will but you __HAVE TO__ set $provider->consumer_secret to the right value or the signature will fail 107 | * It's called by OAuthCheckRequest() 108 | * @param $provider 109 | */ 110 | public function checkConsumer($provider){ 111 | $return = OAUTH_CONSUMER_KEY_UNKNOWN; 112 | 113 | $aConsumer = Consumer::findByKey($provider->consumer_key); 114 | 115 | if(is_object($aConsumer)){ 116 | if(!$aConsumer->isActive()){ 117 | $return = OAUTH_CONSUMER_KEY_REFUSED; 118 | } else { 119 | $this->consumer = $aConsumer; 120 | $provider->consumer_secret = $this->consumer->getSecretKey(); 121 | $return = OAUTH_OK; 122 | } 123 | } 124 | 125 | return $return; 126 | } 127 | 128 | /** 129 | * This function checks the token of the client 130 | * Fails if token not found, or verifier not correct 131 | * Once again you __HAVE TO__ set the $provider->token_secret to the right value or the signature will fail 132 | * It's called by OAuthCheckRequest() unless the client is getting a request token 133 | * @param unknown_type $provider 134 | */ 135 | public function checkToken($provider){ 136 | $token = Token::findByToken($provider->token); 137 | 138 | if(is_null($token)){ // token not found 139 | return OAUTH_TOKEN_REJECTED; 140 | } elseif($token->getType() == 1 && $token->getVerifier() != $provider->verifier){ // bad verifier for request token 141 | return OAUTH_VERIFIER_INVALID; 142 | } else { 143 | if($token->getType() == 2){ 144 | /* if this is an access token we register the user to the provider for use in our api */ 145 | $this->user = $token->getUser(); 146 | } 147 | $provider->token_secret = $token->getSecret(); 148 | return OAUTH_OK; 149 | } 150 | 151 | } 152 | 153 | /** 154 | * This function check both the timestamp & the nonce 155 | * The timestamp has to be less than 5 minutes ago (this is not oauth protocol so feel free to change that) 156 | * And the nonce has to be unknown for this consumer 157 | * Once everything is OK it saves the nonce in the db 158 | * It's called by OAuthCheckRequest() 159 | * @param $provider 160 | */ 161 | public function checkNonce($provider){ 162 | if($this->oauth->timestamp < time() - 5*60){ 163 | return OAUTH_BAD_TIMESTAMP; 164 | } elseif($this->consumer->hasNonce($provider->nonce,$this->oauth->timestamp)) { 165 | return OAUTH_BAD_NONCE; 166 | } else { 167 | $this->consumer->addNonce($this->oauth->nonce); 168 | return OAUTH_OK; 169 | } 170 | } 171 | 172 | public function getUser(){ 173 | if(is_object($this->user)){ 174 | return $this->user; 175 | } else { 176 | throw new Exception("User not authentificated"); 177 | } 178 | } 179 | 180 | } 181 | ?> 182 | -------------------------------------------------------------------------------- /class/Token.class.php: -------------------------------------------------------------------------------- 1 | exec("insert into token (type,consumer_id,token,token_secret,callback_url) values (1,".$consumer->getId().",'".$token."','".$tokensecret."','".$callback."') "); 20 | } 21 | 22 | public static function findByToken($token){ 23 | $ret = null; 24 | $pdo = Db::singleton(); 25 | $find = $pdo->query("select id from token where token = '".$token."'"); 26 | if($find->rowCount()==1){ 27 | $find = $find->fetch(); 28 | $request_token = new Token($find['id']); 29 | $ret = $request_token; 30 | } 31 | return $ret; 32 | } 33 | 34 | 35 | public function __construct($id=0){ 36 | $this->pdo = Db::singleton(); 37 | if($id != 0){ 38 | $this->id = $id; 39 | $this->load(); 40 | } 41 | } 42 | 43 | private function load(){ 44 | $info = $this->pdo->query("select * from token where id = ".$this->id)->fetch(); 45 | $this->token = $info['token']; 46 | $this->type = $info['type']; 47 | $this->token_secret = $info['token_secret']; 48 | $this->consumer = new Consumer($info['consumer_id']); 49 | $this->callback = $info['callback_url']; 50 | $this->verifier = $info['verifier']; 51 | if($info['user_id'] != 0){ 52 | $this->user = new User($info['user_id']); 53 | } else { 54 | $this->user = 0; 55 | } 56 | } 57 | 58 | public function changeToAccessToken($token,$secret){ 59 | if($this->isRequest()){ 60 | $this->pdo->exec("update token set type = 2, verifier = '', callback_url = '', token = '".$token."', token_secret = '".$secret."' where id = ".$this->id); 61 | return true; 62 | } else { 63 | return false; 64 | } 65 | } 66 | 67 | /* some setters */ 68 | 69 | public function setVerifier($verifier){ 70 | $this->pdo->exec("update token set verifier = '".$verifier."' where id = ".$this->id); 71 | $this->verifier = $verifier; 72 | } 73 | 74 | public function setUser(IUser $user){ 75 | $this->pdo->exec("update token set user_id = '".$user->getId()."' where id = ".$this->id); 76 | $this->user = $user; 77 | } 78 | 79 | /* some getters */ 80 | 81 | public function isRequest(){ 82 | return $this->type == 1; 83 | } 84 | 85 | public function isAccess(){ 86 | return !$this->isRequest(); 87 | } 88 | 89 | public function getCallback(){ 90 | return $this->callback; 91 | } 92 | 93 | public function getVerifier(){ 94 | return $this->verifier; 95 | } 96 | 97 | public function getType(){ 98 | return $this->type; 99 | } 100 | 101 | public function getSecret(){ 102 | return $this->token_secret; 103 | } 104 | 105 | public function getUser(){ 106 | return $this->user; 107 | } 108 | 109 | } 110 | ?> -------------------------------------------------------------------------------- /class/User.class.php: -------------------------------------------------------------------------------- 1 | query("select id from user where login = '".$login."'"); 14 | if($check->rowCount()==1){ 15 | $check = $check->fetch(); 16 | return new User($check['id']); 17 | } else { 18 | return null; 19 | } 20 | } 21 | 22 | public function __construct($id = 0){ 23 | $this->pdo = Db::singleton(); 24 | if($id != 0){ 25 | $this->id = $id; 26 | $this->load(); 27 | } 28 | } 29 | 30 | private function load(){ 31 | $info = $this->pdo->query("select * from user where id = ".$this->id)->fetch(); 32 | $this->login = $info['login']; 33 | } 34 | 35 | public function getId(){ 36 | return $this->id; 37 | } 38 | 39 | public function getLogin(){ 40 | return $this->login; 41 | } 42 | } -------------------------------------------------------------------------------- /client/apicall.php: -------------------------------------------------------------------------------- 1 | enableDebug(); 6 | $oauth_client->setToken($_POST['token'],$_POST['token_secret']); 7 | $oauth_client->fetch("http://localhost/OAuthProviderExample/oauth/api/user"); 8 | echo "API RESULT : ".$oauth_client->getLastResponse(); 9 | } catch (OAuthException $E){ 10 | echo $E->debugInfo; 11 | } 12 | } else { 13 | ?> 14 |
15 | Access token :
16 | Access token secret :
17 | 18 |
19 | -------------------------------------------------------------------------------- /client/callback.php: -------------------------------------------------------------------------------- 1 | enableDebug(); 7 | $oauth_client->setToken($_POST['oauth_token'],$_POST['oauth_token_secret']); 8 | $info = $oauth_client->getAccessToken("http://localhost/OAuthProviderExample/oauth/access_token",null,$_POST['oauth_verifier']); 9 | echo "

Congrats !

"; 10 | echo "AccessToken ".$info['oauth_token']."
"; 11 | echo "AccessToken Secret ".$info['oauth_token_secret']; 12 | echo "get your user id with an api call"; 13 | } catch(OAuthException $E){ 14 | echo print_r($E->debugInfo); 15 | } 16 | 17 | 18 | } else { 19 | ?> 20 |
21 | 22 |
23 | 24 | 25 | This is not passed by url, a real client would have stored this somewhere, you can get it from the db 26 |
27 | 28 | 29 | 30 |
31 | -------------------------------------------------------------------------------- /client/index.php: -------------------------------------------------------------------------------- 1 | enableDebug(); 4 | try { 5 | $info = $oauth_client->getRequestToken("http://localhost/OAuthProviderExample/oauth/request_token?oauth_callback=http://localhost/OAuthProviderExample/client/callback.php"); 6 | echo "

We have a request token !

"; 7 | echo "Request token : ".$info['oauth_token']."
"; 8 | echo "Request token secret : ".$info['oauth_token_secret']."
"; 9 | echo "to authenticate go here"; 10 | } catch(OAuthException $E){ 11 | echo "
".print_r($E->debugInfo,true)."
"; 12 | } 13 | ?> 14 | -------------------------------------------------------------------------------- /interfaces/IConsumer.php: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /interfaces/IToken.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /interfaces/IUser.php: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /oauth/.htaccess: -------------------------------------------------------------------------------- 1 | Options +FollowSymLinks 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteRule ^(.*)$ index.php [QSA,L] 5 | -------------------------------------------------------------------------------- /oauth/index.php: -------------------------------------------------------------------------------- 1 | setRequestTokenQuery(); 10 | $provider->checkRequest(); 11 | echo $provider->generateRequestToken(); 12 | } else if(strstr($_SERVER['REQUEST_URI'],"access_token")){ 13 | $provider->checkRequest(); 14 | echo $provider->generateAccessToken(); 15 | } else if(strstr($_SERVER['REQUEST_URI'],"create_consumer")){ 16 | $consumer = Provider::createConsumer(); 17 | ?> 18 |

New consumer

19 | Key : getKey()?>
20 | Secret : getSecretKey()?> 21 | checkRequest(); 25 | try { 26 | echo $provider->getUser()->getId(); 27 | } catch(Exception $E){ 28 | echo $E; 29 | } 30 | } 31 | 32 | ?> 33 | -------------------------------------------------------------------------------- /oauth/login.php: -------------------------------------------------------------------------------- 1 | isRequest()){ 10 | if(!isset($_POST['login'])){ 11 | ?> 12 |
13 |
14 | 15 |
16 | setVerifier(Provider::generateVerifier()); 21 | $request_token->setUser($user); 22 | header("location: ".$request_token->getCallback()."?&oauth_token=".$_REQUEST['oauth_token']."&oauth_verifier=".$request_token->getVerifier()); 23 | } else { 24 | echo "User not found !"; 25 | } 26 | } 27 | } else { 28 | echo "The specified token does not exist"; 29 | } 30 | } else { 31 | echo "Please specify a oauth_token"; 32 | } 33 | -------------------------------------------------------------------------------- /sql/schema.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 3.3.7deb3build0.10.10.1 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- Serveur: localhost 6 | -- Généré le : Mer 12 Janvier 2011 à 16:46 7 | -- Version du serveur: 5.1.49 8 | -- Version de PHP: 5.3.3-1ubuntu9.1 9 | 10 | SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 11 | 12 | -- 13 | -- Base de données: `oauthProvider` 14 | -- 15 | 16 | -- -------------------------------------------------------- 17 | 18 | -- 19 | -- Structure de la table `consumer` 20 | -- 21 | 22 | CREATE TABLE IF NOT EXISTS `consumer` ( 23 | `id` int(11) NOT NULL AUTO_INCREMENT, 24 | `consumer_key` varchar(255) NOT NULL, 25 | `consumer_secret` varchar(255) NOT NULL, 26 | `active` tinyint(1) NOT NULL, 27 | PRIMARY KEY (`id`) 28 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=18 ; 29 | 30 | -- 31 | -- Contenu de la table `consumer` 32 | -- 33 | 34 | INSERT INTO `consumer` (`id`, `consumer_key`, `consumer_secret`, `active`) VALUES 35 | (1, 'key', 'secret', 1); 36 | 37 | -- -------------------------------------------------------- 38 | 39 | -- 40 | -- Structure de la table `consumer_nonce` 41 | -- 42 | 43 | CREATE TABLE IF NOT EXISTS `consumer_nonce` ( 44 | `id` int(11) NOT NULL AUTO_INCREMENT, 45 | `consumer_id` int(11) NOT NULL, 46 | `timestamp` bigint(20) NOT NULL, 47 | `nonce` varchar(255) NOT NULL, 48 | PRIMARY KEY (`id`), 49 | KEY `consumer_id` (`consumer_id`) 50 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 51 | 52 | -- 53 | -- Contenu de la table `consumer_nonce` 54 | -- 55 | 56 | 57 | -- -------------------------------------------------------- 58 | 59 | -- 60 | -- Structure de la table `token` 61 | -- 62 | 63 | CREATE TABLE IF NOT EXISTS `token` ( 64 | `id` int(11) NOT NULL AUTO_INCREMENT, 65 | `type` int(11) NOT NULL, 66 | `consumer_id` int(11) NOT NULL, 67 | `user_id` int(11) NOT NULL, 68 | `token` varchar(255) NOT NULL, 69 | `token_secret` varchar(255) NOT NULL, 70 | `callback_url` text NOT NULL, 71 | `verifier` varchar(255) NOT NULL, 72 | PRIMARY KEY (`id`), 73 | KEY `consumer_id` (`consumer_id`), 74 | KEY `user_id` (`user_id`), 75 | KEY `type` (`type`) 76 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 77 | 78 | -- 79 | -- Contenu de la table `token` 80 | -- 81 | 82 | 83 | -- -------------------------------------------------------- 84 | 85 | -- 86 | -- Structure de la table `token_type` 87 | -- 88 | 89 | CREATE TABLE IF NOT EXISTS `token_type` ( 90 | `id` int(11) NOT NULL AUTO_INCREMENT, 91 | `type` varchar(50) NOT NULL, 92 | PRIMARY KEY (`id`) 93 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; 94 | 95 | -- 96 | -- Contenu de la table `token_type` 97 | -- 98 | 99 | INSERT INTO `token_type` (`id`, `type`) VALUES 100 | (1, 'request'), 101 | (2, 'access'); 102 | 103 | -- -------------------------------------------------------- 104 | 105 | -- 106 | -- Structure de la table `user` 107 | -- 108 | 109 | CREATE TABLE IF NOT EXISTS `user` ( 110 | `id` int(11) NOT NULL AUTO_INCREMENT, 111 | `login` varchar(20) NOT NULL, 112 | PRIMARY KEY (`id`) 113 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; 114 | 115 | -- 116 | -- Contenu de la table `user` 117 | -- 118 | 119 | INSERT INTO `user` (`id`, `login`) VALUES 120 | (1, 'test'); 121 | 122 | -- 123 | -- Contraintes pour les tables exportées 124 | -- 125 | 126 | -- 127 | -- Contraintes pour la table `consumer_nonce` 128 | -- 129 | ALTER TABLE `consumer_nonce` 130 | ADD CONSTRAINT `consumer_nonce_ibfk_1` FOREIGN KEY (`consumer_id`) REFERENCES `consumer` (`id`) ON DELETE CASCADE; 131 | 132 | -- 133 | -- Contraintes pour la table `token` 134 | -- 135 | ALTER TABLE `token` 136 | ADD CONSTRAINT `token_ibfk_2` FOREIGN KEY (`type`) REFERENCES `token_type` (`id`), 137 | ADD CONSTRAINT `token_ibfk_1` FOREIGN KEY (`consumer_id`) REFERENCES `consumer` (`id`) ON DELETE CASCADE; 138 | --------------------------------------------------------------------------------