Yii OAuth Implementation - php

Requiremen :- Yii, OAuth implemenation to authenticate and fetch user data.
I found out that there are two extensions. Eauth(support OAuth 2.0 and other social networking sites) and Eoauth(OAuth 1.0). Correct me If i am wrong.
I dont have to authenticate any social networking site. It's a different url from where I need to get the data.
Now i could successfully login and authenticate using "eoauth" extension but also I need to fetch information about the user. I don't find any function or way how to fetch data from url which lies under OAuth layer. Does Eauth or Eoauth supports fetching or it has to be custom coded ?
If this extensions does not do this then what is the other way I can authenticate and fetch data ?

Of course, Eauth supports fetching user's data.
Let's see on Eauth structure. We have directories /services, /custom_services and class EOAuthService. EOAuthService contains method makeSignedRequest(), that return the protected resource from third-party site.
So, this method we can call from our serviceClass, that extends EOAuthService. For example, class FacebookOAuthService in /services directory. The class contains protected method fetchAttributes(), it calls method makeSignedRequest($url) and get $info (in JSON) from third-party site (FB in our example). Properties of this object - it's our user's data.
What about /custom_services? The directory contains classes for tuning our "BaseServiceClass".
So, for example, CustomFacebookOAuthService extends FacebookOAuthService extends EOAuthService.
You need create your own class, which will make signed request for your third-party site and get proper response (in JSON, for example). Then fetch gotten info - and voila!
Of course, user must be authenticated by third-party site for fine auth on your application through oauth.

Though Old but You just need to use CURL request to the end URL and you will get your data. I guess those modules doesn't have the function to fetch a data. I hope this might help you. I have used in one of my code and It was successful
public function GetData($url){
$signatureMethod = new OAuthSignatureMethod_HMAC_SHA1();
$request = OAuthRequest::from_consumer_and_token($this->consumer,$this->token, 'GET', $url, array());
$request->sign_request($signatureMethod, $this->consumer, $this->token);
$fetchUrl = $request->to_url();
$response = Yii::app()->CURL->run($fetchUrl);
return json_decode($response);
}

Related

Use Laravel to consume an external Laravel API

I have two Laravel sites, a client and a server. The client connects to the server, which (among other things) provides a RESTful api for a database. While this setup may seem a bit convoluted and superfluous, it is necessary for the use-case.
How can I set up the client so that it uses the server's API to interact with resources?
For instance, the sever provides organisation models at an /organisations/{id} end point. If I wanted to display them all on the client, and provide a form for updating each organisation, is there a Laravel-esque way of doing this? Or is it something that'll end up being hand-rolled and hacky?
You have to use the http-client. Laravel provides already one, based on Guzzle.
So, in order to update something You have to create PUT route on Your Server and then just call it from Client like this:
$response = Http::put("https://YOUR.SERVER/organisations/$id", [
'name' => 'Steve',
'role' => 'Network Administrator',
]);
More info, You will find in Laravel Documentation
if you want to use the Laravel as a frontend client to consume a remote API it easy, a part the fact that you can consider the use of vue.js as your frontend in order to keep things simpler.
FRONTEND
Create the Laravel project as usual, the only difference is that you don't need to set up the database and migrations
You are going to use the normal MVC pattern here, so in your Frontend FlightController class, you will fetch the data like this.
getFlights()
{
$response = Http::get(env('API_URL') . '/flights')->json();
}
we can optionally install the package spatie/data-transfer-object
in order to convert your json data to DTO object like this:
getFlights()
{
$flights_data = Http::get(env('API_URL') . '/flights')->json();
$filghts = [];
foreach($flight_data as data)
$filghts->add(new \App\Models\Dto\FlightDto($data));
return view('flights.search-result', compact('filghts'));
}
the DTO class looks like this:
use Spatie\DataTransferObject\DataTransferObject;
class FlightDto extends DataTransferObject
{
/** #var integer|null */
public $id;
/** #var string|null */
public $flight_number;
}
The authentication is little bit tricky, refer to this question to see how you can create custom user provider.
BACKEND
Create a Laravel project, set up database and all your migrations
place all your routes in the default location api.php
Route::get('/trips', 'ApiTripsController#getFlights');
3- in the FlightsController do the following
public getFlights
{
return Flight::all() // where the Flight class is the Eloquent model
}
do not forget to provide a security layer to protect ressources from the server side

Laravel Restfull Api Security

