I'm creating simple app for Uber.
And I've already solved 3 steps from this API: https://developer.uber.com/docs/authentication
But now I want to refresh token (step 5).
I receive access_token, refresh_token, expires_in values, and I can't understand how to set up timer to refresh user's token with refresh_token when the expires_in time expire.
Here I provide my example of code, where I want to renew access token with refresh_token.
<?php
session_start();
require_once 'uber_b.php';
require_once 'config.php';
if(isset($_GET['code'])) {
// try to get an access token
$code = $_GET['code'];
$url = 'https://login.uber.com/oauth/token';
/*
* Create row for function setPostData (uber_b.php)
* All of this rows will be used to build our request
*/
$params = array(
"code" => $code,
"client_id" => $client_id,
"client_secret" => $client_secret,
"redirect_uri" => $redirect,
"grant_type" => "authorization_code"
);
//create example of class
$request = new HttpPost($url);
//Connect this class with our settings
$request->setPostData($params);
//Send our request to Uber
$request->send();
//Receive response
$responseObj = json_decode($request->getHttpResponse());
//Execute parameters from answer
$user_token = $responseObj->access_token;
//Refresh token
$refresh_token = $responseObj->refresh_token;
//Time for token
$expires_in = $responseObj->expires_in;
echo "User's token: " . $user_token;
echo "<br>";
echo "Refresh token is: " .$refresh_token ;
echo "<br>";
echo "Time: ".$expires_in;
echo "<br>";
echo "<a href='order.php'>Order a car</a>";
}
//Refresh token
if(isset($responseObj))
{
$exp_time = time()+2592000;
try {
//insert into database
$stmt = $db->prepare('INSERT INTO token2 (exp_time)
VALUES (:exp_time)
');
$stmt->execute(array(
':exp_time' => $exp_time
));
} catch(PDOException $e) {
echo $e->getMessage();
}
}
if(time() >= $exp_time)
{
//Parameters for Uber refresh token request(step 5)
$r_params = array(
"client_id" => $client_id,
"client_secret" => $client_secret,
"redirect_uri" => $redirect,
"grant_type" => "refresh_token",
"refresh_token" => $refresh_token
);
$r_request = new RefreshToken($url);
$r_request->setPostData($r_params);
$r_request->send();
$refresh = $refresh_token;
$r_responseObj = json_decode($r_request->Refresh());
echo "New Refresh token: " . $r_responseObj->refresh_token;
echo "<br>";
}
?>
As you see, I don't provide timer function, because I don't understand how to make it right.
So, can you explain me how to correctly renew access_token using refresh_token?
Maybe I have to use setcookie(), or something else to solve this task?
First of all, according to the STEP FIVE: REFRESHING TOKENS from the Authentication docs, to refresh the access token you need to HTTP POST the following parameters:
client_secret=YOUR_CLIENT_SECRET
client_id=YOUR_CLIENT_ID
grant_type=refresh_token
redirect_uri=YOUR_REDIRECT_URI
refresh_token=REFRESH_TOKEN
to the https://login.uber.com/oauth/v2/token API endpoint
You are also sending the code parameter, which means you will receive an error because of this additional parameter which fails to validate on Uber's server.
The error you get will be
HTTP/1.1 401 UNAUTHORIZED
{"error": "invalid_grant"}
To be able to check the token validity, after you've exchanged the code with the access token, you need to:
Persist somewhere the "access_token", "expires_in", "refresh_token" and a UNIX timestamp in seconds, representing the current time and date, let's call it "itime".
The location where you can store this information is multi varied: session, file, database, memory cache, etc., depending on how you want to handle token expiration and automatic user login if you already have their token saved and it's not expired, then you don't have to make the user login again.
Before each HTTP request that you make to the Uber API you first check that the access token hasn't expired by retrieving the "itime" and "expires_in" from the storage location for the access token of the user and making sure that the time() < "itime"+"expires_in" holds true.
If the condition is false, then you need to refresh the access token.
Keep in mind that refreshing the access token also changes the refresh token, so you need to replace the current "access_token", "refresh_token" and "expires_in" for the current user identified by the uuid.
Given that the current expiration time for an access token is 30 days (2592000 seconds) I'd suggest that you store the access token data inside a database table, because PHP sessions are short lived (by default session.gc_maxlifetime is 1440 seconds/24 minutes in php.ini) and the user will not stay on your app/website all that time either.
Moreover, checking the expiration time is not enough if you allow the user to login to Uber from multiple devices/places, because after each user login all the previous access/refresh tokens are invalidated. So, after the user signs in on the second device you might have an invalid access/token with a valid expiration time on the first device.
In this scenario, to determine if the access token is still valid I'd suggest you make an additional HTTP request to the GET /v1/me endpoint using the access token. If it works, the token is still valid, otherwise it expired/was invalidated, and you need to request a user re-login on the first device.
tl;dr You don't need a timer, you need to check before each HTTP request to the Uber API that the access token is still valid.
To do this, you need to persist the token details + UNIX timestamp.
Related
Hi I am creating a token to compare against some record on the database to log a user in. I am using token = openssl_random_pseudo_bytes to set this random string, but how its stored on the browser and database seem to be different. How do I compare these two strings?
Set the value token first using a cookie way
$value = "23asdoq23ARDAsdadq2";
// cookie will expire when the browser close
setcookie("tokenCookie", $value);
// cookie will expire in 1 hour or set it to your needs
setcookie("tokenCookie", $value, time() + 3600);
or set the duration to 0, so that cookie duration will end only when users browser is close
setcookie("tokenCookie", $value, 0);
then retrieved the cookie and compare selected token value from the database with the cookie token.
if(!isset($_COOKIE['tokenCookie'])) {
$tokenCookie = $_COOKIE['tokenCookie'];
// Assume you already retrieved the token value from the database and stored it to a variable then you just need to compare it..
if( $tokenCookie == $token_value_from_database ){
echo true;
}else{
echo false;
}
}
I hope you can help me with an issue with phone call dialings using Plivo PHP (new SDK 4.0). First I will indicate what I want to achieve:
- A client on my website wants to talk with an agent of main, so he introduces his telephone number in a form, choose an agent, and finally when submit, the website connect both of them dialing (this works). But then, (here begin my problems), I can't retrieve the call details (status, duration, initial and end dates of the call, etc...) for invoicing the client according to some of these details.
Edited 2018/02/23:
Ramya, the 600 error has dissapeared and everything seems to be ok as I see in the Plivo debug log. Below are my new codes (I think better done thanks to your instructions), and then, I show you the Plivo debud log (perhaps it's better you can see it inside my account, call made Feb 23, 2018 18:33:15), and finally I see my server debug error log is empty!.
The main problem is that dialstatus.php file, although seems to receive the parameters, I don't know how to access them because dialstatus.php does not execute showing the data in my monitor (in my code for example, this line never shows in the monitor screen:)
echo "Status = $estado, Aleg UUID = $aleg, Bleg UUID = $bleg";
So even though it receives the parameters, I can not access them to manipulate them, print them on the screen, do ifs with them, etc. May it be perhaps a permission problem with the files? (These php files have 6,4,4 permissions on my server, the same as the others).
Thank you!
Code 1: makecall.php
require 'vendor/autoload.php';
use Plivo\RestClient;
$client = new RestClient("**********", "**************************");
$telefono_cliente = "34*******";
$telefono_experto = "34*********";
$duracion = 50;
try {
$response = $client->calls->create(
"3491111111",
[$telefono_experto],
"https://www.ejemplo.com/llamar/response.php?telf=$telefono_cliente",
'POST',
[
'time_limit' => $duracion,
]
);
$id = $response->requestUuid;
echo "<br>Este es el requestUuid: " . $id . "<br><br>";
}
catch (PlivoRestException $ex) {
print_r($ex);
}
?>
Code 2: response.php
require 'vendor/autoload.php';
use Plivo\XML\Response;
$resp = new Response();
$params = array(
'callerId' => '3491111111',
'action' => "https://www.ejemplo.com/llamar/dialstatus.php",
'method' => "POST",
'redirect' => "false"
);
$body3 = 'Desde ejemplo un cliente desea hablar con usted.';
$params3 = array(
'language' => "es-ES", # Language used to read out the text.
'voice' => "WOMAN" # The tone to be used for reading out the text.
);
$resp->addSpeak($body3,$params3);
$dial = $resp->addDial($params);
//$number = "34**********";
$number = $_GET['telf'];
$dial->addNumber($number);
Header('Content-type: text/xml');
echo($resp->toXML());
/*
Output:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Speak language="es-ES" voice="WOMAN">Desde ejemplo un cliente desea hablar con usted.</Speak>
<Dial redirect="false" method="POST" action="http://www.ejemplo.com/llamar/dialstatus.php" callerId="3491111111">
<Number>34********</Number>
</Dial>
</Response>
*/
?>
Code 3: dialstatus.php
// Print the Dial Details
$estado = $_REQUEST['DialStatus'];
$aleg = $_REQUEST['DialALegUUID'];
$bleg = $_REQUEST['DialBLegUUID'];
echo "Status = $estado, Aleg UUID = $aleg, Bleg UUID = $bleg";
?>
Plivo Sales Engineer here.
Redirect = true is used only when you want to continue the call by returning another XML in your action URL. For you use case, you don't have to use this parameter. Even if the Redirect is set to false, Plivo will make a request to the action URL with a list of parameters. I looked into your account (here) and I can see this request getting sent with DialStatus, ALegUUID, BLegUUID along with other parameters.
Dial Action URL is the best place to know the DialStatus and DialHangupCause.
You can find the call duration and billing amount in Hangup URL request as well. This Hangup URL can be configured in your first API call (to the expert). By default, hangup URL is set to Answer URL.
Please raise a support ticket with us for further assistance.
Okay so here goes i am using a rest api called strichliste
i am creating a user credit payment system
i am trying to grab a users balance by username problems is
my restapi i can only get the blanace via its userid
I have created a bit of php that grabs all the current users and the corresponding id and balance using this below
function getbal(){
// Get cURL resource
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://example.io:8081/user/'
)
);
// Send the request & save response to $resp
$resp = curl_exec($curl);
// Close request to clear up some resources
curl_close($curl);
print_r($resp);
}
this is the resulting respinse i get after using this in my main php script
<? getbal(); ?>
result --- #
{
"overallCount":3,
"limit":null,
"offset":null,"entries":[
{"id":1,
"name":"admin",
"balance":0,
"lastTransaction":null
},
{"id":2,
"name":"pghost",
"balance":0,
"lastTransaction":null
},
{"id":3,
"name":"sanctum",
"balance":0,
"lastTransaction":null
}
]
}
as you can see there are only currently 3 users but this will grow everyday so the script needs to adapt to growing numbers of users
inside my php script i have a var with the currently logged in use so example
$user = "sanctum";
i want a php script that will use the output fro gatbal(); and only output the line for the given user in this case sanctum
i want it to output the line in jsondecode for the specific user
{"id":3,"name":"sanctum","balance":0,"lastTransaction":null}
can anyone help
$user = "sanctum";
$userlist = getbal();
function findUser($u, $l){
if(!empty($l['entries'])){
foreach($l['entries'] as $key=>$val){
if($val['name']==$user){
return $val;
}
}
}
}
This way, once you have the list, and the user, you can just invoke findUser() by plugging in the userlist, and the user.
$userData = findUser($user, $userlist);
However, I would suggest finding a way to get the server to return only the user you are looking for, instead of the whole list, and then finding based on username. But thats another discussion for another time.
I have a rest service that my website calls it and I want to secure it from calling outside of my website as much as possible.
I want to create a token mixed with timestamp, so the user can only call the service in 10 minutes (for example) with the token that generated in the server.
Let me explain it with some pseudo codes:
1) Server: The token is generated in the server using a private key and timestamp:
// The token is valid only for 10 minutes after 'time'
$token = encrypt($pKey, timestamp); // Server Time
2) Client: We put the token in the javascript variable and use it in our request with the timestamp of the client:
var token = '<?= $token ?>';
var params = {
token : token,
time : timestamp, // Client Time
data : mydata
}
3) Server: If the time parameter mixed with token is not equal to 10 minutes token, the request is invalid:
// I'm Stuck Here
$something = decrypt($pKey, $_POST['token'], $_POST['time']);
if ($something != $tenMinutes) { // Invalid Request }
The Question:
1) Is this senario O.K? If Yes, What is the exact solution? If No, So What is the solution?
2) There is another senario to secure the requests that I've seen in the AWS: http://docs.aws.amazon.com/AmazonS3/latest/dev/S3_Authentication2.html
How can I implement this in PHP?
After you've got token from the client you need to check two things: validity of the token and its timestamp.
There are two scenarios:
Make timestamp part of the token:
function getToken($timestamp) {
return $timestamp . encrypt(getPKey(), $timestamp);
}
$token = genToken(time());
And then validate it:
$token = $_POST['token'];
function validate($token) {
$timestamp = substr($token, 0, 10);
return
(genToken($timestamp) == $token)
&& ($timestamp >= time() - 600);
}
Save generated token in database along with timestamp and after getting token from the client check corresponding timestamp.
I'm trying to work with the examples on the Twitter dev site but can't seem to get to the same signature as they have.
I am trying to complete step 3 on https://dev.twitter.com/docs/auth/implementing-sign-twitter because I am getting an error "Invalid or expired token" but I know it isn't because I've only just been given it, so it must be something wrong with my data packet.
The code I am using to try and generate this is:
// testing bit
$oauth = array(
'oauth_consumer_key'=>'cChZNFj6T5R0TigYB9yd1w',
'oauth_nonce'=>'a9900fe68e2573b27a37f10fbad6a755',
'oauth_signature_method'=>'HMAC-SHA1',
'oauth_timestamp'=>'1318467427',
'oauth_token'=>'NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0',
'oauth_version'=>'1.0'
);
$this->o_secret = 'LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE';
$this->c_secret = 'kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw';
ksort($oauth);
$string = rawurlencode(http_build_query($oauth));
$new_string = strtoupper($http_method).'&'.rawurlencode($main_url[0]).'&'.$string;
// The request_token request doesn't need a o_secret because it doesn't have one!
$sign_key = strstr($fullurl,'request_token') ? $this->c_secret.'&' : $this->c_secret.'&'.$this->o_secret;
echo urlencode(base64_encode(hash_hmac('sha1',$new_string,$sign_key,true)));exit;
And I'm assuming that the keys listed on this page are in fact correct: https://dev.twitter.com/docs/auth/creating-signature. So in that case the signature should be 39cipBtIOHEEnybAR4sATQTpl2I%3D.
If you can spot what I'm missing that would be great.
Your consumer secret and token secret are incorrect for the page you reference. If you look further up the page you can see that they should be:
Consumer secret: L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg
Token secret: veNRnAWe6inFuo8o2u8SLLZLjolYDmDP7SzL0YfYI
Also in Step 3 you need to include the oauth_verifier in the list of parameters when calculating your signature base string.
I'm not familiar with PHP so I haven't checked your code to calculate the signature.
This code has now worked - I will tidy it up from there :)
// This function is to help work out step 3 in the process and why it is failing
public function testSignature(){
// testing bit
$oauth = array(
'oauth_consumer_key'=>'cChZNFj6T5R0TigYB9yd1w',
'oauth_nonce'=>'a9900fe68e2573b27a37f10fbad6a755',
'oauth_signature_method'=>'HMAC-SHA1',
'oauth_timestamp'=>'1318467427',
'oauth_token'=>'NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0',
'oauth_version'=>'1.0'
);
$this->o_secret = 'LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE';
$this->c_secret = 'kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw';
ksort($oauth);
$string = http_build_query($oauth);
$new_string = strtoupper($http_method).'&'.$main_url[0].'&'.$string;
$new_string = 'POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521';
// The request_token request doesn't need a o_secret because it doesn't have one!
$sign_key = $this->c_secret.'&'.$this->o_secret;
echo 'Should be: tnnArxj06cWHq44gCs1OSKk/jLY=<br>';
echo 'We get: '.base64_encode(hash_hmac('sha1',$new_string,$sign_key,true));
exit;
}
you want to access token from twitter and sign in implementation you can see in this example.
1) http://www.codexworld.com/login-with-twitter-using-php/
and this one for timeline tweets
2) http://www.codexworld.com/create-custom-twitter-widget-using-php/
may be this help you .