JWT Token generated always results in 401 when submitted to Apple servers - jwt

I am using the following code in PHP to generate a JWT token to use with the App Store Server API:
$keyId = 'provided by apple';
$priv_key = <<<EOD
-----BEGIN PRIVATE KEY-----
provided by apple
-----END PRIVATE KEY-----
EOD;
$pem_private_key = file_get_contents('AuthKey.pem');
$private_key = openssl_pkey_get_private($pem_private_key);
$public_key_pem = openssl_pkey_get_details($private_key)['key'];
$public_key = openssl_pkey_get_public($public_key_pem);
$headers = [
"kid"=> $keyId,
"typ" => 'JWT'
];
$payload = [
"iss" => "provided by apple",
"iat" => time(),
"exp" => time() + (60 * 60 * 24 * 7),
"aud" => "appstoreconnect-v1",
"bid" => "com.bundle.my"
];
$jwt = JWT::encode($payload, $priv_key, 'ES256', $keyId, $headers);
This results in a JWT token. However when I try to use it with the Apple Store API, I always get 401 Unauthorized; Unauthenticated.
What am I doing wrong?

The problem was the expiration time as Apple only allows an expiration of max 20 mins.
Changed to time() + 1200.

Related

What is this? (Facebook Offline Conversions API) Error #21009 - The data set upload is temporarily not ready