to me what is needed to prevent outsiders. I just want to respond to requests from those places I have defined.
Example : allowed applications and url
com.x.app
com.y.app
--------- AND ---------
http://www.x.com
Is there an easy way to do this? Best regards!
You should explain what you want clearly. Basically, to do something like this you need to check the $_SERVER['HTTP_USER_AGENT'] attribute of the HTTP header that you are receiving and filter on Android or iPhone keywords.
The best way to build a RESTful API in Laravel is via the routes/api.php
When you add a route to this file, such as the following:
Route::get('/users/list', 'ApiController#userList');
This means when you go to yourwebsite.com/api/users.list, it will execute the given method in the given controller.
As far as authenticating you API users, you can store your users and their API keys in a database and authenticate them before they reach the method by using the magic construct method.
public function __construct() {
$inputKey = filter_input(INPUT_GET, 'key'); //filter input the way you want
if(!isCustomer($inputKey) { //validate api keys in your app somehow
die('Authentication Failure'); //kick the freebooters
}
}

Symfony token getCredentials returns null

I created a way to authenticate a user with API keys, thanks to a class A implementing the SimplePreAuthenticatorInterface interface. Everything works well (the user is successfully authenticated).
I'm trying to store the API keys, for a later use during the user's journey. To do so, inside the authenticate method of my class A, I return a PreAuthenticatedToken in which the credentials are my API keys.
The problem is : Inside a custom service, when I try to get the token credentials, I get null... I successfully get the API keys when I comment the line 76 of the PreAuthenticatedToken Symfony core class :
public function eraseCredentials()
{
parent::eraseCredentials();
//$this->credentials = null;
}
My questions are:
1) Why is the method eraseCredentials called whereas the user is authenticated? I thought this method was called during user's logging out...
2) What am I doing wrong? Is the PreAuthenticatedToken token the right place to store my API keys? How can I get them back from a custom service ?
Thanks for helping me. :)
PS : I'm a newbee on posting in Stackoverflow (and in English ^^). Sorry in advance for any mistakes.
I found another similar question but it has no helping response and I added some more precisions.
EDIT: The code of my custom service where I try to get the credentials is:
$token = $this->container->get("security.token_storage")->getToken();
if ($token !== null) {
$credentials = $token->getCredentials();
// $credentials is null here
}
EDIT 2: The return part in my code of my SimplePreAuthenticatorInterface::authenticateToken method :
return new PreAuthenticatedToken(
$user,
$apiKeys,
$providerKey,
$user->getRoles()
);
Ad 1. It depends on your AuthenticationProviderManager: this class accepts $eraseCredentials as second parameter - by default set to true (here).
That's why eraseCredentials method is being called on PreAuthenticatedToken $token during authenication (here).
Ad 2. Please check How to Authenticate Users with API Keys tutorial. You should create your custom ApiKeyAuthenticator class and add logic there.
According to your comment:
Note that authenticateMethod from tutorial is being called inside authenticate method (here). At that time token credentials are not erased yet and you can access them. For security reason they are erased after authentication (but this can also be changed / configured via security.yml file). If you need them later you can introduce custom token class and store API key there.

Properly implementing resource authorization for a RESTful API

My team has an API we wrote in PHP using the Slim Framework. It's being consumed by a web app and a third party mobile app.
We use the standard OAuth 2 workflow to provide access to our resources. We can see if someone is a sending a valid access token along with the API request and that part of the flow makes sense.
The stumbling block we're running into is how to most efficiently authorize access to a resource depending on the permissions of the user associated with the access token.
For the sake of simplicity let's say that we just want to ensure that the owner of the resource in question matches the owner of the access token. To me that seems like something that a route middleware would handle, for every request, before processing the request make sure that the resource owner ID matches that of the access token.
The problem in my mind is that resource permissions aren't necessarily consistent across all routes, a route isn't necessarily going to have an ID in the same section of the URI, it might not have an ID in the URI at all, etc. etc.
My current solution has been to have an authorization utility class that takes in an email and checks it against the user that's currently "logged in" (token owner).
class Authorization() {
checkResourcePermissions($email) {
if (loggedInUser->email == $email) {
return true;
}
}
}
Obviously this is a simplification, but what this means is that since a route middleware won't have the context of a request until that request goes through I will need to call this authorization method inside of every API route, responding with an error if necessary, etc. Our API is fairly large, essentially boiling this down to a large amount of copy and paste which always makes me very nervous.
What am I missing?
I'd suggest going the way using a 'normal' MiddleWare:
First, let's assume you have a class 'user', where you implement your logic to access various types of resources or has specific permissions, given only the $app. It can access the request and get any information from a the HTTP request necessary to identify a single user.
class User{
private $userid=false;
public function __construct($app){
$this->app=$app;
$users_mail=$this->app->request->post('email');
//SELECT user_id FROM USERSTABLE WHERE email = $users_mail
//$this->userid=user_id
}
public function ensureHasAccess($resourceID,$redirect='/noPermission'){
if(!/*some DB Query which returns true if this user may access the given $resourceID*/)
$this->app->redirect($redirect)
}
public function ensureHasRole($role) {
//some other permission checking, like ensureHasAccess();
}
public function ensureIsUser(){
//do Something
}
}
Next, you'll need a MiddleWare which is run before the route is dispatched, and creates an User-Object:
class UserPermissionMiddleware extends \Slim\Middleware{
public function call(){
$this->app->request->user = new User($app);
$this->next->call();
}
}
Then, simply add this Middleware:
$app->add(new UserPermissionMiddleware());
Now, you can modify every route to check the access to a resource, while the resource id (of course) still needs to be supplied by hand, according to the route-specific code:
$app->get('/resource/:id',function($resourceId) use ($app){
$app->request->user->ensureHasAccess($resourceId);
//deliver resource
});
If the user is not allowed to access this resource, the whole process is interrupted (Note that redirect() is implemented using Exceptions!) and another route is executed. You'll still need some code in every single Route, but if there's no consistent way to determine the resource to be acccessed, there'll be no way around this.
Hope this helps you so far. If you have any Questions, feel free to ask!

Show protected methods in SWAGGER (RESTLER 3)

Im making an API, and I really like the SWAGGER interface for methods, but all my API requests will need to be protected and verified by Basic Auth. So any of those protected methods or classes will be available for SWAGGER. Is there any way to show them ?
Placing the following in your index.php will enable listing of protected methods
use \Luracast\Restler\Resources;
Resources::$hideProtected = false;
Accessing Basic Auth protected api from swagger will work just fine. But authenticating and getting through basic auth will require some work done on the swagger ui side
I read this on the SWAGGER docs but.. I need to dynamically send user & password typed using SWAGGER UI input fields.. and then convert them for Basic Auth. So actually the question is how to add user&pwd fields into every SWAGGER request and set them to be sent via Basic Auth headers.
// add a new ApiKeyAuthorization when the api-key changes in the ui.
$('#input_apiKey').change(function() {
var key = $('#input_apiKey')[0].value;
if(key && key.trim() != "") {
window.authorizations.add("key", new ApiKeyAuthorization("api_key", key, "header"));
}
})

Categories