use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Security\OAuth1\OAuthServer;
-use Friendica\Security\OAuth1\OAuthSignatureMethod_HMAC_SHA1;
-use Friendica\Security\OAuth1\OAuthSignatureMethod_PLAINTEXT;
+use Friendica\Security\OAuth1\Signature\OAuthSignatureMethod_HMAC_SHA1;
+use Friendica\Security\OAuth1\Signature\OAuthSignatureMethod_PLAINTEXT;
/**
* OAuth protocol
namespace Friendica\Security\OAuth1;
-use Friendica;
-use Friendica\Security\OAuth1\OAuthUtil;
+use Friendica\Util\Strings;
class OAuthRequest
{
/**
* pretty much a helper function to set up the request
*
- * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
- * @param \Friendica\Security\OAuth1\OAuthToken $token
- * @param string $http_method
- * @param string $http_url
- * @param array|null $parameters
+ * @param OAuthConsumer $consumer
+ * @param OAuthToken $token
+ * @param string $http_method
+ * @param string $http_url
+ * @param array|null $parameters
*
* @return OAuthRequest
*/
- public static function from_consumer_and_token(\Friendica\Security\OAuth1\OAuthConsumer $consumer, $http_method, $http_url, array $parameters = null, \Friendica\Security\OAuth1\OAuthToken $token = null)
+ public static function from_consumer_and_token(OAuthConsumer $consumer, $http_method, $http_url, array $parameters = null, OAuthToken $token = null)
{
@$parameters or $parameters = [];
$defaults = [
* @param string|null $realm
*
* @return string
- * @throws \Friendica\Security\OAuth1\OAuthException
+ * @throws OAuthException
*/
public function to_header($realm = null)
{
foreach ($this->parameters as $k => $v) {
if (substr($k, 0, 5) != "oauth") continue;
if (is_array($v)) {
- throw new \Friendica\Security\OAuth1\OAuthException('Arrays not supported in headers');
+ throw new OAuthException('Arrays not supported in headers');
}
$out .= ($first) ? ' ' : ',';
$out .= OAuthUtil::urlencode_rfc3986($k) .
}
- public function sign_request(\Friendica\Security\OAuth1\OAuthSignatureMethod $signature_method, $consumer, $token)
+ public function sign_request(Signature\OAuthSignatureMethod $signature_method, $consumer, $token)
{
$this->set_parameter(
"oauth_signature_method",
$this->set_parameter("oauth_signature", $signature, false);
}
- public function build_signature(\Friendica\Security\OAuth1\OAuthSignatureMethod $signature_method, $consumer, $token)
+ public function build_signature(Signature\OAuthSignatureMethod $signature_method, $consumer, $token)
{
$signature = $signature_method->build_signature($this, $consumer, $token);
return $signature;
*/
private static function generate_nonce()
{
- return Friendica\Util\Strings::getRandomHex(32);
+ return Strings::getRandomHex(32);
}
-}
\ No newline at end of file
+}
namespace Friendica\Security\OAuth1;
use Friendica\Security\FKOAuthDataStore;
-use OAuthConsumer;
-use OAuthRequest;
-use OAuthSignatureMethod;
-use OAuthToken;
+use Friendica\Security\OAuth1\Signature;
class OAuthServer
{
protected $timestamp_threshold = 300; // in seconds, five minutes
protected $version = '1.0'; // hi blaine
- /** @var \Friendica\Security\OAuth1\OAuthSignatureMethod[] */
+ /** @var Signature\OAuthSignatureMethod[] */
protected $signature_methods = [];
/** @var FKOAuthDataStore */
$this->data_store = $data_store;
}
- public function add_signature_method(\Friendica\Security\OAuth1\OAuthSignatureMethod $signature_method)
+ public function add_signature_method(Signature\OAuthSignatureMethod $signature_method)
{
$this->signature_methods[$signature_method->get_name()] =
$signature_method;
* process a request_token request
* returns the request token on success
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
+ * @param OAuthRequest $request
*
- * @return \Friendica\Security\OAuth1\OAuthToken|null
+ * @return OAuthToken|null
* @throws OAuthException
*/
- public function fetch_request_token(\Friendica\Security\OAuth1\OAuthRequest $request)
+ public function fetch_request_token(OAuthRequest $request)
{
$this->get_version($request);
* process an access_token request
* returns the access token on success
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
+ * @param OAuthRequest $request
*
* @return object
* @throws OAuthException
*/
- public function fetch_access_token(\Friendica\Security\OAuth1\OAuthRequest $request)
+ public function fetch_access_token(OAuthRequest $request)
{
$this->get_version($request);
/**
* verify an api call, checks all the parameters
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
+ * @param OAuthRequest $request
*
* @return array
* @throws OAuthException
*/
- public function verify_request(\Friendica\Security\OAuth1\OAuthRequest $request)
+ public function verify_request(OAuthRequest $request)
{
$this->get_version($request);
$consumer = $this->get_consumer($request);
/**
* version 1
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
+ * @param OAuthRequest $request
*
* @return string
* @throws OAuthException
*/
- private function get_version(\Friendica\Security\OAuth1\OAuthRequest $request)
+ private function get_version(OAuthRequest $request)
{
$version = $request->get_parameter("oauth_version");
if (!$version) {
/**
* figure out the signature with some defaults
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
+ * @param OAuthRequest $request
*
- * @return \Friendica\Security\OAuth1\OAuthSignatureMethod
+ * @return Signature\OAuthSignatureMethod
* @throws OAuthException
*/
- private function get_signature_method(\Friendica\Security\OAuth1\OAuthRequest $request)
+ private function get_signature_method(OAuthRequest $request)
{
$signature_method =
@$request->get_parameter("oauth_signature_method");
/**
* try to find the consumer for the provided request's consumer key
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
+ * @param OAuthRequest $request
*
- * @return \Friendica\Security\OAuth1\OAuthConsumer
+ * @return OAuthConsumer
* @throws OAuthException
*/
- private function get_consumer(\Friendica\Security\OAuth1\OAuthRequest $request)
+ private function get_consumer(OAuthRequest $request)
{
$consumer_key = @$request->get_parameter("oauth_consumer_key");
if (!$consumer_key) {
/**
* try to find the token for the provided request's token key
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
+ * @param OAuthRequest $request
* @param $consumer
* @param string $token_type
*
- * @return \Friendica\Security\OAuth1\OAuthToken|null
+ * @return OAuthToken|null
* @throws OAuthException
*/
- private function get_token(\Friendica\Security\OAuth1\OAuthRequest &$request, $consumer, $token_type = "access")
+ private function get_token(OAuthRequest &$request, $consumer, $token_type = "access")
{
$token_field = @$request->get_parameter('oauth_token');
$token = $this->data_store->lookup_token(
* all-in-one function to check the signature on a request
* should guess the signature method appropriately
*
- * @param \Friendica\Security\OAuth1\OAuthRequest $request
- * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
- * @param \Friendica\Security\OAuth1\OAuthToken|null $token
+ * @param OAuthRequest $request
+ * @param OAuthConsumer $consumer
+ * @param OAuthToken|null $token
*
* @throws OAuthException
*/
- private function check_signature(\Friendica\Security\OAuth1\OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+ private function check_signature(OAuthRequest $request, OAuthConsumer $consumer, OAuthToken $token = null)
{
// this should probably be in a different method
$timestamp = @$request->get_parameter('oauth_timestamp');
/**
* check that the nonce is not repeated
*
- * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
- * @param \Friendica\Security\OAuth1\OAuthToken $token
- * @param string $nonce
- * @param int $timestamp
+ * @param OAuthConsumer $consumer
+ * @param OAuthToken $token
+ * @param string $nonce
+ * @param int $timestamp
*
* @throws OAuthException
*/
- private function check_nonce(\Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token, $nonce, int $timestamp)
+ private function check_nonce(OAuthConsumer $consumer, OAuthToken $token, $nonce, int $timestamp)
{
if (!$nonce)
throw new OAuthException(
+++ /dev/null
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-
-/**
- * A class for implementing a Signature Method
- * See section 9 ("Signing Requests") in the spec
- */
-abstract class OAuthSignatureMethod
-{
- /**
- * Needs to return the name of the Signature Method (ie HMAC-SHA1)
- *
- * @return string
- */
- abstract public function get_name();
-
- /**
- * Build up the signature
- * NOTE: The output of this function MUST NOT be urlencoded.
- * the encoding is handled in OAuthRequest when the final
- * request is serialized
- *
- * @param OAuthRequest $request
- * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
- * @param \Friendica\Security\OAuth1\OAuthToken $token
- *
- * @return string
- */
- abstract public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null);
-
- /**
- * Verifies that a given signature is correct
- *
- * @param OAuthRequest $request
- * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
- * @param \Friendica\Security\OAuth1\OAuthToken $token
- * @param string $signature
- *
- * @return bool
- */
- public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
- {
- $built = $this->build_signature($request, $consumer, $token);
- return ($built == $signature);
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-use Friendica\Security\OAuth1\OAuthUtil;
-
-/**
- * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
- * where the Signature Base String is the text and the key is the concatenated values (each first
- * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
- * character (ASCII code 38) even if empty.
- * - Chapter 9.2 ("HMAC-SHA1")
- */
-class OAuthSignatureMethod_HMAC_SHA1 extends \Friendica\Security\OAuth1\OAuthSignatureMethod
-{
- function get_name()
- {
- return "HMAC-SHA1";
- }
-
- /**
- * @param OAuthRequest $request
- * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
- * @param \Friendica\Security\OAuth1\OAuthToken $token
- *
- * @return string
- */
- public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
- {
- $base_string = $request->get_signature_base_string();
- $request->base_string = $base_string;
-
- $key_parts = [
- $consumer->secret,
- ($token) ? $token->secret : "",
- ];
-
- $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
- $key = implode('&', $key_parts);
-
-
- $r = base64_encode(hash_hmac('sha1', $base_string, $key, true));
- return $r;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-use Friendica\Security\OAuth1\OAuthUtil;
-
-/**
- * The PLAINTEXT method does not provide any security protection and SHOULD only be used
- * over a secure channel such as HTTPS. It does not use the Signature Base String.
- * - Chapter 9.4 ("PLAINTEXT")
- */
-class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod
-{
- public function get_name()
- {
- return "PLAINTEXT";
- }
-
- /**
- * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
- * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
- * empty. The result MUST be encoded again.
- * - Chapter 9.4.1 ("Generating Signatures")
- *
- * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
- * OAuthRequest handles this!
- *
- * @param $request
- * @param $consumer
- * @param $token
- *
- * @return string
- */
- public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
- {
- $key_parts = [
- $consumer->secret,
- ($token) ? $token->secret : "",
- ];
-
- $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
- $key = implode('&', $key_parts);
- $request->base_string = $key;
-
- return $key;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\OAuth1\OAuthRequest;
-
-/**
- * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
- * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
- * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
- * verified way to the Service Provider, in a manner which is beyond the scope of this
- * specification.
- * - Chapter 9.3 ("RSA-SHA1")
- */
-abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod
-{
- public function get_name()
- {
- return "RSA-SHA1";
- }
-
- // Up to the SP to implement this lookup of keys. Possible ideas are:
- // (1) do a lookup in a table of trusted certs keyed off of consumer
- // (2) fetch via http using a url provided by the requester
- // (3) some sort of specific discovery code based on request
- //
- // Either way should return a string representation of the certificate
- protected abstract function fetch_public_cert(&$request);
-
- // Up to the SP to implement this lookup of keys. Possible ideas are:
- // (1) do a lookup in a table of trusted certs keyed off of consumer
- //
- // Either way should return a string representation of the certificate
- protected abstract function fetch_private_cert(&$request);
-
- public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
- {
- $base_string = $request->get_signature_base_string();
- $request->base_string = $base_string;
-
- // Fetch the private key cert based on the request
- $cert = $this->fetch_private_cert($request);
-
- // Pull the private key ID from the certificate
- $privatekeyid = openssl_get_privatekey($cert);
-
- // Sign using the key
- openssl_sign($base_string, $signature, $privatekeyid);
-
- // Release the key resource
- openssl_free_key($privatekeyid);
-
- return base64_encode($signature);
- }
-
- public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
- {
- $decoded_sig = base64_decode($signature);
-
- $base_string = $request->get_signature_base_string();
-
- // Fetch the public key cert based on the request
- $cert = $this->fetch_public_cert($request);
-
- // Pull the public key ID from the certificate
- $publickeyid = openssl_get_publickey($cert);
-
- // Check the computed signature against the one passed in the query
- $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
-
- // Release the key resource
- openssl_free_key($publickeyid);
-
- return $ok == 1;
- }
-}
namespace Friendica\Security\OAuth1;
-use Friendica\Security\OAuth1\OAuthUtil;
-
class OAuthToken
{
// access tokens and request tokens
--- /dev/null
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+
+/**
+ * A class for implementing a Signature Method
+ * See section 9 ("Signing Requests") in the spec
+ */
+abstract class OAuthSignatureMethod
+{
+ /**
+ * Needs to return the name of the Signature Method (ie HMAC-SHA1)
+ *
+ * @return string
+ */
+ abstract public function get_name();
+
+ /**
+ * Build up the signature
+ * NOTE: The output of this function MUST NOT be urlencoded.
+ * the encoding is handled in OAuthRequest when the final
+ * request is serialized
+ *
+ * @param OAuthRequest $request
+ * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
+ * @param \Friendica\Security\OAuth1\OAuthToken $token
+ *
+ * @return string
+ */
+ abstract public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null);
+
+ /**
+ * Verifies that a given signature is correct
+ *
+ * @param OAuthRequest $request
+ * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
+ * @param \Friendica\Security\OAuth1\OAuthToken $token
+ * @param string $signature
+ *
+ * @return bool
+ */
+ public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
+ {
+ $built = $this->build_signature($request, $consumer, $token);
+ return ($built == $signature);
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+use Friendica\Security\OAuth1\OAuthUtil;
+
+/**
+ * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
+ * where the Signature Base String is the text and the key is the concatenated values (each first
+ * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
+ * character (ASCII code 38) even if empty.
+ * - Chapter 9.2 ("HMAC-SHA1")
+ */
+class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod
+{
+ function get_name()
+ {
+ return "HMAC-SHA1";
+ }
+
+ /**
+ * @param OAuthRequest $request
+ * @param \Friendica\Security\OAuth1\OAuthConsumer $consumer
+ * @param \Friendica\Security\OAuth1\OAuthToken $token
+ *
+ * @return string
+ */
+ public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+ {
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+
+ $key_parts = [
+ $consumer->secret,
+ ($token) ? $token->secret : "",
+ ];
+
+ $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
+ $key = implode('&', $key_parts);
+
+
+ $r = base64_encode(hash_hmac('sha1', $base_string, $key, true));
+ return $r;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+use Friendica\Security\OAuth1\OAuthUtil;
+
+/**
+ * The PLAINTEXT method does not provide any security protection and SHOULD only be used
+ * over a secure channel such as HTTPS. It does not use the Signature Base String.
+ * - Chapter 9.4 ("PLAINTEXT")
+ */
+class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod
+{
+ public function get_name()
+ {
+ return "PLAINTEXT";
+ }
+
+ /**
+ * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
+ * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
+ * empty. The result MUST be encoded again.
+ * - Chapter 9.4.1 ("Generating Signatures")
+ *
+ * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
+ * OAuthRequest handles this!
+ *
+ * @param $request
+ * @param $consumer
+ * @param $token
+ *
+ * @return string
+ */
+ public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+ {
+ $key_parts = [
+ $consumer->secret,
+ ($token) ? $token->secret : "",
+ ];
+
+ $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
+ $key = implode('&', $key_parts);
+ $request->base_string = $key;
+
+ return $key;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Security\OAuth1\Signature;
+
+use Friendica\Security\OAuth1\OAuthRequest;
+
+/**
+ * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
+ * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
+ * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
+ * verified way to the Service Provider, in a manner which is beyond the scope of this
+ * specification.
+ * - Chapter 9.3 ("RSA-SHA1")
+ */
+abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod
+{
+ public function get_name()
+ {
+ return "RSA-SHA1";
+ }
+
+ // Up to the SP to implement this lookup of keys. Possible ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ // (2) fetch via http using a url provided by the requester
+ // (3) some sort of specific discovery code based on request
+ //
+ // Either way should return a string representation of the certificate
+ protected abstract function fetch_public_cert(&$request);
+
+ // Up to the SP to implement this lookup of keys. Possible ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ //
+ // Either way should return a string representation of the certificate
+ protected abstract function fetch_private_cert(&$request);
+
+ public function build_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, \Friendica\Security\OAuth1\OAuthToken $token = null)
+ {
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+
+ // Fetch the private key cert based on the request
+ $cert = $this->fetch_private_cert($request);
+
+ // Pull the private key ID from the certificate
+ $privatekeyid = openssl_get_privatekey($cert);
+
+ // Sign using the key
+ openssl_sign($base_string, $signature, $privatekeyid);
+
+ // Release the key resource
+ openssl_free_key($privatekeyid);
+
+ return base64_encode($signature);
+ }
+
+ public function check_signature(OAuthRequest $request, \Friendica\Security\OAuth1\OAuthConsumer $consumer, $signature, \Friendica\Security\OAuth1\OAuthToken $token = null)
+ {
+ $decoded_sig = base64_decode($signature);
+
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the public key cert based on the request
+ $cert = $this->fetch_public_cert($request);
+
+ // Pull the public key ID from the certificate
+ $publickeyid = openssl_get_publickey($cert);
+
+ // Check the computed signature against the one passed in the query
+ $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
+
+ // Release the key resource
+ openssl_free_key($publickeyid);
+
+ return $ok == 1;
+ }
+}