I have two one question about the Fat Free Framework.
First of all, how can i use multiple parameters(tokens in fat free framework) in a GET request?
Or, is there only 1 token possible per REST GET request, and should one handle additional
arguments as a regular GET request, for example:
domain/rest/somedata/5231?param1=value1¶m2=value2
where the ?param1=value1¶m2=value2 should be 'manually' parsed, not by a framework?
Is it at all possible to build a RESTful API with Fat Free Framework and also have some area's or routes needing authentication? if so, how?
I just stumbled upon this related question: REST API Best practices: Where to put parameters?
[edit]: i've found out that it is indeed possible to have authentication with fat free framework using several methods. However, they seem not very well documented (at least not on their github wiki).
[edit2] Since it's only very basic authentication, for now i'm using this:
function beforeRoute($f3,$params) {
$url = $params[0];
$parsed_key = parse_str(parse_url($url, PHP_URL_QUERY));
if (isset($apikey)){
// check if apikey is in database
$authenticated = false;
foreach(R::find('apikey') as $key_bean) {
if($key_bean->key == $apikey) {
$authenticated = true;
break;
}
}
if($authenticated == false) $f3->error(403);
} else {
$f3->error(403);
}
}
I'm looking for documentation on the basic http authentication method!
The auth class always authenticates you against a mapper. Feel free to use F3's Jig, Mongo or SQL.
$db = new DB\SQL('mysql:host=localhost;dbname=mydb', 'dbuser', '1234');
$mapper = new DB\SQL\Mapper($db, 'users');
$auth = new Auth($mapper, array('id'=>'username','pw'=>'password'));
if($auth->basic())
return true;
password and username are field names in the database. id and pw are internal used by the auth class. I recommend checking the auth class code and the unit tests in the dev branch on Github.
An simple example would be something like...
Username: admin, Password: 123
// Create users table using Jig.
$db = new \DB\Jig('data/');
$users = array(
0 => array('username' => 'admin', 'password' => '202cb962ac59075b964b07152d234b70'),
);
$db->write('users', $users);
$db_mapper = new \DB\Jig\Mapper($db, 'users');
$auth = new \Auth($db_mapper, array('id' => 'username', 'pw' => 'password'));
// Callback function because of md5 stored password.
function chkauth($pw) {
return md5($pw);
}
$auth->basic('chkauth');
Related
Good day,
Im trying to develop a web platform using Slim framework. I've done it in MVC way. some of my APIs are used to render the view and some is just built to get data from the db.
for example :
$app->get('/api/getListAdmin', function () use ($app) {
$data = ...//code to get admins' list
echo json_encode($data);
})->name("getListAdmin");
$app->get('/adminpage', function () use ($app) {
// **** METHOD 1 :// get the data using file_get_contents
$result = file_get_contents(APP_ROOT.'api/getListAdmin');
// or
// **** METHOD 2 :// get data using router
$route = $this->app->router->getNamedRoute('getListAdmin');
$result = $route->dispatch();
$result = json_decode($result);
$app->render('adminpage.php', array(
'data' => $result
));
});
I'm trying to call the db handling Api '/api/getListAdmin' within the view related apis '/adminpage'.
based on solutions i have found in the web i tried method 1 and 2 but:
method 1 (using file_get_contents) take a long time to get the data (few seconds on my local environment).
method 2 (router->getNamedRoute->dispatch) seems dosnt work becuz it will render the result in the view even if i use $result = $route->dispatch(); to store the result in a variable but seems dispatch method still render to result to the screen.
I tried to create a new slim app only for db related API but still calling one of them takes quite long time 2 to 3 seconds.
Really appreciate it if some one can help me on what i'm doing wrong or what is the right way to get data from another api.
Thanks
Method 1
This could be another method, creating a Service layer, where redundant code is deleted:
class Api {
function getListAdmin() {
$admins = array("admin1", "admin2", "admin3"); //Retrieve your magic data
return $admins;
}
}
$app->get('/api/getListAdmin', function () use ($app) {
$api = new Api();
$admins = $api->getListAdmin();
echo json_encode($admins);
})->name("getListAdmin");
$app->get('/adminpage', function () use ($app) {
$api = new Api();
$admins = $api->getListAdmin();
$app->render('adminpage.php', array(
'data' => $admins
));
});
Method 2
If you are ok with an overkill method, you could use Httpful:
$app->get('/adminpage', function () use ($app) {
$result = \Httpful\Request::get(APP_ROOT.'api/getListAdmin')->send();
//No need to decode if there is the JSON Content-Type in the response
$result = json_decode($result);
$app->render('adminpage.php', array(
'data' => $result
));
});
I have two cakePHP apps on 2 different servers. One app is required to get data from the first one; I have succeeded to put the Restful architecture in place but I failed to implement an authentication procedure to the requests the server sends. I need to authenticate to secure the data. I have looked around on the web but can't seem to get it working. Can anyone point me to a resource / tutorial that explains this in detail.
What I would ultimately need would be a way to authenticate my server every time it sends a request to the other server. Any help would be appreciated.
I finally got it to work after some research; indeed one of the solutions is OAuth. In case you are facing the same problem, I can advise you this Plugin made for CakePHP.
In details what I did was put the OAuth Plugin into my API Server and I used it like so for my restful controller:
class RestObjectController extends AppController {
public $components = array('RequestHandler', 'OAuth.OAuth');
public $layout = FALSE;
public function token() {
$this->autoRender = false;
try {
$this->OAuth->grantAccessToken();
} catch (OAuth2ServerException $e) {
$e->sendHttpResponse();
}
}
public function index() {
$objects = $this->Object->find('all');
$this->set(array(
'objects' => $objects,
'_serialize' => array('objects')
));
}
The function RestObject.token() is what I would call to get an Access token which will be used to give me access to the Resources in my controller. (Note that by declaring OAuth in my controller components, all the resources within my controller will need an access token to be accessible).
So on the client Server I would get an access token in the following way:
public function acquireAccessToken(){
$this->autoRender = FALSE;
App::uses('HttpSocket', 'Network/Http');
$link = API_SERVER."rest_objects/token";
$data = array(
'grant_type' => 'client_credentials',
'client_id' => 'xxxx',
'client_secret' => 'xxxx'
);
$response = $httpSocket->post($link, $data);
if($response->code == 200){
$data = json_decode($response->body, true);
return $data['access_token'];
}
return FALSE;
}
This assumes that you have clients already set up as explained in the Plugin Doc (replace xxxx by the real values for the client credentials). Once I have my access token, all I have to do is use it as follows:
public function test(){
$this->layout = FALSE;
App::uses('HttpSocket', 'Network/Http');
$httpSocket = new HttpSocket();
if($access_token = $this->acquireAccessToken()){
$link = API_SERVER."rest_objects.json"; //For the index as e.g.
$data = array('access_token' => $access_token);
$response = $httpSocket->get($link, $data);
}
}
And here you have it! So start by reading the Oauth Specification to understand the Protocol (in particular the Obtaining Authorization part), see which protocol (can be different from the one I used) applies and adapt to your case by using the Plugin
Tutorial Here
I've been Googling for quite some time now for some ideas or a guide on how to integrate OAuth (v1.0 & v2.0) alongside the standard Laravel 4 Eloquent authentication driver.
Essentially, I'd like to be able for site visitors to create an account via their existing Google, Facebook, or Twitter accounts, or via the standard email/password authentication. Certain user information such as email, first and last names, and avatar are important for me to have stored in a unified users table.
So far the projects I've looked at seem to support only OAuth and do away with the standard method. These projects include: eloquent-oauth, and oauth-4-laravel.
At this point, I might just roll my own solution, but I'm hoping some of you guys might have better advice for me!
TL;DR: I'm stuck at trying to find a simple and secure way to allow OAuth and standard Eloquent user authentication in Laravel. Halp.
I think the easiest way would be to use this service provider that you mention "artdarek/oauth-4-laravel" and then store the values as usual and log them in.
/**
* Login user with facebook
*
* #return void
*/
public function loginWithFacebook() {
// get data from input
$code = Input::get( 'code' );
// get fb service
$fb = OAuth::consumer( 'Facebook' );
// check if code is valid
// if code is provided get user data and sign in
if ( !empty( $code ) ) {
// This was a callback request from facebook, get the token
$token = $fb->requestAccessToken( $code );
// Send a request with it
$result = json_decode( $fb->request( '/me' ), true );
// store new user or login if user exists
$validator = Validator::make($result, array(
'email'=>'required|email|unique:users'
));
if ($validator->passes()) {
# Save user in DB
$user = new User;
$user->username = $result['name'];
$user->email = $result['email'];
$user->save();
}else {
$user = User::findByUsernameOrFail($result['name']);
}
Auth::login($user);
}
// if not ask for permission first
else {
// get fb authorization
$url = $fb->getAuthorizationUri();
// return to facebook login url
return Redirect::to( (string)$url );
}
}
I have created one application in YiiFramework which has two functionalities.
1. Login to google
For login to google, I have followed the tutorial on below website.
Tutorial : https://github.com/Nodge/yii-eauth
Tutorial Demo : http://nodge.ru/yii-eauth/demo/login
2 Get calendar using Zend_Gdata Library
Tutorial : http://www.bcits.co.in/googlecalendar/index.php/site/install
Tutorial Demo : http://www.bcits.co.in/googlecalendar/index.php/site/page?view=about
[1st Step] I get successfully login to my application using yii-eauth.
[2nd Step] when I need to use calendar, I am giving hard coded gmail Id and password.
I am accessing calendar in this way.
<?php
$user = 'your gmail username';
$pass ='your gmail password';
Yii::app()->CALENDAR->login($user, $pass);
?>
login() in googlecalendar.php file.
public function login($user, $pass) {
$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);// It uses hard-coded gmail/password to get login again
$calenderlist = $this->outputCalendarList($client);
$events = $this->outputCalendar($client);
$calendardate = $this->outputCalendarByDateRange($client, $startDate = '2011-05-01', $endDate = '2011-06-01');
.........
}
Does Zend_Gdata library contain any function which automatically gets calendar of current user without again logging in(hard-coded here).
Stuck with this. Appreciate helps. Thanks
From my understanding, Zend_Gdata_ClientLogin sets some parameters for $client which is the object returned. See the following excerpt from that function:
if ($loginToken || $loginCaptcha) {
if ($loginToken && $loginCaptcha) {
$client->setParameterPost('logintoken', (string) $loginToken);
$client->setParameterPost('logincaptcha', (string) $loginCaptcha);
} else {
require_once 'Zend/Gdata/App/AuthException.php';
throw new Zend_Gdata_App_AuthException(
'Please provide both a token ID and a user\'s response ' .
'to the CAPTCHA challenge.');
}
}
What you could do is store that token or that $client object (which is an instance of Zend_Gdata_HttpClient). Pretty much all of the Zend_Gdata components accept a $client argument.
Check out the __construct() method for Zend_Gdata_Calendar:
So anyway, you would want something similar to this logic (sorry I'm not familiar with Yii):
$client = Yii::app()->getClient();
if (!$client) {
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
Yii::app()->setClient($client);
}
Of course, you would have to then define that getClient() method somehow.
Hope this helps!
I want to read all birthdays of the friends from current user. I use the new Graph API of facebook. I request the authorization of the permissions (read_friendslist and friends_birthday) based on Facebooks insights example and php-sdk example. For reading the friendslist and the user details I used the Graph API with Facebook PHP SDK.
The upcoming code snippets are a short self contained correct example of my approach. If I try to use my app it requests login, then asks for permissions and then fails in printing all my friends due to the fact that no session is available. What's wrong here?
First is the birthday.php which is used by the following index.php, I removed some boilerplate code or code I think it's not causing this problem (identified by [...]). You can find the complete code on the end of this question.
<?php
function get_birthday_of_friends() {
$fbconfig['appid' ] = "MY_APP_ID";
$fbconfig['secret'] = "MY_APP_SECRET";
try{
include_once "facebook/src/facebook.php";
}
catch(Exception $o){
// [...] log error
}
// Create our Application instance.
$facebook = new Facebook(array(
'appId' => $fbconfig['appid'],
'secret' => $fbconfig['secret'],
'cookie' => true,
));
$session = $facebook->getSession();
$fbme = null;
// Session based graph API call.
if ($session) {
// [...] return birthdays
} else {
echo "No session found";
}
}
?>
The required lib.php is identically with the insights example.
<?php
// [...] Include and define app-id etc.
function get_access_token($base_url) {
if (isset($_REQUEST['access_token'])) {
return $_REQUEST['access_token'];
}
$params = array();
$params['client_id'] = APP_ID;
$params['redirect_uri'] = $base_url;
if (!isset($_REQUEST['code'])) {
$params['scope'] = 'read_friendlists, friends_birthday';
$url = FacebookMethods::getGraphApiUrl('oauth/authorize', $params);
throw new RedirectionException($url);
} else {
$params['client_secret'] = APP_SECRET;
$params['code'] = $_REQUEST['code'];
$url = FacebookMethods::getGraphApiUrl('oauth/access_token');
$response = FacebookMethods::fetchUrl($url, $params);
$response = strstr($response, 'access_token=');
$result = substr($response, 13);
$pos = strpos($result, '&');
if ($pos !== false) {
$result = substr($result, 0, $pos);
}
return $result;
}
}
// [...] Call get_access_token() and get_birthday_of_friends()!
?>
Can you help me with that? I added the whole source code on pastebin.com if this helps you to identify my problem. Source code on pastebin.com for "index.php" and "birthday.php".
Thank you in advance!
I am not sure if the method that you are using is deprecated or not, but I know it's the old way and you should try with the new one in order to get the auth token.
Take a look at this link:
http://developers.facebook.com/docs/authentication/signed_request/
In a glance, you have to:
Get the signed_request parameter from $_REQUEST.
Use the sample function provided in
the link to decode it Once you decode
it, you will have an array in which
there is a parameter called
oauth_token.
With this parameter, you can start
making calls to the Graph by
appending it to the URL e.g.
*https://graph.facebook.com/PROFILE_ID/pictures/?access_token=OAUTH_TOKEN*
Make sure that you have Oauth 2.0 for Canvas enabled into the Configuration settings of your app (Advanced tab).
I think in some browsers there's a prblem with third party cookies. Are you testing in Safari? And also, try to add permissions to the loginUrl - it's a bit more simple than adding and requesting the permissions with oauth.
If no session is available, I had to redirect to the login page and require the extended permissions with the parameters. This did the trick to me, thanks to manuelpedrera for helping me out.
$facebook->getLoginUrl(array('req_perms' => 'read_friendlists, [...]'));