Dynamic callback url laravel - laravel

I tried to make my callback url dynamic because I'm configuring socialite in a multi auth system. I tried to use the socialiteproviders/manager as below:
$clientId = env($provider."_client_id");
$clientSecret = env($provider."_client_secret");
$redirectUrl = "the url i want";
$config = new \SocialiteProviders\Manager\Config($clientId,$clientSecret,$redirectUrl);
return Socialite::with($provider)->setConfig($config)->redirect();
but it says:
Call to undefined method Laravel\Socialite\Two\FacebookProvider::setConfig()
when trying to login with facebook.
Can someone please help me? Thank you.

I could reproduce and found a solution. The code you provided was outdated, and I found other instances of it here: https://laravel.io/forum/07-28-2016-dynamic-callback-url-laravel-socialite
By default, Socialite will get the provider config in services.php by passing the $providerName = facebook
So your code now becomes:
// The services.php config will return null, fix it by using: strtoupper()
$clientId = env(strtoupper($provider . "_client_id"));
$clientSecret = env(strtoupper($provider . "_client_secret"));
$redirectUrl = "/the-url-i-want";
// ->redirect() acts as a closure, without it, you'll get an error like:
// "Serialization of 'Closure' is not allowed"
$user = Socialite::with($provider)->redirect();
return redirect()->to($redirectUrl)->with(['user', $user]);
More info on redirecting with session data:
https://laravel.com/docs/6.x/redirects#redirecting-with-flashed-session-data

Related

YouTube DATA API V3 does not return refresh token

I have almost looked through all the answers to this question and have not been able to solve my problem. I tried different options but can't get refresh token. Here's an example of my code.
$googleClient = new \Google_Client();
$redirectUrl = url('***');
$googleClient->setClientId(config('services.google_api_key.client_id'));
$googleClient->setClientSecret(config('services.google_api_key.client_secret'));
$googleClient->setScopes(config('services.google_api_key.scopes'));
$redirect = filter_var($redirectUrl);
$googleClient->setRedirectUri($redirect);
$googleClient->setAccessType('offline');
$googleClient->setApprovalPrompt('force');
if ($request->has('code')) {
$googleClient->authenticate($request->get('code'));
$token = $googleClient->getAccessToken();
dd($token);
}
And it returned only these data
[
"access_token" => "***"
"expires_in" => 3599
"scope" => "https://www.googleapis.com/auth/youtube"
"token_type" => "Bearer"
"created" => 1613189613
]
I know that the refresh token is provided only on the first call, and so I tried to use this method $googleClient->revokeToken($token); to get it again, but it didn't help, and I already spent a whole day trying to solve this problem and could not. Please help me solve this problem. I understand that I am making a mistake somewhere, but I cannot understand where. Thanks in advance.
I finally found the problem and would like to explain in detail what was the reason, maybe someone else will come in handy. And so I created everything as it was described in the official documentation https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps#obtainingaccesstokens.
I used this code and was unable to get the refresh token.
$googleClient = new \Google_Client();
$redirectUrl = url('***');
$googleClient->setClientId(config('services.google_api_key.client_id'));
$googleClient->setClientSecret(config('services.google_api_key.client_secret'));
$googleClient->setScopes(config('services.google_api_key.scopes'));
$redirect = filter_var($redirectUrl);
$googleClient->setRedirectUri($redirect);
$googleClient->setAccessType('offline');
$googleClient->setApprovalPrompt('force');
if ($request->has('code')) {
$googleClient->authenticate($request->get('code'));
$token = $googleClient->getAccessToken();
dd($token);
}
The official documentation says this:
$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
$client->setIncludeGrantedScopes(true); // incremental auth
Pay attention to this part:
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
And this is what I managed to find out
$client->setApprovalPrompt('force'); // works
$client->setApprovalPrompt('consent'); // doesn't work
$client->setPrompt('consent'); // works
For 'consent' setApprovalPrompt() doesn't work, but I could not find about it in the official documentation. And found this error from here https://github.com/googleapis/google-api-php-client/issues/1795.
My final code looks like this which works fine and returns me a refresh token:
$redirectUrl = url('my_callback_url');
$client = new \Google_Client();
$client->setClientId(config('services.google_api_key.client_id'));
$client->setClientSecret(config('services.google_api_key.client_secret'));
$client->addScope(config('services.google_api_key.scopes'));
$client->setState(substr(md5(time()), 0, 15));
$client->setRedirectUri($redirectUrl);
$client->setAccessType('offline');
$client->setPrompt('consent');
$client->setIncludeGrantedScopes(true);
return $client->createAuthUrl();
Thank you stvar for your answer, after that I started to read the documentation all over again and look for the reason.
adding consent prompt fixed the issue. for js library it will look like this:
const authorizationUrl = oauth2Client.generateAuthUrl({
// 'offline' will get refresh_token
access_type: 'offline',
scope: scopes,
prompt: 'consent',
state: stateName,
});

