How To get a new Access using Laravel Socialteprovider - php

i'm using
lumen
https://socialiteproviders.com/Microsoft-Azure/#installation-basic-usage
I'm getting access_token and refresh_token after authentication but I want to refresh a token after its expiry, which I'm not able to find a way to do or any method in the library, any help would be appreciated.
/*Google OR Azure */
switch ($provider) {
case 'google':
$scopes = [
'https://www.googleapis.com/auth/plus.business.manage',
// 'https://graph.microsoft.com/user.read',
/*List of scopes to add if needed */
];
$parameters = ['access_type' => 'offline', "prompt" => "consent select_account"];
break;
case 'azure':
$scopes = [
'offline_access openid',
'https://graph.microsoft.com/user.read',
];
$parameters = ['access_type' => 'offline_access'];
break;
}
return Socialite::driver($provider)->scopes($scopes)->with($parameters)->stateless()->redirect();
public function handleProviderCallback()
{
$providerUser = Socialite::driver('azure')->stateless()->user();
return $data = [
'status' => 'success',
'access_token' => $providerUser->token,
'refresh_token' => $providerUser->refreshToken,
'expiry_time' => $providerUser->expiresIn,
'auth_provider' => 'azure',
'email' => $providerUser->email
];
}
i have tried a couple of ways but none of them seems to work for me as below
// $a = Socialite::driver('azure')->refreshToken($refToken);
// $a = (object) Socialite::driver('azure')
// ->setScopes(['offline_access'])
// ->getRefreshTokenResponse($refToken);
// $a= (object) Socialite::driver('azure')->user();
//$a= (object) Socialite::driver('azure')->getAccessToken();
// $a= Socialite::driver('azure')->stateless()->user();
// $a= Socialite::driver('azure')->userFromToken($accessToken);
//$a= Socialite::driver('twitch')->refreshToken($storedRefreshToken)
print_r($a);

Related

How to add wishlist data to trailData without overwriting existing data?

