I am working in building a restful api using php & slim for my app backend and also we have a web version but my team use pure php with the web suit , we work separately . it is just the first time that i have the backend responsibility I have a miss understanding about how i can handle the authentication in a secure and professional way i have read this article but i need a detailed way how to implement it in php & slim and extend it to the web team so to use the same authentication technic .
this is how the log in / sign up code that i have used :
help me to improve it :
$app->post('/api/create_user', function( $request , $response , $args ){
require('../config.php');
$email = $_POST['email'];
$qry= "select * from user where email ='". $email."'";
$result=$mysqli->query($qry);
if(mysqli_num_rows($result)>0){
$user = new stdClass();
$user->status=0;
$user->error=" the email is registered ";
$result = new stdClass();
$result->result=$user;
}
else {
$password = md5($_POST['password']);
$image=$_FILES['image']['name'];
$email=$_POST['email'] ;
$nickname =$_POST['nickname'];
$birthDay=$_POST['birthdate'];
$insert_req="INSERT INTO user VALUES ('', '$email', '$password','$nickname')";
$insert_user_result=$mysqli->query($insert_req);
if ($insert_user_result) {
$user = new stdClass();
$user->status=1;
$result = new stdClass();
$result->result=$user;}
else {$user = new stdClass();
$user->status=2;
$user->error=mysql_error();
$result = new stdClass();
$result->result=$user;}
}
if (isset($result)){
header('Content-type: application/json');
echo json_encode($result);}
});
?>
<?php
$app->post('/api/login', function( $request , $response , $args ){
require('../config.php');
$email =$_POST['email'];
$password = md5($_POST['password']);
$findemail_qry= "select user_id from user where email ='". $email."'";
$findemail_result =$mysqli->query($findemail_qry);
if(mysqli_num_rows($findemail_result)>0)
{
$login_qry="select user_id from user where email ='". $email."'AND password ='".$password."'";
$login_result =$mysqli->query($login_qry);
if(mysqli_num_rows($login_result)>0)
{
$data =mysqli_fetch_assoc ($login_result);
$user_id=$data['user_id'];
$user = new stdClass();
$user->status=1;
$user->user_id=$user_id;
$result = new stdClass();
$result->result=$user;}
else
{$user = new stdClass();
$user->status=2;
$user->error="wrong password";
$result = new stdClass();
$result->result=$user; }
}
else
{$user = new stdClass();
$user->status=0;
$user->error=" this email not registered ";
$result = new stdClass();
$result->result=$user;}
if (isset($result)){
header('Content-type: application/json');
echo json_encode($result);
}
});
?>
You can use JWT in your slim application as your authntication layer for Your API
You can use this library to implement it
Slim JWT
In a simple way you can use something like this
Try to use Basic authorization to send user name and password
Then You will generate a new JWT Token ,That will used in all others API
<?php
use \Firebase\JWT\JWT;
use \Slim\Middleware\HttpBasicAuthentication\AuthenticatorInterface;
require '../vendor/autoload.php';
$app = new \Slim\App;
class RandomAuthenticator implements AuthenticatorInterface {
public function __invoke(array $arguments) {
//validation for user and password
$Password=$arguments['password'];
$user=$arguments['user'];
if(($Password=="admin") &&($user=="admin") ){
return true;
}
else{
return false ;
}
}}
//add http basic middleware for login route
$app->add(new \Slim\Middleware\HttpBasicAuthentication([
"path" => "/login",
"realm" => "Protected",
"authenticator" => new RandomAuthenticator()
]));
$app->post("/login", function ($request, $response, $arguments) {
//generate JWT token
$now = new DateTime();
$future = new DateTime("now +20 minutes");
$server = $request->getServerParams();
$payload = [
"iat" => $now->getTimeStamp(),
"exp" => $future->getTimeStamp(),
"sub" => $server["PHP_AUTH_USER"],
];
$secret = "TOURSECERTKEY";
$token = JWT::encode($payload, $secret, "HS512");
$data["status"] = "ok";
$data["token"] = $token;
return $response->withStatus(201)
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
});
//Add jWT token Authorization middleware for all API
$app->add(new \Slim\Middleware\JwtAuthentication([
"path" => ["/"],
"passthrough" => ["/login"],
"secret" => "TOURSECERTKEY",
"error" => function ($request, $response, $arguments) {
$data["status"] = "error";
$data["message"] = $arguments["message"];
return $response
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
]));
Related
I am using dialogflow php client library for accessing v2 rest api of dialogflow. I can call detectIntent and other stuffs and it is working. But some times i should need to search for a specific trainingPhrase and if not present then add new training phrase for detected intent. How could i do this using php client library? I am tired of searching on this. Please help me. Any answers will be appreciated. The function I'm using to getIntent with the some text is as below,
function detect_intent_texts($projectId, $text, $sessionId, $languageCode = 'en-US')
{
global $common;
// new session
$test = array('credentials' => 'key_file.json');
$sessionsClient = new SessionsClient($test);
$session = $sessionsClient->sessionName($projectId, $sessionId ?: uniqid());
//printf('Session path: %s' . PHP_EOL, $session);
// create text input
$textInput = new TextInput();
$textInput->setText($text);
$textInput->setLanguageCode($languageCode);
// create query input
$queryInput = new QueryInput();
$queryInput->setText($textInput);
// get response and relevant info
$response = $sessionsClient->detectIntent($session, $queryInput);
$queryResult = $response->getQueryResult();
$queryText = $queryResult->getQueryText();
$intent = $queryResult->getIntent();
$displayName = $intent->getDisplayName();
$common->write_to_log("intent displayName : ".$displayName);
if($displayName == "Default Fallback Intent")
{
$result = json_encode(array("result"=>false));
$common->write_to_log("No matching intent found");
}
else
{
$confidence = $queryResult->getIntentDetectionConfidence();
$fulfilmentText = $queryResult->getFulfillmentText();
$common->write_to_log("intent response : ".$fulfilmentText);
$result = json_encode(array("result"=>true,"message"=>$fulfilmentText));
}
echo $result;
$sessionsClient->close();
}
I'm using this composer package https://github.com/basvandorst/StravaPHP
The OAUTH is working fine and its generating me the JSON with the access token and user id, etc..
But whenever I try to use other function it returns me 404 not found.
Output is this :
{"token_type":"Bearer","access_token":"077058e0c800881c72a4b10a04a520d5898d4e3e","athlete":{"id":35670467,"username":"amir_do","resource_state":2,"firstname":"Amir","lastname":"Do","city":null,"state":null,"country":null,"sex":"M","premium":false,"summit":false,"created_at":"2018-10-13T13:55:41Z","updated_at":"2018-10-13T13:56:25Z","badge_type_id":0,"profile_medium":"https://lh5.googleusercontent.com/-ku6v9lKNgYY/AAAAAAAAAAI/AAAAAAAAAAA/ABtNlbASj8KhClhwnVYVqRrEG2oiYzWPbA/mo/photo.jpg","profile":"https://lh5.googleusercontent.com/-ku6v9lKNgYY/AAAAAAAAAAI/AAAAAAAAAAA/ABtNlbASj8KhClhwnVYVqRrEG2oiYzWPbA/mo/photo.jpg","friend":null,"follower":null,"email":"goncalomaia97#gmail.com"}}
35670467
Client error: `GET https://www.strava.com/api/athletes/35670467/stats?access_token=077058e0c800881c72a4b10a04a520d5898d4e3e` resulted in a `404 Not Found` response: {"message":"Record Not Found","errors":[{"resource":"resource","field":"path","code":"invalid"}]}
And this is my current callback.php page code:
<?php
include 'vendor/autoload.php';
use Strava\API\Client;
use Strava\API\Exception;
use Strava\API\Service\REST;
session_start();
$client = new GuzzleHttp\Client();
global $connect;
require_once("configs/database.php");
$connect = new mysqli($config['database']['host'],$config['database']['user'],$config['database']['pass'],$config['database']['db']);
$code = $_GET['code'];
$state = $_GET['state'];
$scope = $_GET['scope'];
$user = $_SESSION['username'];
$check = $connect->query("SELECT * FROM users WHERE email = '$user'");
$fetch = $check->fetch_array(MYSQLI_ASSOC);
$apix = $fetch['api'];
$api_secretx = $fetch['api_secret'];
$client = new GuzzleHttp\Client();
$data = [
"client_id" => $apix,
"client_secret" => $api_secretx,
"code" => $code
];
$result = $client->post('https://www.strava.com/oauth/token', ['json' => $data]);
print "<pre>";
print_r( $result->getBody()->getContents() );
print "</pre>";
$bodyb = $result->getBody();
$varx = json_decode((string) $bodyb, true);
$token = $varx['access_token'];
$id = $varx['athlete']['id'];
$_SESSION['token'] = $token;
printf($id);
try {
// REST adapter (We use `Guzzle` in this project)
$adapter = new \GuzzleHttp\Client(['base_uri' => 'https://www.strava.com/api/v3']);
// Service to use (Service\Stub is also available for test purposes)
$service = new \Strava\API\Service\REST($token, $adapter);
// Receive the athlete!
$client = new Client($service);
$athlete = $client->getAthleteStats($id);
print_r($athlete);
} catch(Exception $e) {
print $e->getMessage();
}
$adapter = new \GuzzleHttp\Client(['base_uri' => 'https://www.strava.com/api/v3']);
Change that to this (It should be trailing) :
$adapter = new \GuzzleHttp\Client(['base_uri' => 'https://www.strava.com/api/v3/']);
I am trying to upload using client on twilio and trying buy a twilio number.
Also, I need to get a dynamic voice URL in order to record a conference call dynamically.
<?php
require_once 'vendor/autoload.php'; // Loads the library
use Twilio\Rest\Client;
// Your Account Sid and Auth Token from twilio.com/user/account
$sid = "*********************";
$token = "*******************";
$client = new Client($sid, $token);
$numbers = $client->availablePhoneNumbers('US')->local->read(
array("areaCode" => "424")
);
$twilioNumber = $numbers[0]->phoneNumber;
$newNumber = $client->incomingPhoneNumbers->create(
[
"voiceUrl" => "host url",
"voiceMethod" => "GET"
]
);
if ($newNumber) {
return $twilioNumber;
} else {
return 0;
}
//
In the voiceUrl parameter i am passing a conference call connect code hosted link but its not getting updated to twilio account dynamically.
You can use like
require 'Services/Twilio.php';
$account_id = ACCOUNT_SID;
$auth_token = AUTH_TOKEN;
$number = $_REQUEST['id'];
$client = new Services_Twilio($account_id, $auth_token);
try{
$number= $client->account->incoming_phone_numbers->create(array('PhoneNumber' =>'+'.$number));
$number_sid=$number->sid;
$number1 = $client->account->incoming_phone_numbers->get($number_sid);
$number1->update(array("VoiceUrl" => "http://11.11.1.111/test/twilio_call_response.php","SmsUrl"=>"http://11.11.1.111/test/incomingsms.php","VoiceFallbackUrl"=>"http://11.11.1.111/test/fall_backurl.php"));
$phone_number=str_replace('+','',$numbers);
$allocate='1';
}catch(Exception $e){
echo $err = "Error purchasing number: {$e->getMessage()}";
}
echo $phone_number;
When I use "this solution" I get a blank contacts array.
I'm using "google-api-php-client-0.6.7" with a serviceAccount.php into the examples/contacts folder, and a Google_ContactsService into src/contrib folder.
I have configured the Google Apis Access, with OAUTH 2 as Server Account. I have the p12 file, a client id and a cliend mail address. The project name is "Google Contacts Sample".
serviceAccount.php:
<?php
require_once '../../src/Google_Client.php';
require_once '../../src/contrib/Google_ContactsService.php';
const CLIENT_ID = 'xxxxxxxxxxxxx.apps.googleusercontent.com';
const SERVICE_ACCOUNT_NAME = 'xxxxxxxxxxxxx#developer.gserviceaccount.com';
const KEY_FILE = '/absolute_path/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-privatekey.p12';
$client = new Google_Client();
$client->setApplicationName("Google Contacts Sample");
session_start();
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new Google_AssertionCredentials(SERVICE_ACCOUNT_NAME, array('https://www.googleapis.com/auth/contacts'), $key));
$client->setClientId(CLIENT_ID);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$token = $client->getAccessToken();
$service = new Google_ContactsService($client);
$result = $service->all();
print '<h2>Contacts Result:</h2><pre>' . print_r($result, true) . '</pre>';
Google_ContactsService.php:
<?php
class Google_ContactsService
{
const SCOPE = "https://www.google.com/m8/feeds";
/**
* #var Google_Client
*/
private $client;
public function __construct($pClient)
{
$this->client = $pClient;
$this->client->setScopes(self::SCOPE);
}
public function all()
{
$result = $this->execute('default/full?max-results=999');
$contacts = array();
foreach($result["feed"]["entry"] as $entry)
{
if(!isset($entry['gd$email']))
$entry['gd$email'] = array();
if(!isset($entry['gd$phoneNumber'])||empty($entry['gd$phoneNumber']))
continue;
$phones = array();
$emails = array();
foreach($entry['gd$phoneNumber'] as $phone)
{
$phone['$t'] = preg_replace('/\+33/', "0", $phone['$t']);
$phone['$t'] = preg_replace('/\-/', '', $phone['$t']);
$phones[] = $phone['$t'];
}
foreach($entry['gd$email'] as $email)
{
$emails[] = $email['address'];
}
$contacts[] = array(
"fullName"=>utf8_decode($entry['title']['$t']),
"phones"=>$phones,
"emails"=>$emails
);
}
return $contacts;
}
private function execute($pUrl)
{
$oauth = Google_Client::$auth;
$request = new Google_HttpRequest("https://www.google.com/m8/feeds/contacts/".$pUrl."&alt=json");
$oauth->sign($request);
$io = Google_Client::$io;
$result_json = $io->makeRequest($request)->getResponseBody();
$result = json_decode($result_json, true);
return $result;
}
}
When I go to "http://server.com/packs/googleapi/examples/contacts/serviceAccount.php" I don't see any contact.
The function Execute return empty.
What can I do?
Thanks.
I realize this is old so you have probably moved on but for other's finding this I believe the reason you don't see any contacts is that you are not delegating to a specific user. Not counting shared contacts on Google Apps Premier and Education Editions domains, contacts are private to that user.
I would change this line
$client->setAssertionCredentials(new Google_AssertionCredentials(SERVICE_ACCOUNT_NAME, array('https://www.googleapis.com/auth/contacts'), $key));
to be more like this
$auth = new Google_AssertionCredentials(SERVICE_ACCOUNT_NAME, array('https://www.google.com/m8/feeds'), $key);
$auth->sub = 'user#domain.com'; //whoever's contacts you want to see
$client->setAssertionCredentials($auth);
You could keep the first two lines together if you look at Google_AssertionCredentials method signature, but I think this makes it more explicit. Depending on what you are trying to achieve, user#domain.com will likely be a variable that is set from some kind of input, database, etc.
How do I use this function?
I have a userid and a group id.
The error message I get when I try to add my fields has to do with the Google_Member instance. How would I use this in my PHP code?
BTW it is from the Google Apps API
/**
* Add user to the specified group. (members.insert)
*
* #param string $groupKey Email or immutable Id of the group
* #param Google_Member $postBody
* #param array $optParams Optional parameters.
* #return Google_Member
*/
public function insert($groupKey, Google_Member $postBody, $optParams = array()) {
$params = array('groupKey' => $groupKey, 'postBody' => $postBody);
$params = array_merge($params, $optParams);
$data = $this->__call('insert', array($params));
if ($this->useObjects()) {
return new Google_Member($data);
} else {
return $data;
}
}
Follow the instructions listed here to setup the application in Google Console and to enable Domain Delegation of Authority.
http://jamespeckham.com/wordpress/?p=9 (Thank you JDPeckham)
Download the client from: https://code.google.com/p/google-api-php-client/downloads/list
Here is my working code:
require_once "google-api-php-client/src/Google_Client.php";
require_once "google-api-php-client/src/contrib/Google_DirectoryService.php";
require_once "google-api-php-client/src/contrib/Google_Oauth2Service.php";
session_start();
const GROUP_SCOPE = 'https://www.googleapis.com/auth/admin.directory.group';
const SERVICE_ACCOUNT_EMAIL = '.....#developer.gserviceaccount.com';
const SERVICE_ACCOUNT_PKCS12_FILE_PATH = '/path/to/...privatekey.p12';
const CLIENT_ID = '....apps.googleusercontent.com';
$userEmail = 'email-address-with-admin-rights#domain.com';
$key = file_get_contents(SERVICE_ACCOUNT_PKCS12_FILE_PATH);
$auth = new Google_AssertionCredentials(SERVICE_ACCOUNT_EMAIL, array(GROUP_SCOPE), $key, 'notasecret', 'http://oauth.net/grant_type/jwt/1.0/bearer', $userEmail);
$client = new Google_Client();
$client->setClientId(CLIENT_ID); // from API console
$client->setApplicationName("Project Name from API Console");
$client->setUseObjects(true);
$client->setAssertionCredentials($auth);
$member = new Google_Member(array('email' => 'abc#testing.com',
'kind' => 'admin#directory#member',
'role' => 'MEMBER',
'type' => 'USER'));
$service = new Google_DirectoryService($client);
$results = $service->members->insert('mailing-list-name#domain.com', $member);
print '<h2>Response Result:</h2><pre>' . print_r($results, true) . '</pre>';
require_once $_SERVER['DOCUMENT_ROOT'] . '/../vendor/autoload.php';
$updateName = $_POST["name"];
$updateEmail = $_POST["email"];
//USING A SERVICE ACCOUNT TO CALL GOOGLE CLIENT
putenv('GOOGLE_APPLICATION_CREDENTIALS=/home/myserver/mywebsite/credentialsfile.json');
$client = new Google\Client();
// MY ACCOUNT DATA HERE
$client_id = 'clientid';
$service_account_name = 'serviceaccountemailhere'; //Email Address
$key_file_location = '/home/myserver/mywebsite/mykeyfile.json'; //key.p12
$agencyAdminGroupKey = 'emailforGroupKey#gmial.com'; //agency admins group key
$memberKey = $updateEmail; //$memberemail
$domain = 'yourwebsite.com';
if (getenv('GOOGLE_APPLICATION_CREDENTIALS')) {
// use the application default credentials
$client->useApplicationDefaultCredentials();
} else {
echo missingServiceAccountDetailsWarning();
return;
}
// set the scope(s) that will be used
//$client->setScopes(array('https://www.googleapis.com/auth/admin.directory.group'));
$client->setScopes(array('https://www.googleapis.com/auth/admin.directory.group'));
// this is needed only if you need to perform
// domain-wide admin actions, and this must be
// an admin account on the domain; it is not
// necessary in your example but provided for others
$client->setSubject('yourgoogleaccountemail#domain.com');
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey("paste-your-developer-key");
$service = new Google_Service_Directory($client);
$member = new Google_Service_Directory_Member( array('email' => $updateEmail,
'kind' => 'admin#directory#member',
'role' => 'MEMBER',
'type' => 'USER',
"deliverySettings" => 'DAILY'));
//GET request to google groups server
// $results = $service->members->listMembers($groupKey);
$results = $service->members->insert($agencyAdminGroupKey, $member);
Here are some useful links:
https://github.com/googleapis/google-api-php-client
https://developers.google.com/admin-sdk/directory/v1/quickstart/php
https://developers.google.com/resources/api-libraries/documentation/admin/directory_v1/php/latest/class-Google_Service_Directory_Groups.html
https://developers.google.com/admin-sdk/directory/reference/rest/v1/members