Acessing auth user attribute

I am in the guzzle controller making a request to an external api.
I wanna use an id from the user who is logged in.
I have been doing the request with a static id, but now i want it dynamically.
I tried like this:
$science = Auth::user()->science_id;
$client = new Client(['headers' => ['Accept' => 'application/json']]);
$request = $client->get(
'https://url_to_the_api/'.$science.'/degree',
[
'auth' => ['client', 'secret'],
]
);
$data = $request->getBody()->getContents();
return $data;
And i have the error
500(internal server error)
and this message:
"Trying to get property 'science_id' of non-object"
What am i missing?
Thanks for your time
If you are using it in web app then make sure you first check if user is already authenticated by using auth middleware or manually by using Auth::check() function.
Or
If you are trying to hit this by api that will not work here because session will not be maintained in that case. That's why JWT tokens were introduced to maintain the state of an application.
I've solved it like this:
$science = auth('api')->user()->science_id;
Thanks for the help!

What to do when lucadegasperi oauth2 server for laravel gets caught by auth middleware?

So currently building an oauth2 server with:
https://github.com/lucadegasperi/oauth2-server-laravel/blob/master/docs/authorization-server/auth-code.md
Auth Grant
laravel 5.2
Now no where in the instructions does it address what to do when the user is not logged in. (which most times will be the case)
So in that scenario - the user hits the auth middleware kicking them to the login screen... but what to do after that? There is nothing passed to the login page? so how do i know where to redirect the user back to?
Now yes of course I can just do this on my own, but before I do that I just want to make sure I am not missing anything? again it was not address in the documentation, so I can only assume this was thought through?
Let me know your thoughts.
Steve
So just ended up doing a work around in my Authenticate.php file. Incase anyone else is curious I did this:
$params = [];
if($request->has('client_id'))
$params['client_id'] = $request->client_id;
if($request->has('redirect_uri'))
$params['redirect_uri'] = $request->redirect_uri;
if($request->has('response_type'))
$params['response_type'] = $request->response_type;
if($request->has('scope'))
$params['scope'] = $request->scope;
if($request->has('state'))
$params['state'] = $request->state;
return redirect()->route('login', $params);
//return redirect()->guest('login');
Passed this to my loginController. Then in loginController:
$params = [];
if($this->request->has('redirect_uri'))
$params['redirect_uri'] = $this->request->redirect_uri;
if($this->request->has('response_type'))
$params['response_type'] = $this->request->response_type;
if($this->request->has('scope'))
$params['scope'] = $this->request->scope;
if($this->request->has('state'))
$params['state'] = $this->request->state;
if($this->request->has('client_id'))
{
$params['client_id'] = $this->request->client_id;
//dd($params);
return redirect()->route('oauth.authorize.get', $params);
}
Let me know if you see any issues.
Cheers
Citti

Laravel 5: Calling routes internally

