diff --git a/js/README.md b/js/README.md new file mode 100644 index 0000000..787ee52 --- /dev/null +++ b/js/README.md @@ -0,0 +1,56 @@ +#OAuthSimple for Javascript + +## A Word of Caution: +It might be useful to understand what OAuth is. OAuth is a way for two +(or more) parties to confirm the fact that they are who they say they +are. This is done by a set of secret handshakes that only both sides +know. + +In short, the very first thing that happens is that both sides +exchange some secret value. This exchange happens outside of OAuth and +the secret is NEVER displayed to anyone other than the two parties. + +This... gets a bit tricky when you're talking about javascript. + +The example code in index.html doesn't even try to hide the secret, +and frankly, it's considerably difficult to do that even in the best +of situations because users can stop and examine code with most recent +browsers. + +So, while your secret may be disclosed, in a properly functioning +system, the user's data is only disclosed after the user concents to +it. + +If you're building this for your own use on a device you control where +your code can't be inspected by malicious parties. Go for it. +Otherwise, you probably want to do the OAuth exchange on the server +and pass back the final access token to the javascript app. (See the +OAuth documentation for whatever site you're working with for details +about that.) + +## Webcalls without a Web + +There are lots of environments that let you run javascript outside of +a browser. I'm not going to detail all of them (because there are a +lot of them), but I'll note that OAuth was designed around using HTTP +as the transport mechanism. + +Fortunately, that doesn't mean that you have to fire up your browser +of choice in order to make these calls. You do need to have something +that talks HTTP, however. Again, there are lots of choices, for +instance libcURL is available for darn near everything out there. +There are also plenty of systems that provide native calls. + +For the most part, these calls will either want the arguments in-line +with the call (use ```OAuthSimple().sign(...).signed_url;```), as a +request header ( ```OAuthSimple().sign(...).header```), or as the POST +request body (you may want to use _normalizedParameters() for that, +but understand that it's not a public function and is subject to +change.) Again, see the documentation for the service you wish to +connect to for how best to provide this info. + +## How to use it. + +Honestly? Read the source. I commented the heck out of it and there's +example code inside there. Plus, unlike this, it is more likely to be +documented and included with the distribution. diff --git a/php/OAuthSimple.php b/php/OAuthSimple.php index 24b7b61..0790609 100644 --- a/php/OAuthSimple.php +++ b/php/OAuthSimple.php @@ -1,9 +1,9 @@ * @copyright unitedHeroes.net 2011 * @version 1.3 @@ -17,7 +17,7 @@ class OAuthSimple { private $_action; private $_nonce_chars; - /** + /** * Constructor * * @access public @@ -26,47 +26,47 @@ class OAuthSimple { * @return OAuthSimple (Object) */ function __construct ($APIKey = "", $sharedSecret=""){ - + if (!empty($APIKey)) { $this->_secrets['consumer_key'] = $APIKey; } - + if (!empty($sharedSecret)) { $this->_secrets['shared_secret'] = $sharedSecret; } - + $this->_default_signature_method = "HMAC-SHA1"; $this->_action = "GET"; $this->_nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - + return $this; } - - /** - * Reset the parameters and URL - * + + /** + * Reset the parameters and URL + * * @access public * @return OAuthSimple (Object) - */ + */ public function reset() { $this->_parameters = Array(); $this->path = NULL; $this->sbs = NULL; - - return $this; + + return $this; } - /** - * Set the parameters either from a hash or a string - * + /** + * Set the parameters either from a hash or a string + * * @access public * @param(string, object) List of parameters for the call, this can either be a URI string (e.g. "foo=bar&gorp=banana" or an object/hash) * @return OAuthSimple (Object) - */ + */ public function setParameters ($parameters=Array()) { - + if (is_string($parameters)) { $parameters = $this->_parseParameterString($parameters); @@ -103,24 +103,24 @@ class OAuthSimple { { $this->_parameters['oauth_version']="1.0"; } - + return $this; } - /** + /** * Convenience method for setParameters - * + * * @access public * @see setParameters - */ - public function setQueryString ($parameters) + */ + public function setQueryString ($parameters) { return $this->setParameters($parameters); } - /** + /** * Set the target URL (does not include the parameters) - * + * * @param path (String) the fully qualified URI (excluding query arguments) (e.g "http://example.org/foo") * @return OAuthSimple (Object) */ @@ -131,28 +131,28 @@ class OAuthSimple { throw new OAuthSimpleException('No path specified for OAuthSimple.setURL'); } $this->_path=$path; - + return $this; } - /** + /** * Convenience method for setURL * - * @param path (String) + * @param path (String) * @see setURL */ - public function setPath ($path) + public function setPath ($path) { return $this->_path=$path; } - /** + /** * Set the "action" for the url, (e.g. GET,POST, DELETE, etc.) * * @param action (String) HTTP Action word. * @return OAuthSimple (Object) */ - public function setAction ($action) + public function setAction ($action) { if (empty($action)) { @@ -164,17 +164,17 @@ class OAuthSimple { throw new OAuthSimpleException('Invalid action specified for OAuthSimple.setAction'); } $this->_action = $action; - + return $this; } - /** + /** * Set the signatures (as well as validate the ones you have) * * @param signatures (object) object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:} * @return OAuthSimple (Object) */ - public function signatures ($signatures) + public function signatures ($signatures) { if (!empty($signatures) && !is_array($signatures)) { @@ -182,7 +182,7 @@ class OAuthSimple { } if (!empty($signatures)) { - if (empty($this->_secrets)) + if (empty($this->_secrets)) { $this->_secrets=Array(); } @@ -216,16 +216,16 @@ class OAuthSimple { { throw new OAuthSimpleException('Missing oauth_secret for supplied oauth_token in OAuthSimple.signatures'); } - + return $this; } - public function setTokensAndSecrets($signatures) + public function setTokensAndSecrets($signatures) { return $this->signatures($signatures); } - /** + /** * Set the signature method (currently only Plaintext or SHA-MAC1) * * @param method (String) Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now) @@ -248,7 +248,7 @@ class OAuthSimple { throw new OAuthSimpleException ("Unknown signing method $method specified for OAuthSimple.setSignatureMethod"); break; } - + return $this; } @@ -259,8 +259,8 @@ class OAuthSimple { * * @param args (Array) hash of arguments for the call {action, path, parameters (array), method, signatures (array)} all arguments are optional. * @return (Array) signed values - */ - public function sign($args=array()) + */ + public function sign($args=array()) { if (!empty($args['action'])) { @@ -280,12 +280,12 @@ class OAuthSimple { } if (empty($args['parameters'])) { - $args['parameters']=array(); + $args['parameters']=array(); } $this->setParameters($args['parameters']); $normParams = $this->_normalizedParameters(); $this->_parameters['oauth_signature'] = $this->_generateSignature($normParams); - + return Array ( 'parameters' => $this->_parameters, 'signature' => self::_oauthEscape($this->_parameters['oauth_signature']), @@ -295,7 +295,7 @@ class OAuthSimple { ); } - /** + /** * Return a formatted "header" string * * NOTE: This doesn't set the "Authorization: " prefix, which is required. @@ -303,9 +303,9 @@ class OAuthSimple { * ways to do that. * * @param args (Array) - * @return $result (String) + * @return $result (String) */ - public function getHeaderString ($args=array()) + public function getHeaderString ($args=array()) { if (empty($this->_parameters['oauth_signature'])) { @@ -335,7 +335,7 @@ class OAuthSimple { return preg_replace('/, $/','',$result); } - private function _parseParameterString ($paramString) + private function _parseParameterString ($paramString) { $elements = explode('&',$paramString); $result = array(); @@ -364,7 +364,7 @@ class OAuthSimple { } - private static function _oauthEscape($string) + private static function _oauthEscape($string) { if ($string === 0) { return 0; } if ($string == '0') { return '0'; } @@ -372,21 +372,18 @@ class OAuthSimple { if (is_array($string)) { throw new OAuthSimpleException('Array passed to _oauthEscape'); } - $string = rawurlencode($string); + $string = urlencode($string); - //FIX: rawurlencode of ~ - $string = str_replace('%7E','~', $string); - $string = str_replace('+','%20',$string); - $string = str_replace('!','%21',$string); - $string = str_replace('*','%2A',$string); - $string = str_replace('\'','%27',$string); - $string = str_replace('(','%28',$string); - $string = str_replace(')','%29',$string); + //FIX: urlencode of ~ and '+' + $string = str_replace( + Array('%7E','+' ), // Replace these + Array('~', '%20'), // with these + $string); return $string; } - private function _getNonce($length=5) + private function _getNonce($length=5) { $result = ''; $cLength = strlen($this->_nonce_chars); @@ -396,22 +393,22 @@ class OAuthSimple { $result .= substr($this->_nonce_chars,$rnum,1); } $this->_parameters['oauth_nonce'] = $result; - + return $result; } - private function _getApiKey() + private function _getApiKey() { if (empty($this->_secrets['consumer_key'])) { throw new OAuthSimpleException('No consumer_key set for OAuthSimple'); } $this->_parameters['oauth_consumer_key']=$this->_secrets['consumer_key']; - + return $this->_parameters['oauth_consumer_key']; } - private function _getAccessToken() + private function _getAccessToken() { if (!isset($this->_secrets['oauth_secret'])) { @@ -422,16 +419,16 @@ class OAuthSimple { throw new OAuthSimpleException('No access token (oauth_token) set for OAuthSimple.'); } $this->_parameters['oauth_token'] = $this->_secrets['oauth_token']; - + return $this->_parameters['oauth_token']; } - private function _getTimeStamp() + private function _getTimeStamp() { return $this->_parameters['oauth_timestamp'] = time(); } - private function _normalizedParameters() + private function _normalizedParameters() { $normalized_keys = array(); $return_array = array(); @@ -439,52 +436,52 @@ class OAuthSimple { foreach ( $this->_parameters as $paramName=>$paramValue) { if (!preg_match('/\w+_secret/',$paramName) OR (strpos($paramValue, '@') !== 0 && !file_exists(substr($paramValue, 1))) ) { - if (is_array($paramValue)) + if (is_array($paramValue)) { $normalized_keys[self::_oauthEscape($paramName)] = array(); - foreach($paramValue as $item) + foreach($paramValue as $item) { array_push($normalized_keys[self::_oauthEscape($paramName)], self::_oauthEscape($item)); } } - else + else { - $normalized_keys[self::_oauthEscape($paramName)] = self::_oauthEscape($paramValue); + $normalized_keys[self::_oauthEscape($paramName)] = self::_oauthEscape($paramValue); } } } - + ksort($normalized_keys); - - foreach($normalized_keys as $key=>$val) + + foreach($normalized_keys as $key=>$val) { - if (is_array($val)) + if (is_array($val)) { sort($val); - foreach($val as $element) + foreach($val as $element) { array_push($return_array, $key . "=" . $element); } } - else + else { array_push($return_array, $key .'='. $val); } - + } - + return join("&", $return_array); } - private function _generateSignature ($parameters="") + private function _generateSignature ($parameters="") { $secretKey = ''; if(isset($this->_secrets['shared_secret'])) { $secretKey = self::_oauthEscape($this->_secrets['shared_secret']); } - + $secretKey .= '&'; if(isset($this->_secrets['oauth_secret'])) { @@ -509,8 +506,8 @@ class OAuthSimple { } class OAuthSimpleException extends Exception { - - public function __construct($err, $isDebug = FALSE) + + public function __construct($err, $isDebug = FALSE) { self::log_error($err); if ($isDebug) @@ -518,12 +515,12 @@ class OAuthSimpleException extends Exception { self::display_error($err, TRUE); } } - + public static function log_error($err) { - error_log($err, 0); + error_log($err, 0); } - + public static function display_error($err, $kill = FALSE) { print_r($err);