Yammer not accepting OAuth token token through header during post - post

I am currently trying to upgrade my application to send an OAuth token through as a header instead of through the query string as per their new requirements. When making a GET request with the OAuth token in the header, my request succeeds verifying a valid access_token. However when trying to make a post with the same token, I receive a 401 unauthorized. This post with the same access token succeeds when the access token is placed on the query string.
var request = (HttpWebRequest)WebRequest.Create(yammerurl);
request.Method = "POST";
request.Headers["Authorization"] = "Bearer " + access_token;
request.Host = "www.yammer.com";
request.ContentType = "application/json;charset=utf-8";
This is my set up for posting that is receiving an unauthorized exception and below is my set up for the GET request that succeeds. Again both of them are using the same access token and both methods work when the access token is passed through the query string.
string url = "https://www.yammer.com/api/v1/groups.json?mine=1";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Headers["Authorization"] = "Bearer " + YammerAccessToken;
request.Host = "www.yammer.com";
Does anybody know if my setup for posting is incorrect or if there is another parameter I need to add?

Is it because you are not specifying the HTTP verb GET in the second one? This is how I accomplish it in PHP and it works fine...
I call this in my main php file...
$ymuser = yammer_user_by_email('myemail#test.com');
this function is in my inc file...
function yammer_user_by_email($email, $token = null){
global $YAMMER_ADMIN_TOKEN;
$user = yammer_api_get('https://www.yammer.com/api/v1/users/by_email.json?email='.$email, $YAMMER_ADMIN_TOKEN);
return $user[0];
}
All of my http calls are routed through here, and the admin token is applied to the header...
function yammer_api_call($url, $method = 'GET', $body = '', $token){
if ($token == null) {
if (!$_SESSION['yammer_token'] || !$_SESSION['yammer_token']->access_token->token) return false;
$token = $_SESSION['yammer_token']->access_token->token;
}
if ($method == 'GET'){
$opts = array('http' =>
array(
'method' => $method,
'header' => "Host: www.yammer.com\r\n"
."Authorization: Bearer " . $token . "\r\n"
)
);
}else{
$opts = array('http' =>
array(
'method' => $method,
'header' => "Content-Type: application/x-www-form-urlencoded\r\n"
."Host: www.yammer.com\r\n"
."Authorization: Bearer " . $token . "\r\n"
."Content-Length: " . strlen($body) . "\r\n",
'content' => $body,
'timeout' => 60
)
);
}
$context = stream_context_create($opts);
$resp = file_get_contents($url, false, $context);
//print($resp);
$resp_obj = json_decode($resp);
return $resp_obj;
}

Related

I want to send the proper parameter to salesforce for authentication with JWT on Ruby