I'm new to PHP and I'm building API for wishlist, for both guest users and logged-in users in Laravel Lumen. Here I'm using TrailManagerService as session manager
It saves data as
- for logged in users
Array
(
[trail_id] => 4b19bd9d-f2da-431b-8aba-d181d7eca736
[inception_time] => 1599813465
[last_used] => 1600762156
[customer_id] => 106210
[customer_data.customer_id] => 106210
[customer_data.firstname] => XXXX
[customer_data.lastname] => YYYY
[customer_data.gender] => Male
[customer_data.dob] => 1999-10-19
[customer_data.email] => xx#yy.com
[customer_data.mobile] => 2245436547
[customer_data.referral_code] => HRI11489
-for guest users
Array
(
[trail_id] => 8b7e6931-6ad3-48a0-af61-4caaab85cf20
[inception_time] => 1600761357
[last_used] => 1600761391
I want to add wishlist items to trailData and save it to DB if user does login and then emptytraildata after it get saved to DB. Also, if user doesnt login wishlist data should be saved in trailData for current session.
Code for WishlistControllerService
<?php
namespace App\Http\Services\v1\Products;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Redis;
use Illuminate\Http\Request;
use App\Services\SOA\TrailManagerService;
use App\Repositories\WishlistRepository;
class WishlistControllerService
{
public function __construct(WishlistRepository $wishlistRepository)
{
$this->wishlistRepository = $wishlistRepository;
}
public function showList(Request $request){
$trailData = TrailManagerService::getAllTrailData('customer_id');
$trailCustomerId = TrailManagerService::getTrailData('customer_id');
$headerCustomerId = (int) $request->header('X-Customer-ID', 0);
$responseData = [];
$trailCustomerId = $trailData['customer_id'] ?? 0;
print_r($trailData);exit;
if($trailCustomerId === $headerCustomerId) {
// print_r("hi");exit;
$wishlistData = $this->wishlistRepository->getWishlist($trailCustomerId);
$responseData = [
'identifier' => 'wishlist',
'data' => [
'list' => $wishlistData
]
];
} else if($trailCustomerId === 0) {
// print_r("bye");exit;
// $tempWishlistItem = [
// // 'guestUserID' => $,
// 'productID' => $request->input('product_id'),
// 'sizeID' => $trailData['size_id'],
// 'productQuantity' => $request->input('quantity'),
// 'shippingPin' => $request->input('postal_code'),
// 'shippingCity' => $request->input('city_name'),
// ];
$responseData = [
'identifier' => '',
'data' => [
'list' => []
]
];
} else {
// print_r("why");exit;
$responseData = [
'status' => 403,
'message' => 'Access Forbidden'
];
}
return $responseData;
}
public function store($request, $productId){
$trailData = TrailManagerService::getAllTrailData();
$responseData = [];
$headerCustomerId = (int) $request->header('X-Customer-ID', 0);
$trailCustomerId = $trailData['customer_id'] ?? 0;
$tempWishlistItem =
[
// 'siteUserID`' => $customerId ?? $trailCustomerId,
'productID' => $productId,
'sizeID' => $request->input('size_id'),
'productQuantity' => $request->input('quantity'),
'currency' => strtoupper($request->input('currencyCode')),
];
$tempData[] =
array_push($trailData, $tempWishlistItem);
TrailManagerService::setTrailData($trailData);
print_r($trailData);exit;
// if($trailCustomerId === $customerId) {
$wId = $this->wishlistRepository->create($wishlistModelData);
$responseData = ['data' => ['userWID' => $wId]];
$wishlistModelData = [
'siteUserID' => $customerId,
'productID' => $productId,
'sizeID' => $request->input('size_id'),
'productQuantity' => $request->input('quantity'),
'currency' => strtoupper($request->input('currencyCode')),
];
// print_r($wishlistModelData);exit;
$wishlistItem = $this->wishlistRepository
->findWhere(['status' => 1, 'siteUserID' => $customerId, 'productID' =>
$productId]);
if(empty($wishlistItem[0]) === false) {
$responseData = [
'status' => 403,
'message' => 'Forbidden, Item already in Wishlist'
];
} else {
$wId = $this->wishlistRepository->create($wishlistModelData);
$responseData = ['data' => ['userWID' => $wId]];
}
} else {
// $tempWishlistData = [];
$tempWishlistItem =
[
// 'siteUserID' => $customerId ?? $trailCustomerId,
'productID' => $productId,
'sizeID' => $request->input('size_id'),
'productQuantity' => $request->input('quantity'),
'currency' => strtoupper($request->input('currencyCode')),
];
$tempWishlistData = array_merge($trailData, [$tempWishlistItem]);
print_r($tempWishlistData);exit;
$trailDataTemp = TrailManagerService::setTrailData(
$tempWishlistData
);
print_r($trailDataTemp);exit;
if($customerId === $trailData['customerID']){
foreach($tempWishlistData as $item) {
$wId = $this->wishlistRepository->create($wishlistModelData);
$responseData = ['data' => ['userWID' => $wId]];
}
TrailManagerService::emptyTrailData();
}
return $responseData;
}
I want to add wishlist items to trailData and save it to DB if user does login and then emptytraildata after it get saved to DB. Also, if user doesnt login wishlist data should be saved in trailData for current session.
Code for Wishlist Controller
<?php
namespace App\Http\Controllers\v1\Products;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Services\v1\Products\WishlistControllerService;
use Validator;
use App\Helpers\Utilities;
use App\Services\SOA\TrailManagerService;
use Illuminate\Support\Facades\Route;
class WishlistController extends Controller
{
private $controllerService;
public function __construct(WishlistControllerService $controllerService)
{
// $request = app(Request::class);
// $customerId = $request->header('X-Customer-ID', 0);
// TrailManagerService::authorize($customerId);
$this->controllerService = $controllerService;
}
public function index(Request $request)
{
$responseData = $this->controllerService->showList($request);
$httpStatus = $responseData['status'] ?? 200;
return $this->response($responseData, $httpStatus);
}
public function store(Request $request, int $productId){
$requestParams = $request->all();
// $requestParams['productId'] = $request->header('product_id');
$validator = Validator::make($requestParams,
[
'product_id' => 'integer',
'size_id' => 'integer',
'quantity' => 'required|integer|digits_between:1,2',
'currencyCode' => 'required|string|in:INR,EUR,USD,AUD,CAD,SGD,HKD'
],
[
'product_id.integer'=> 'Parameter product_id is mandatory',
'size_id.integer' => 'Invalid value for parameter size_id',
],
);
if ($validator->fails()) {
$messages = $validator->errors();
$responseData = Utilities::requestValiationResponse($messages);
} else {
// print_r($productId);exit;
$responseData = $this->controllerService->store($request, $productId);
}
$httpStatus = $responseData['status'] ?? 200;
return $this->response($responseData, $httpStatus);
}
public function remove(Request $request, int $productId)
{
$responseData = $this->controllerService->remove($request, $productId);
$httpStatus = $responseData['status'] ?? 200;
return $this->response($responseData, $httpStatus);
}
}
Code for Wishlist Repo
<?php
namespace App\Repositories;
use Prettus\Repository\Eloquent\BaseRepository;
use App\Models\MxUserWishlist;
use Illuminate\Support\Facades\DB;
use App\Helpers\Utilities;
class WishlistRepository extends BaseRepository
{
/**
* Specify Model class name
*
* #return string
*/
public function model()
{
return MxUserWishlist::class;
}
/**
* #param int $customerId
* #return array
*/
public function getWishlist($trailCustomerId): array
{
$wishlistData = [];
$query = "SELECT W.userWID, W.siteUserID, W.productID,P.productTitle, PSI.imageName,
W.sizeID, S.sizeTitle, D.designerName,P.designerID, P.categoryID,
PS.productPrice, PS.discountPercent,PS.filterPrice,P.seoUri
FROM mx_user_wishlist W
INNER JOIN mx_product P ON P.productID = W.productID
INNER JOIN mx_product_set PS ON (W.productID = PS.productID AND W.sizeID = PS.sizeID)
INNER JOIN mx_product_set_images PSI ON PSI.productID = W.productID
INNER JOIN mx_size S ON S.sizeID = W.sizeID
INNER JOIN mx_designer D ON P.designerID = D.designerID
WHERE W.siteUserID = $trailCustomerId";
$wishlistCollection = DB::select($query, ['siteUserID' => $trailCustomerId]);
if(empty($wishlistCollection) === false) {
foreach ($wishlistCollection as $key => $wishlist) {
$productId = 0;
$productUrl = '';
$productUrl = '/products/'.$wishlist->seoUri.'/'.$wishlist->productID;
$wishlistItems = [
'id' => $wishlist->productID,
'name' => $wishlist->productTitle,
'image' => config('global.cdni_url').'/tr:w-317/uploads/product/'.$wishlist->imageName,
'product_url' => $productUrl,
'sizes' => [
'id' => $wishlist->productID,
'name' => $wishlist->sizeTitle
],
'designer_name' => $wishlist->designerName,
'category_id' => $wishlist->categoryID,
'mrp' => $wishlist->productPrice,
'discount_percentage' => $wishlist->discountPercent,
'you_pay' => $wishlist->filterPrice,
];
}
return $wishlistItems;
} else {
$responseData = [];
return $responseData;
}
// return $responseData;
}

How to unit test all code execution paths of Laravel's Cache::remember functionality?

I am a big fan of Laravel's Cache::remember functionality and I use it on my service classes like this:
/**
* SummaryService
*/
public function getSummaryData(string $userId)
{
$summaryCacheKey = $userId . '_summary_cache';
$summaryCacheLifespanMinutes = config('summary_cache_lifespan_minutes');
return Cache::remember($summaryCacheKey, $summaryCacheLifespanMinutes, function () use ($userId) {
$summaryResult = [
'userExists' => false,
'data' => [],
];
$user = $this->userRepository->findById($userId);
if ($user) {
$summaryResult = [
'userExists' => true,
'data' => $this->summaryRepository->getSummaryByUserId($user->id),
];
}
return $summaryResult;
});
}
This works as expected. If the data is present in the cache, it's returned and if it's not, it's loaded and cached and returned.
Now, I am trying to unit test my SummaryService (both execution paths).
The first part where the data is returned via cache is easy to test and it looks like this:
public function i_can_load_summary_data_via_cache()
{
// given
$userId = 'aaaa45-bbbb-cccc-ddddssswwwdw';
$expectedResult = [
'userExists' => true,
'data' => [ ... ],
];
$summaryCacheKey = $userId . '_summary_cache';
$summaryCacheLifespanMinutes = config('summary_cache_lifespan_minutes');
Cache::shouldReceive('remember')
->once()
->with($summaryCacheKey, $summaryCacheLifespanMinutes, Closure::class)
->andReturn($expectedResult);
// when
$result = $this->summaryService->getSummaryData($userId);
// then
$this->assertSame($expectedResult, $result);
}
However, when I try to test scenario where the data is not present in cache and I have to load it (via mocked repositories) like so:
public function i_can_load_summary_data_via_database()
{
// given
$userId = 'aaaa45-bbbb-cccc-ddddssswwwdw';
$expectedResult = [
'userExists' => true,
'data' => [ ... ],
];
$user = new User();
$user->id = $userId;
$summaryCacheKey = $userId . '_summary_cache';
$summaryCacheLifespanMinutes = 0;
Cache::shouldReceive('remember')
->once()
->with($summaryCacheKey, $summaryCacheLifespanMinutes, \Mockery::on(function() use($user) {
$this->mockedUserRepository
->shouldReceive('findById')
->once()
->andReturn($user);
$this->mockedSummaryRepository
->shouldReceive('getSummaryByUserId')
->once()
->with($user->id)
->andReturn([ ... ]);
}))
->andReturn($expectedResult);
// when
$result = $this->summaryService->getSummaryData($userId);
// then
$this->assertSame($expectedResult, $result);
}
The test is failing:
No matching handler found for
Mockery_3_Illuminate_Cache_CacheManager::remember('aaaa45-bbbb-cccc-ddddssswwwdw_summary_cache', '10', object(Closure)). Either the method was unexpected or its
arguments matched no expected argument list for this method
Objects: ( array ( 'Closure' => array (
'class' => 'Closure',
'properties' =>
array (
), ), ))
Any idea on how to test this properly?
Okay, I seem to have over complicated this; so I have broken it down and fixed it slightly differently like this.
My service code now looks like this:
/**
* SummaryService
*/
public function getSummaryData(string $userId)
{
$summaryCacheKey = $userId . '_summary_cache';
$summaryCacheLifespanMinutes = config('summary_cache_lifespan_minutes');
return Cache::remember($summaryCacheKey, $summaryCacheLifespanMinutes, function () use ($userId) {
return $this->loadLiveSummaryData($userId);
});
}
public function loadLiveSummaryData(string $userId)
{
$summaryResult = [
'userExists' => false,
'data' => [],
];
$user = $this->userRepository->findById($userId);
if ($user) {
$summaryResult = [
'userExists' => true,
'data' => $this->summaryRepository->getSummaryByUserId($user->id),
];
}
return $summaryResult;
}
and now, I just need to confirm via my unit test that:
My service can load cached version and match the call parameters
and I can load live data (where i can mock the repos)
Which looks something like this:
/**
* #test
*/
public function i_can_load_live_summary_data_for_existing_user()
{
// given
$userId = 'aaaa45-bbbb-cccc-ddddssswwwdw';
$expectedResult = [
'userExists' => true,
'data' => [ ... ],
];
$user = new User();
$user->id = $userId;
$this->mockedUserRepository
->shouldReceive('findById')
->once()
->andReturn($user);
$this->mockedSummaryRepository
->shouldReceive('getSummaryByUserId')
->once()
->with($user->id)
->andReturn([ ... ]);
// when
$result = $this->summaryService->loadLiveSummaryData($userId);
// then
$this->assertSame($expectedResult, $result);
}
/**
* #test
*/
public function i_expect_cache_to_be_called_when_loading_summary_data_for_specific_user()
{
// given
$userId = 'aaaa45-bbbb-cccc-ddddssswwwdw';
$expectedResult = [
'userExists' => true,
'data' => [ ... ],
];
$summaryCacheKey = $userId . '_summary_cache';
$summaryCacheLifespanMinutes = 10;
Cache::shouldReceive('remember')
->once()
->with($summaryCacheKey, $summaryCacheLifespanMinutes, \Mockery::on(function($value) {
return is_callable($value);
}))
->andReturn($expectedResult);
// when
$result = $this->summaryService->getSummaryData($userId);
// then
$this->assertSame($expectedResult, $result);
}
Let me know if there was a better or "correct" way to do this.
Had a similar situation where I wanted to test both paths, when data is returned via the cache and when the callback function is executed.
The key for me was to not use any of the facade mock method (e.g. Cache::shouldReceive('remember')) and then the callback code will run.
Seems pretty obvious now :(

An active access token must be used to query information about the current user in laravel

I am trying to login with facebook using angularjs with laravel. But I am stuck with this error:
{"error":{"message":"An active access token must be used to query
information about the current user.","type":"OAuthExce (truncated...)
Here is my Controller:
public function facebookLogin(Request $request){
$client = new GuzzleHttp\Client();
$params = [
'code' => $request->input('code'),
'client_id' => $request->input('clientId'),
'redirect_uri' => $request->input('redirectUri'),
'client_secret' => Config::get('app.facebook_secret'),
'grant_type'=>'client_credentials'
];
// Step 1. Exchange authorization code for access token.
$accessTokenResponse = $client->request('GET', 'https://graph.facebook.com/v2.5/oauth/access_token', [
'query' => $params
]);
$accessToken = json_decode($accessTokenResponse->getBody(), true);
// Step 2. Retrieve profile information about the current user.
$fields = 'id,email,first_name,last_name,link,name,picture';
/**** problem counted with this request ************/
$profileResponse = $client->request('GET', 'https://graph.facebook.com/v2.5/me', [
'query' => [
'access_token' => $accessToken['access_token'],
'fields' => $fields
]
]);
$profile = json_decode($profileResponse->getBody(), true);
$user = User::where('email', '=', $profile['email'])->first();
if($user) {
Auth::loginUsingId($user->id);
$user_info = Auth::user();
$profile_seen = $user_info->profile_seen;
User::where('id', '=', $user_info->id)->update(array('profile_seen' => 1));
return Response::json(['login' => Auth::check(),'profile_seen' => $profile_seen ]);
}else{
$user = User::create(array(
'username' => $profile['name'],
'email' => $profile['email'],
'first_name' => $profile['first_name'],
'last_name' => $profile['last_name'],
'facebook_id'=> $profile['id']
));
Auth::loginUsingId($user->id,1);
$user_info = Auth::user();
$profile_seen = $user_info->profile_seen;
User::where('id', '=', $user_info->id)->update(array('profile_seen' => 1));
return Response::json(['login' => Auth::check(),'profile_seen' => $profile_seen ]);
}
}
I have encountered this problem. You need to run the composer update. Then run the command composer dump-autoload. This problem has been fixed in version Socialite v2.0.21.

JWTAuth getToken give false result when tried to call it in laravel 5

I'm new in laravel and get stuck already with JWTAuth service in laravel.
I'm developing mobile app using ionic and try to make request to generate jwt token. It turn out I was able to generate the token, but when I try another request to compare the token, I cannot get the token using JWTAuth::getToken() in the laravel.
here my script for signin (generate token)
public function signin(Request $request){
$request = [
'email' => urldecode($request->request->get('email')),
'password' => urldecode($request->request->get('password'))
];
if(Auth::attempt($request)){
$user = Auth::user();
Auth::login($user, true);
$custom = ['id' => $user->id, 'email' => $user->email, 'fullname' => $user->name];
$newToken = JWTAuth::fromUser($user,$custom);
$return = array('success' => true, 'token' => $newToken);
}else{
$return = array('success' => false,'token' => '');
};
return response()->json($return);
}
and this is another method to get the token from laravel
public function signout($token){
$user = Auth::user();
if($user){
$return = array('success' => false,'token' => JWTAuth::getToken());
}else{
$return = array('success' => false,'token' => $token);
}
return response()->json($return);
}
is there anyone experience same problem with me? or I missed something here? thanks for the answer and help!

ZF2 SessionManager usage

I am new to ZF2 and not quite used to how to do stuff. I want to use session to keep track of an user (remember me). I had this code in one part of my class:
$sessionManager = new \Zend\Session\SessionManager();
$sessionManager->rememberMe($time);
// i want to keep track of my user id too
$populateStorage = array('user_id' => $user->getId());
$storage = new ArrayStorage($populateStorage);
$sessionManager->setStorage($storage);
Ok, so far so good. When i try:
var_dump($sessionManager->getStorage());
I get the expected data.
In another part of my program, i want to retreive my data again (a bit like containers):
$sessionManager = new \Zend\Session\SessionManager();
var_dump($sessionManager->getStorage());
This only returns an empty object.
I guess this is due to the "new" and i think i have to implement SessionManager in a different way, but how? I do not know. This is what i came up with:
In my Module i now have:
public function onBootstrap(\Zend\Mvc\MvcEvent $e)
{
$config = $e->getApplication()
->getServiceManager()
->get('Configuration');
$sessionConfig = new SessionConfig();
$sessionConfig->setOptions($config['session']);
$sessionManager = new SessionManager($sessionConfig);
$sessionManager->start();
In my module.config:
'session' => array(
'remember_me_seconds' => 2419200,
'use_cookies' => true,
'cookie_httponly' => true,
),
But how to procede? How do i get the instance for my sessionManager?
There is not well documented SessionManagerFactory (zf2 api doc) and SessionConfigFactory (zf2 api doc). With those is instantiate SessionManager very easy, just put these factories to your ServiceManager configuration:
'service_manager' => [
'factories' => [
'Zend\Session\SessionManager' => 'Zend\Session\Service\SessionManagerFactory',
'Zend\Session\Config\ConfigInterface' => 'Zend\Session\Service\SessionConfigFactory',
],
],
and to module configuration put your session options, under the session_config key:
'session_config' => [
'remember_me_seconds' => 2419200,
'use_cookies' => true,
'cookie_httponly' => true,
],
and that's it, now you can grab SessionManager from service locator anywhere, for example in controller:
/** #var Zend\Session\SessionManager $sm */
$sessionManager = $this->serviceLocator->get('Zend\Session\SessionManager');
This is available as of 2.2 version of Zend Framework (related pull request).
In my project i use example from other source (book or official documentation, forget).
Main Module.php file:
namespace Application;
class Module
{
public function getServiceConfig()
{
return array(
'factories' => array(
'Zend\Session\SessionManager' => function ($sm){
$config = $sm->get('config');
if (isset($config['session'])){
$session_config = $config['session'];
$sessionConfig = null;
if (isset($session_config['config'])){
$class = isset($session_config['config']['class'])
? $session_config['config']['class']
: 'Zend\Session\Config\SessionConfig';
$options = isset($session_config['config']['options'])
? $session_config['config']['options']
: array();
$sessionConfig = new $class();
$sessionConfig->setOptions($options);
}
$sessionStorage = null;
if (isset($session_config['storage'])){
$class = $session_config['storage'];
$sessionStorage = new $class();
}
$sessionSaveHandler = null;
if (isset($session_config['save_handler'])){
// class should be fetched from service manager
// since it will require constructor arguments
$sessionSaveHandler = $sm->get($session_config['save_handler']);
}
$sessionManager = new SessionManager(
$sessionConfig,
$sessionStorage,
$sessionSaveHandler
);
if (isset($session_config['validator'])){
$chain = $sessionManager->getValidatorChain();
foreach ($session_config['validator'] as $validator){
$validator = new $validator();
$chain->attach('session.validate', array(
$validator,
'isValid'
));
}
}
} else {
$sessionManager = new SessionManager();
}
Container::setDefaultManager($sessionManager);
return $sessionManager;
},
),
);
}
}
My config/autoload/global.php config file:
return array(
'session' => array(
'config' => array(
'class' => 'Zend\Session\Config\SessionConfig',
'options' => array(
'use_cookies' => true,
),
),
'storage' => 'Zend\Session\Storage\SessionArrayStorage',
'validators' => array(
array(
'Zend\Session\Validator\RemoteAddr',
'Zend\Session\Validator\HttpUserAgent',
),
),
),
);
To get user_id from session:
$sessionStorage = $sm->get('Zend\Session\SessionManager')
->getStorage();
$user_id = $sessionStorage->user_id;

Categories