Is there a way, in Laravel 5, to call routes internally/programmatically from within the application? I've found a lot of tutorials for Laravel 4, but I cannot find the information for version 5.
Using laravel 5.5, this method worked for me:
$req = Request::create('/my/url', 'POST', $params);
$res = app()->handle($req);
$responseBody = $res->getContent();
// or if you want the response to be json format
// $responseBody = json_decode($res->getContent(), true);
Source:
https://laracasts.com/discuss/channels/laravel/route-dispatch
*note: maybe you will have issue if the route you're trying to access
has authentication middleware and you're not providing the right credentials.
to avoid this, be sure to set the correct headers required so that the request is processed normally (eg Authorisation bearer ...).
UPDATE: i've tried this method with laravel 8 and it works but if you're using PHP version 8.0 you might need to call opcache_reset(); before this line $req = Request::create('/my/url', 'POST', $params); to avoid an error.
see guzzlehttp/guzzle dosn't work after update php to php 8 for more info
You may try something like this:
// GET Request
$request = Request::create('/some/url/1', 'GET');
$response = Route::dispatch($request);
// POST Request
$request = Request::create('/some/url/1', 'POST', Request::all());
$response = Route::dispatch($request);
You can actually call the controller that associates to that route instead of 'calling' the route internally.
For example:
Routes.php
Route::get('/getUser', 'UserController#getUser');
UserController.php
class UserController extends Controller {
public function getUser($id){
return \App\User::find($id);
};
}
Instead of calling /getUser route, you can actually call UserController#getUser instead.
$ctrl = new \App\Http\Controllers\UserController();
$ctrl->getUser(1);
This is the same as calling the route internally if that what you mean. Hope that helps
// this code based on laravel 5.8
// I tried to solve this using guzzle first . but i found guzzle cant help me while I
//am using same port. so below is the answer
// you may pass your params and other authentication related data while calling the
//end point
public function profile(){
// '/api/user/1' is my api end please put your one
//
$req = Request::create('/api/user/1', 'GET',[ // you may pass this without this array
'HTTP_Accept' => 'application/json',
'Content-type' => 'application/json'
]);
$res = app()->handle($req);
$responseBody = json_decode($res->getContent()); // convert to json object using
json_decode and used getcontent() for getting content from response
return response()->json(['msg' =>$responseBody ], 200); // return json data with
//status code 200
}
None of these answers worked for me: they would either not accept query parameters, or could not use the existing app() instance (needed for config & .env vars).
I want to call routes internally because I'm writing console commands to interface with my app's API.
Here's what I did that works well for me:
<?php // We're using Laravel 5.3 here.
namespace App\Console;
use App\MyModel;
use App\MyOtherModel;
use App\Http\Controllers\MyController;
use Illuminate\Console\Command;
class MyCommand extends Command
{
protected $signature = 'mycommand
{variable1} : First variable
{variable2} : Another variable';
public function handle()
{
// Set any required headers. I'm spoofing an AJAX request:
request()->headers->set('X-Requested-With', 'XMLHttpRequest');
// Set your query data for the route:
request()->merge([
'variable1' => $this->argument('variable1'),
'variable2' => $this->argument('variable2'),
]);
// Instantiate your controller and its dependencies:
$response = (new MyController)->put(new MyModel, new MyOtherModel);
// Do whatever you want with the response:
var_dump($response->getStatusCode()); // 200, 404, etc.
var_dump($response->getContent()); // Entire response body
// See what other fun stuff you can do!:
var_dump(get_class_methods($response));
}
}
Your Controller/Route will work exactly as if you had called it using curl. Have fun!

get product list using soap api magento

I am using Soap Api and want to get product list whose stock is not 0, meaning there is at least 1 inventory(Stock) of the product in magento.
I am using this type of code but it is not working.
$proxy = new SoapClient('http://magentohost/api/v2_soap/?wsdl');
$sessionId = $proxy->login((object)array('username' => 'apiUser', 'apiKey' => 'apiKey'));
$result = $proxy->catalogInventoryStockItemList((object)array('sessionId' => $sessionId->result, 'productIds' => array(1,2)));
var_dump($result->result);
Use the code below, it worked for me:
$proxy = new SoapClient('http://yourstore.com/api/v2_soap/?wsdl');
$sessionId = $proxy->login('apiUserName', 'apiKey');
$result = $proxy->catalogProductList($sessionId);
var_dump($result);
If this did not work for you try to replace the url with the following (add "index.php") http://yourstore.com/index.php/api/v2_soap/?wsdl
Hope this solves your problem!
Try adding the following lines before the code to enable error logging to see what the error is, seeing a blank screen might be because there is an error but you dont see it:
ini_set('display_errors', true);
error_reporting(E_ALL);
Can you also access this URL "yourstore.com/api/v2_soap/?wsdl" or this "yourstore.com/index.php/api/v2_soap/?wsdl" directly in your browser and let me know what you see? you should be able to see an XML document, if there is a setting issue, you will see something like "Invalid service adapter" or somekind of an error message.
use v1 api
$proxy = new SoapClient('http://magentohost/api/soap/?wsdl');
$session = $client->login('apiUser', 'apiKey');
$proxy->call($session, 'catalog_product.info',array(1,2));//productIds

Resources