I am currently working on the project that I am going to integrate the application of my company and salesforce.
In my case, it seemed that using the JWT for authentication is better. So, I wanted to try it.
but I don't know how to generate JWT and send the proper request to salesforce on Ruby though I read docs.
What I wanted to do is that
1, create application on salesforce (done)
2, create X509 certification and set it on the application on salesforce. (done)
3, create JWT by using the secret key of X509 certification. (I think I've done it )
4, send post request with JWT parameter included in assertion params and grant_type(grant_type= urn:ietf:params:oauth:grant-type:jwt-bearer&) (I got an error)
when I send post request the errors says {"error":"invalid_grant","error_description":"invalid assertion"} so it occurs certainly because of the parameter I sent.
the code I randomly wrote is something like this.
require 'jwt'
require 'json'
require 'net/http'
require 'uri'
payload = {
"sub": "abel#example.com", ← my account on salesforce
"iss": "3MVG9pe2TCoA1PasbdvjabsodyoQFZTn0Rjsdbfjbasojdbn;oajs", ← the consumer key of the application on salesforce.
"aud": "https://test.salesforce.com"
}
public_key = Base64.urlsafe_encode64(
'USqTxNC7MMIeF9iegop3WeDvFL
075JSUECgYEA76FNJLeStdq+J6Fj2ZBYdDoeuDHv3iNA0nnIse9d6HnjbdrdvjmV
rT1CJuHh9gnNKg4tyjkbpc9IVj4/GF0mNUCgYEAynvj
qOYCzts4W7Bdumk6z8QULJ5QoYCrAgFtwra9R1HDcxTz+GPgJOVx2QBX+aQbDOaD
WV1s9WqE0/Lfi/VVUEzg1hZ8326buGRk1DRVG2Oa48==') ← this is public_key example of the certification.
rsa_private = OpenSSL::PKey::RSA.generate 2048
rsa_public = rsa_private.public_key
token = JWT.encode payload, rsa_private, 'RS256'
puts token
decoded_token = JWT.decode token, rsa_public, true, { algorithm: 'RS256' }
puts decoded_token
post = {
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion': token
}
uri = URI.parse('https://login.salesforce.com/services/oauth2/token')
https = Net::HTTP.new(uri.host, 443)
https.use_ssl = true
response = https.post(uri.path, post.to_query)
print response.body
the PHP version of what I want to achieve is something like this.
<?php
require_once './vendor/autoload.php';
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
// login URL
// production: https://login.salesforce.com
// Sandbox: https://test.login.salesforce.com
define('LOGIN_URL', 'https://test.salesforce.com');
//consumer key
define('CLIENT_ID', <<consumer key of the application on salesforce>>);
//user ID
define('USER_ID', 'xxxxx#example.com');
function createjwt() {
$signer = new Sha256();
$privateKey = new Key('file://cert/server.key'); ← probably the key from certification
$time = time();
$token = (new Builder())->issuedBy(CLIENT_ID) // iss: consumer key
->permittedFor(LOGIN_URL) // aud: Salesforce login URL
->relatedTo(USER_ID) // sub: Salesforce user ID
->expiresAt($time + 3 * 60) // exp: within three mins
->getToken($signer, $privateKey);
return $token;
}
$jwt = createjwt();
echo $jwt;
function auth() {
$jwt = createjwt();
$post = array(
'grant_type' => GRANT_TYPE,
'assertion' => $jwt,
);
$curl = curl_init();
curl_setopt( $curl, CURLOPT_URL, AUTH_URL );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $post );
$buf = curl_exec( $curl );
if ( curl_errno( $curl ) ) {
exit;
}
curl_close( $curl );
$json = json_decode( $buf );
$accinfo = array(
// URL to access
'instance_url' => $json->instance_url,
// Bearer token in order to access
'access_token' => $json->access_token,
);
return $accinfo;
}
$accinfo = auth();
EDIT
I changed a code a lot. But I still have different error that says 'initialize': Neither PUB key nor PRIV key: nested asn1 error (OpenSSL::PKey::RSAError)' around #private_key definition.
I read this and tried changing the string in private_key.pem to in one line but I didn't work ( maybe I did in a wrong way) and didn't understand the meaning of incorrect password (mentioned as the second answer) What causes "Neither PUB key nor PRIV key:: nested asn1 error" when building a public key in ruby?
def initialize
#cert_file = File.join(File.dirname(__FILE__), *%w[private_key.pem])
# #cert = Base64.urlsafe_encode64(#cert_file)
# print #cert_
# #cert_file = File.join(File.dirname(__FILE__), *%w[server.csr])
#base_url = "https://test.salesforce.com"
#auth_endpoint = "/services/oauth2/authorize"
#token_request_endpoint = "/services/oauth2/token"
#token_revoke_endpoint = "/services/oauth2/revoke"
#username = "my username"
#client_id = "pe2TCoA1~~~~" client_id
#private_key = OpenSSL::PKey::RSA.new(File.read(#cert_file))
# #private_key = OpenSSL::PKey::RSA.generate(private_key)
#rsa_public = #private_key.public_key
# #private_key = OpenSSL::PKey::RSA.new(File.read(#cert_file))
end
def claim_set
{
iss: #client_id,
sub: #username,
aud: #base_url,
exp: (Time.now + 3.minutes).to_i.to_s
}
end
def jwt_bearer_token
JWT.encode(self.claim_set.to_s, #rsa_public, 'RS256')
end
def request_auth
post = {body: {grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer", assertion: jwt_bearer_token}}
uri = URI.parse("#{#base_url}#{#token_request_endpoint}")
https = Net::HTTP.new(uri.host, 443)
https.use_ssl = true
response = https.post(uri.path, post.to_query)
print response.body
end
Salesforce.new.request_auth
end
Any advices are appreciated.
Thank you

The view function did not return a valid response. The return type must be a string, dict

using Spotify API and Flask I am trying to extend refresh_token validity. As a result, when I send a request to the server, I get this error:
*The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a Response.*
My code:
#app.route("/index")
def index():
if time.time() > session['expires_in']:
payload = session['refresh_token']
ref_payload = {
'grant_type': 'refresh_token',
'refresh_token':session["refresh_token"]
}
header={'Authorization': 'Basic ' + '<CLIENT_ID>:<CLIENT_SECRET'}
r = requests.post(AUTH_URL, data=ref_payload, headers=header)
return r
#app.route("/q")
def api_callback():
session.clear()
code = request.args.get('code')
res = requests.post(AUTH_URL, data={
"grant_type":"authorization_code",
"code":code,
"redirect_uri":REDIRECT_URI,
"client_id":CLIENT_ID,
"client_secret":CLIENT_SECRET
})
res_body = res.json()
session["token"] = res_body.get("access_token")#token
session["expires_in"] = res_body.get("expires_in")#time
session["refresh_token"] = res_body.get("refresh_token")#reflesh token
return redirect("index")
https://accounts.spotify.com/api/token is accepted as AUTH_URL
Most likely the problem is very commonplace, but I can't think of a solution now. Thanks in advance
I solved this problem. In my configurashion file i was create a veriable in which i encode my client_id and client_secret to base64 format:
ID_SEC = CLIENT_ID +':'+ CLIENT_SECRET
base64_encode = base64.b64encode(ID_SEC.encode()).decode()
After in the header i edit authorisation :
header={
'Content-Type':'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Authorization': 'Basic {}'.format(base64_encode)
}
And send post requests:
r = requests.post(AUTH_URL, data=ref_payload, headers=header)

Slim Framework GetHeaders from Post Request

I am sending a token in header and I want that token for JWT authentication. How can I get the headers passed. Body I am getting in
$data using below code
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
I need the headers sent in post.
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
$app->post('/staff','getStaff');
$app->run();
function getStaff() {
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
$header = $request->getBasePath();
// echo $header;
print_r( $header);
print_r( $data);
}
$header = $app->request->headers->get('Content-Type');
I got the answer. My version of Slim was 2.4 and I figured it out from old documentation.
Pass the header key you want, in my case it was Token
$header = $app->request->headers->get('Token');
Now I will get the token passed through headers

XING oauth api error invalid oauth signature

I got a problem with the xing oauth api.
Currently this works:
Get a request token from xing
Redirect the client to authentificate at xing
Get the callback from xing
Now I have to get the access token from xing, using the oauth token and verifier.
I'm using the same code to generate the oauth signature for this like when I request the request token at step 1.
With this function, I generate the signature:
private function buildOauthSignature($httpMethod, $requestTokenUrl, $params) {
// Remove 'oauth_signature' if it's empty
if (empty($params['oauth_signature'])) {
unset($params['oauth_signature']);
}
$parts = array(
$httpMethod,
$requestTokenUrl,
$this->buildQuery($params)
);
$parts = $this->urlencode_rfc3986($parts);
$signatureBaseString = implode('&', $parts);
$keyParts = array(
$this->strategy['consumer_secret'],
""
);
$key = implode('&', $keyParts);
return base64_encode(hash_hmac('sha1', $signatureBaseString, $key, true));
}
Does someone know this?

How do you POST to a page using the PHP header() function?

I found the following code on here that I think does what I want, but it doesn't work:
$host = "www.example.com";
$path = "/path/to/script.php";
$data = "data1=value1&data2=value2";
$data = urlencode($data);
header("POST $path HTTP/1.1\r\n");
header("Host: $host\r\n");
header("Content-type: application/x-www-form-urlencoded\r\n");
header("Content-length: " . strlen($data) . "\r\n");
header("Connection: close\r\n\r\n");
header($data);
I'm looking to post form data without sending users to a middle page and then using JavaScript to redirect them. I also don't want to use GET so it isn't as easy to use the back button.
Is there something wrong with this code? Or is there a better method?
Edit I was thinking of what the header function would do. I was thinking I could get the browser to post back to the server with the data, but this isn't what it's meant to do. Instead, I found a way in my code to avoid the need for a post at all (not breaking and just continuing onto the next case within the switch).
The header function is used to send HTTP response headers back to the user (i.e. you cannot use it to create request headers.
May I ask why are you doing this? Why simulate a POST request when you can just right there and then act on the data someway? I'm assuming of course script.php resides on your server.
To create a POST request, open a up a TCP connection to the host using fsockopen(), then use fwrite() on the handler returned from fsockopen() with the same values you used in the header functions in the OP. Alternatively, you can use cURL.
The answer to this is very needed today because not everyone wants to use cURL to consume web services. Also PHP does allow for this using the following code
function get_info()
{
$post_data = array(
'test' => 'foobar',
'okay' => 'yes',
'number' => 2
);
// Send a request to example.com
$result = $this->post_request('http://www.example.com/', $post_data);
if ($result['status'] == 'ok'){
// Print headers
echo $result['header'];
echo '<hr />';
// print the result of the whole request:
echo $result['content'];
}
else {
echo 'A error occured: ' . $result['error'];
}
}
function post_request($url, $data, $referer='') {
// Convert the data array into URL Parameters like a=b&foo=bar etc.
$data = http_build_query($data);
// parse the given URL
$url = parse_url($url);
if ($url['scheme'] != 'http') {
die('Error: Only HTTP request are supported !');
}
// extract host and path:
$host = $url['host'];
$path = $url['path'];
// open a socket connection on port 80 - timeout: 30 sec
$fp = fsockopen($host, 80, $errno, $errstr, 30);
if ($fp){
// send the request headers:
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
if ($referer != '')
fputs($fp, "Referer: $referer\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ". strlen($data) ."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $data);
$result = '';
while(!feof($fp)) {
// receive the results of the request
$result .= fgets($fp, 128);
}
}
else {
return array(
'status' => 'err',
'error' => "$errstr ($errno)"
);
}
// close the socket connection:
fclose($fp);
// split the result header from the content
$result = explode("\r\n\r\n", $result, 2);
$header = isset($result[0]) ? $result[0] : '';
$content = isset($result[1]) ? $result[1] : '';
// return as structured array:
return array(
'status' => 'ok',
'header' => $header,
'content' => $content);
}
In addition to what Salaryman said, take a look at the classes in PEAR, there are HTTP request classes there that you can use even if you do not have the cURL extension installed in your PHP distribution.
There is a good class that does what you want. It can be downloaded at: http://sourceforge.net/projects/snoopy/
private function sendHttpRequest($host, $path, $query, $port=80){
header("POST $path HTTP/1.1\r\n" );
header("Host: $host\r\n" );
header("Content-type: application/x-www-form-urlencoded\r\n" );
header("Content-length: " . strlen($query) . "\r\n" );
header("Connection: close\r\n\r\n" );
header($query);
}
This will get you right away

Resources