We have been uploading to Facebook's Offline Conversion API for the past 3 weeks with no issues. Suddenly, Facebook is returning this error:
(#21009) The data set upload is temporarily not ready.
See below code for full JSON payload.
Our Auth Token is still valid. (e.g. Not expired, still valid)
According to this tool: https://developers.facebook.com/tools/debug/accesstoken/
# I had to remove these fields for privacy reasons
define('FACEBOOK_APP_ACCESS_TOKEN', 'YOUR TOKEN HERE');
define('FACEBOOK_PIXEL_OFFLINE_EVENT_SET_ID', 'YOUR PIXEL ID HERE');
# Be sure to change the email/name fields accordingly
$event_name='test-upload';
$data = array();
$data["match_keys"] = array();
$data["match_keys"]['email'] = hash('sha256', 'bob.ross#example.com');
$data["match_keys"]['fn'] = hash('sha256', 'bob');
$data["match_keys"]['ln'] = hash('sha256', 'ross');
$data["match_keys"]['gen'] = hash('sha256', 'm');
$data["event_time"] = time();
$data["event_name"] = $event_name;
$data["currency"] = "USD";
$data["value"] = '0.00';
// Turn Data to JSON
$data_json = json_encode(array($data));
// Fill available fields
$fields = array();
$fields['access_token'] = FACEBOOK_APP_ACCESS_TOKEN;
$fields['upload_tag'] = $event_name . '-' . time(); // You should set a tag here (feel free to adjust)
$fields['data'] = $data_json;
$url = 'https://graph.facebook.com/v3.2/' . FACEBOOK_PIXEL_OFFLINE_EVENT_SET_ID . '/events';
$curl = curl_init($url);
curl_setopt_array($curl, array(
// Replace with your offline_event_set_id
CURLOPT_URL => 'https://graph.facebook.com/v3.2/' . FACEBOOK_PIXEL_OFFLINE_EVENT_SET_ID . '/events',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => http_build_query($fields),
CURLOPT_HTTPHEADER => array(
"cache-control: no-cache",
//"content-type: multipart/form-data",
"Accept: application/json" ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Expected result from Facebook:
{"id":"36485444079550","num_processed_entries":1}
Actual result from Facebook
{
"error": {
"message": "(#21009) The data set upload is temporarily not ready.",
"type": "OAuthException",
"code": 21009,
"fbtrace_id": "GeofD5QsXdI"
}
}
I would add a comment instead of an "answer" but I don't quite have the points yet. The commenters on the Facebook thread (https://developers.facebook.com/support/bugs/1052442614962359/) have had this magically resolve overnight, and I experienced the same (problem happening and no explanation, then magical resolution and no explanation). It seems like Facebook may have fixed whatever was causing the issue.

Slim 3: How to access user information from request headers

I am using Slim 3.1 and able to authenticate correctly i.e. able to generate the token and use it for another POST request. Now I want to parse the request header to extract the user information so I can identify which user have sent the request.
Here is my code to get the token.
$app->post('/login/token', function (Request $request, Response $response,
array $args) {
$input = $request->getParsedBody();
$now = new DateTime();
$future = new DateTime("+10 minutes");
$server = $request->getServerParams();
$jti = (new Base62)->encode(random_bytes(16));
$payload = [
"iat" => $now->getTimeStamp(),
"exp" => $future->getTimeStamp(),
"jti" => $jti,
"sub" => $input['username']
];
$sql = "SELECT * FROM user WHERE User_Name= :username";
$sth = $this->db->prepare($sql);
$sth->bindParam("username", $input['username']);
$sth->execute();
$user = $sth->fetchObject();
// verify email address.
if(!$user) {
return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);
}
// verify password.
if (!password_verify($input['password'],$user->User_Password)) {
return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);
}
$settings = $this->get('settings'); // get settings array.
//$token = JWT::encode(['User_ID' => $user->User_ID, 'username' => $user->User_Name], $settings['jwt']['secret'], "HS256");
$token = JWT::encode($payload, $settings['jwt']['secret'], "HS256");
return $this->response->withJson(['token' => $token, 'ACL' => $user->User_ACL]);
});
This returns me a token that I send in the following POST request
$app->group('/api', function(\Slim\App $app) {
$app->post('/createuser', function (Request $request, Response $response,
array $args) {
$headerValueArray = $request->getHeader('HTTP_AUTHORIZATION');
return $this->response->withJson(['success' => true, $token]);
});
});
The above POST request gives the following output
{
"success": true,
"0": ["Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzU4Mjk0OTUsImV4cCI6MTUzNTgzNjY5NSwianRpIjoiMWc5ZFM3dUNLbzl1blRQZzBmYjU2diIsInN1YiI6InN5c2FkbWluIn0.vo3FBPhBkhfA2y7AG-afmjfeEhygIYY7lIaaVNX5i5k"]
}
I need to parse this token to extract the user information to see if its the valid user to perform this operation.In other words, how I can decode the above token.
Any help here will be much appreciated!

Can my facebook app serve a gallery from a different facebook account?

I am trying to serve a Facebook gallery for a client, and due to the server the site is being hosted on, the request needs to be authenticated.
I have set up an app using our company Facebook developer account. Although I have set the domain of the app to that of our client's, the gallery returned in the request is empty.
I am assuming that I will need access to the client's facebook account so I can create an app associated directly with their facebook account - the one where I want the galleries from? EDIT - just thought I'd point out that the client would prefer not to give me their passwords for their facebook account...
Here is the auth code I have used, if anyone will be kind enough to point out any school boy errors I may have made.
$no_albums = 6;
$latest_albums = null;
$user_id = "xxxxxx";
$app_secret = "xxxxxxxxxxxxxxxxxxxx";
$app_token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $user_id
. "&client_secret=" . $app_secret
. "&grant_type=client_credentials"
. "&scope=user_photos";
$response = wp_remote_get($app_token_url);
$access_token = $response['body'];
error_log(print_r($response,true));
$query = 'https://graph.facebook.com/'.$user_id.'/albums?' . $access_token;
$albums = json_decode(file_get_contents('http://graph.facebook.com/'.$user_id.'/albums') );
And this is the response I get ( $albums ) in my error logs:
Array
(
[headers] => Array
(
[access-control-allow-origin] => *
[cache-control] => private, no-cache, no-store, must-revalidate
[content-type] => application/json; charset=UTF-8
[etag] => "1050253aec7b29caff644806927dabfa81406eee"
[expires] => Sat, 01 Jan 2000 00:00:00 GMT
[pragma] => no-cache
[x-fb-rev] => 812093
[x-fb-debug] => 9I0lRzV3GZxrflP/19iBvhly6FLUVI9jCHJAXcw0Dm0=
[date] => Mon, 13 May 2013 10:45:39 GMT
[connection] => close
[content-length] => 11
)
[body] => {"data":[]}
[response] => Array
(
[code] => 200
[message] => OK
)
[cookies] => Array
(
)
[filename] =>
Thanks.
You've got a couple of basic problems here.
First, in your API request, you are looking for albums associated with your APP_ID. There are none. You should be using the client's PAGE_ID or USER_ID in the request to the graph API.
Second, you should be using the Facebook PHP SDK instead of file_get_contents() to make your requests. Especially if this is to be a production environment.
If your clients albums are publicly visible, you may not need to authenticate a user to view them. To know this for sure, you'd need to share your client's Facebook username.

Zend Gmail Oauth: How to get authenticated user profile?

I am using Zend Gmail Oauth 1.0 for implementing login with Gmail feature.
After successful authentication, how can I get authenticated user's profile, specifically user's unique gmail id? Here is the code:
$THREE_LEGGED_SCOPES = array('https://mail.google.com/',
'https://www.google.com/m8/feeds');
$options = array(
'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER,
'version' => '1.0',
'consumerKey' => $THREE_LEGGED_CONSUMER_KEY,
'consumerSecret' => $THREE_LEGGED_CONSUMER_SECRET_HMAC,
'callbackUrl' => getCurrentUrl(),
'requestTokenUrl' => 'https://www.google.com/accounts/OAuthGetRequestToken',
'userAuthorizationUrl' => 'https://www.google.com/accounts/OAuthAuthorizeToken',
'accessTokenUrl' => 'https://www.google.com/accounts/OAuthGetAccessToken'
);
if ($THREE_LEGGED_SIGNATURE_METHOD == 'RSA-SHA1') {
$options['signatureMethod'] = 'RSA-SHA1';
$options['consumerSecret'] = new Zend_Crypt_Rsa_Key_Private(
file_get_contents(realpath($THREE_LEGGED_RSA_PRIVATE_KEY)));
} else {
$options['signatureMethod'] = 'HMAC-SHA1';
$options['consumerSecret'] = $THREE_LEGGED_CONSUMER_SECRET_HMAC;
}
$consumer = new Zend_Oauth_Consumer($options);
/**
* When using HMAC-SHA1, you need to persist the request token in some way.
* This is because you'll need the request token's token secret when upgrading
* to an access token later on. The example below saves the token object
* as a session variable.
*/
if (!isset($_SESSION['ACCESS_TOKEN'])) {
if (!isset($_SESSION['REQUEST_TOKEN'])) {
// Get Request Token and redirect to Google
$_SESSION['REQUEST_TOKEN'] = serialize($consumer->getRequestToken(array('scope' => implode(' ', $THREE_LEGGED_SCOPES))));
$consumer->redirect();
} else {
// Have Request Token already, Get Access Token
$_SESSION['ACCESS_TOKEN'] = serialize($consumer->getAccessToken($_GET, unserialize($_SESSION['REQUEST_TOKEN'])));
header('Location: ' . getCurrentUrl(false));
exit;
}
} else {
// Retrieve mail using Access Token
$accessToken = unserialize($_SESSION['ACCESS_TOKEN']);
}
near as I can tell you can't.
Gmail doesn't have an api just a read only feed.
However if you want that feed the scope url is:
https://mail.google.com/mail/feed/atom/
There are some api's for working with gmail accounts in the context of Google Apps.

How to format Serialized Zend_Service_Twitter response

When I use OAuth to connect an application to a twitter account I put the access token and the user data in my database as follow:
$this->consumer = new Zend_Oauth_Consumer($this->configTwitter);
if(!empty($_GET) && isset($_SESSION['TWITTER_REQUEST_TOKEN']))
{
$token = $this->consumer->getAccessToken($_GET, unserialize($_SESSION['TWITTER_REQUEST_TOKEN']));
// Get user info
$twitter = new Zend_Service_Twitter(array(
'username' => $token->screen_name,
'accessToken' => $token,
'callbackUrl' => $this->_getParam('SettingsWebsiteUrl').'/news/index/connecttwitter',
'consumerKey' => 'XXXXXX',
'consumerSecret' => 'XXXXXXX'
));
$response = $twitter->account->verifyCredentials();
// place in database
$this->NewsService->TokenSocialMedia(
$token,
'twitter',
serialize($response)
);
$_SESSION['TWITTER_REQUEST_TOKEN'] = null;
$this->_helper->flashMessenger(array('message' => $this->view->translate('The CMS is successfully connected to your twitter account'), 'status' => 'success'));
$this->_helper->redirector('settings', 'index');
}
else
{
$token = $this->consumer->getRequestToken();
$_SESSION['TWITTER_REQUEST_TOKEN'] = serialize($token);
$this->consumer->redirect();
}
This works fine. The response looks like this below and I have no clue of how to format this and display it to the user. Only thing I want is to store the twitter id, twitter name (not screen_name) and the image url.
O:23:"Zend_Rest_Client_Result":2:{s:8:"�*�_sxml";O:16:"SimpleXMLElement":34:{s:2:"id";s:9:"150638034";s:4:"name";s:20:"De Graaf & Partners ";s:11:"screen_name";s:15:"GraafenPartners";s:8:"location";s:9:"Culemborg";s:11:"description";s:34:"Full service communications agency";s:17:"profile_image_url";s:78:"http://a2.twimg.com/profile_images/1191111069/Logo_DG_P-CMYK_Square_normal.jpg";s:3:"url";s:31:"http://www.degraafenpartners.nl";s:9:"protected";s:5:"false";s:15:"followers_count";s:1:"0";s:24:"profile_background_color";s:6:"C0DEED";s:18:"profile_text_color";s:6:"333333";s:18:"profile_link_color";s:6:"0084B4";s:26:"profile_sidebar_fill_color";s:6:"DDEEF6";s:28:"profile_sidebar_border_color";s:6:"C0DEED";s:13:"friends_count";s:1:"0";s:10:"created_at";s:30:"Tue Jun 01 12:47:51 +0000 2010";s:16:"favourites_count";s:1:"0";s:10:"utc_offset";s:4:"3600";s:9:"time_zone";s:9:"Amsterdam";s:28:"profile_background_image_url";s:60:"http://a3.twimg.com/a/1296525272/images/themes/theme1/bg.png";s:23:"profile_background_tile";s:5:"false";s:28:"profile_use_background_image";s:4:"true";s:13:"notifications";s:5:"false";s:11:"geo_enabled";s:4:"true";s:8:"verified";s:5:"false";s:9:"following";s:5:"false";s:14:"statuses_count";s:1:"6";s:4:"lang";s:2:"en";s:20:"contributors_enabled";s:5:"false";s:19:"follow_request_sent";s:5:"false";s:12:"listed_count";s:1:"0";s:21:"show_all_inline_media";s:5:"false";s:13:"is_translator";s:5:"false";s:6:"status";O:16:"SimpleXMLElement":15:{s:10:"created_at";s:30:"Mon Jan 03 08:41:11 +0000 2011";s:2:"id";s:17:"21848534684794880";s:4:"text";s:53:"De Graaf & Partners wenst iedereen een creatief 2011!";s:6:"source";s:3:"web";s:9:"truncated";s:5:"false";s:9:"favorited";s:5:"false";s:21:"in_reply_to_status_id";O:16:"SimpleXMLElement":0:{}s:19:"in_reply_to_user_id";O:16:"SimpleXMLElement":0:{}s:23:"in_reply_to_screen_name";O:16:"SimpleXMLElement":0:{}s:13:"retweet_count";s:1:"0";s:9:"retweeted";s:5:"false";s:3:"geo";O:16:"SimpleXMLElement":0:{}s:11:"coordinates";O:16:"SimpleXMLElement":0:{}s:5:"place";O:16:"SimpleXMLElement":0:{}s:12:"contributors";O:16:"SimpleXMLElement":0:{}}}s:10:"�*�_errstr";N;}
How do I need to format the data, or how can I store the data better?
If all you want to store is their image url, then you just need their username, then use this:
http://img.tweetimag.es/i/oprah_o
where oprah_o is the username.
You don't need to use OAuth and Zend_Service_Twitter to do that. If you want to be able to get data from a non public feed, or publish tweets to their accounts, that's where you need Zend_Service_Twitter.
If you want to get data from that resultset, just do:
$result_obj = unserialize($token);