Google Client API setAccessToken() before isAccessTokenExpired() results in invalid credentials - laravel

I am working with the Google Client API in Laravel to allow my users to sync their calendars with Google. Everything works, but the issue I am running into is when their tokens expire they are getting an "Invalid Credentials" error, in order to fix it they have to log out and log back in which I am trying to avoid.
I don't understand why setAccessToken() is to be called before isAccessTokenExpired().
I need to check if the access token is expired before I set it but if I do it this way then isAccessTokenExpired() always returns true.
Any ideas would be helpful. Thanks!
Here is my code:
GoogeServiceController.php
class GoogleServiceController extends Controller
{
protected $client;
protected $service;
public function __construct()
{
$client = new Google_Client();
$client->setAuthConfig(Config::get('google_config.web'));
$client->setAccessType('offline');
$client->addScope(Google_Service_Calendar::CALENDAR);
$service = new Google_Service_Calendar($client);
$this->client = $client;
$this->service = $service;
}
public function oauth(Request $request)
{
if (App::environment('local')) {
$this->client->setRedirectUri('http://esm.development.com/oauth');
} else {
$this->client->setRedirectUri('https://essentialstudiomanager.com/oauth');
}
if (is_null($request->user()->refresh_token)) {
$this->client->setApprovalPrompt("force");
}
if (!$request->has('code')) {
$auth_url = $this->client->createAuthUrl();
$filtered_url = filter_var($auth_url, FILTER_SANITIZE_URL);
return redirect($filtered_url);
} else {
$this->client->authenticate($request->code);
if (is_null($request->user()->refresh_token)) {
$refresh_token = $this->client->getRefreshToken();
$user = $request->user();
$user->refresh_token = $refresh_token;
$user->save();
}
$request->session()->put('access_token', $this->client->getAccessToken());
$notification = ['message' => 'Your calendar is now synced with your Google Calendar.', 'alert-type' => 'success'];
return redirect()->route('home')->with($notification);
}
}
}
GoogleEventController.php
public function updateGoogleEvent($request, $event, $title, $description, $start, $end)
{
if ($request->session()->has('access_token')) {
$this->client->setAccessToken(session('access_token'));
if ($this->client->isAccessTokenExpired()) {
$this->client->refreshToken($request->user()->refresh_token);
$request->session()->put('access_token', $this->client->getAccessToken());
$this->client->setAccessToken(session('access_token'));
}
} else {
return redirect()->route('oauthCallBack');
}
$users_calendar = $this->service->calendars->get('primary');
$get_event = $this->service->events->get('primary', $event->google_event_id);
$get_event->setSummary($title);
$get_event->setDescription($description);
$start_date = new Google_Service_Calendar_EventDateTime();
$start_date->setDateTime($start);
$start_date->setTimeZone($users_calendar->timeZone);
$get_event->setStart($start_date);
$end_date = new Google_Service_Calendar_EventDateTime();
$end_date->setDateTime($end);
$end_date->setTimeZone($users_calendar->timeZone);
$get_event->setEnd($end_date);
$updatedEvent = $this->service->events->update('primary', $get_event->getId(), $get_event);
}

Related

Laravel Create a request internally Resolved

I need to recreate a resquest so that it behaves like a call via api to go through the validator, but my $request->input('rps.number') always arrives empty, although I can see the data in the debug
I also couldn't get it to go through the laravel validator
I can't use a technique to make an http call, because I need to put this call in a transaction
<?php
$nota = new stdClass();
$rps = new stdClass();
$rps->numero = (int)$xml->Rps->IdentificacaoRps->Numero;
$rps->serie = (string)$xml->Rps->IdentificacaoRps->Serie;
$rps->tipo = (int)$xml->Rps->IdentificacaoRps->Tipo;
$nota->rps = $rps;
$controller = new NotaController(new Nota());
$content = new StoreNotaRequest();
$content->request->add($nota);
$result = $controller->store($content);
StoreNotaRequest
<?php
class StoreNotaRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$request = $this->request;
return [
'rps.numero' => 'required_with:rps|numeric|between:1,999999999999999',
'rps.serie' => 'required_with:rps|string|min:1|max:5',
'rps.tipo' => 'required_with:rps|integer|in:1,2,3'
];
}
}
NotaController
<?php
class NotaController extends Controller
{
private Nota $nota;
public function __construct(Nota $nota)
{
$this->nota = $nota;
}
public function store(StoreNotaRequest $request): JsonResponse
{
// $validated = $request->validated();
try {
$nota = DB::transaction(function () use ($request) {
$request->input('rps.numero');
});
return response()->json($nota);
} catch (Throwable $e) {
return response()->json($data, 409);
}
}
}
Solution
the solution was a little too verbose, I believe it is possible to solve with less code.
more does what it needs to go through the validation of the data contained in the StoreNotaRequest
and it returns an http response, in addition to being able to put all these isolated calls in a single transaction
DB::beginTransaction();
$errors = [];
foreach ($itens as $item) {
$controller = new NotaController(new Nota());
$request = new StoreNotaRequest();
$request->setMethod('POST');
$request->request->add($nota);
$request
->setContainer(app())
->setRedirector(app(Redirector::class))
->validateResolved();
$response = $controller->store($request);
if ($response->statusText() !== 'OK') {
$errors[$item->id] = 'ERROR';
}
}
if (count($errors) === 0) {
DB::commit();
} else {
DB::rollBack();
}

Auth::user() Returns Null in API Controller

I'm using Laravel 7 and my problem is to get null from Auth::user();
auth()->user and Auth::id() return null as well.
BTW, in balde template Auth::user() works.
It returns null when I try to use it in controller.
What I'm trying to do is to create a comment page in backend (Vuejs) and I want to build up a filter logic. In order to do that, I want to add a new property named repliedBy into each comment in controller. If a comment isn't replied by the current user, repliedBy will be notByMe. So I don't event try to return user id to Vuejs. I can't get id even in the controller. BTW, login, registration etc work normal way.
Here is my CommentsController:
public function index()
{
$comments = Comment::join("site_languages", "language_id", "=", "site_languages.id")
->select("content_comments.*", "site_languages.shorthand as lang_shorthand")
->with(["replies", "post", "user"])
->orderBy('id', 'desc')
->get()
->groupBy("commentable_type");
$grouppedComments = [];
foreach ($comments as $type => $typeSet) {
$newType = strtolower(explode("\\", $type)[1]);
$grouppedByLanguage = $typeSet->groupBy("lang_shorthand");
$langSet = [];
foreach ($grouppedByLanguage as $lang => $commentSet) {
$grouppedBycontent = [];
foreach ($commentSet as $comments) {
$content = $newType . "_" . $comments->commentable_id;
if (array_key_exists($content, $grouppedBycontent)) {
array_push($grouppedBycontent[$content], $comments);
} else {
$grouppedBycontent[$content] = [$comments];
}
}
$groupAfterOrganized = [];
foreach ($grouppedBycontent as $content => $comments) {
$order = 1;
$commentAndReplies = [];
foreach ($comments as $comment) {
if ($comment->parent_id === null) {
if (isset($comment->order) === false || $comment->order > $order) {
$comment->order = $order;
}
array_push($commentAndReplies, $comment);
} else {
foreach ($comments as $parentComment) {
if ($parentComment->id === $comment->parent_id) {
$parent = $parentComment;
break;
}
}
foreach ($parent->replies as $replyInParent) {
if ($replyInParent->id === $comment->id) {
$reply = $replyInParent;
break;
}
}
if (isset($comment->order) === false) {
$comment->order = $order;
$order++;
}
if (isset($parent->order) === false || $parent->order > $comment->order) {
$parent->order = $comment->order;
}
$reply->order = $comment->order;
$reply->replies = $comment->replies;
$reply[$newType] = $comment[$newType];
$basePower = 6;
if ($comment->user_id !== null) {
if ($comment->user_id === Auth::id()) {
$reply->replyFrom = "me";
} else if ($comment->user->role->power >= $basePower) {
$reply->replyFrom = "staff";
} else {
$reply->replyFrom = "user";
}
} else {
$reply->replyFrom = "visitor";
}
$iReplied = false;
$staffReplied = false;
foreach ($reply->replies as $replyOfReply) {
if ($replyOfReply->user_id !== null) {
$power = $replyOfReply->user->role->power;
if ($power >= $basePower) {
$staffReplied = true;
}
}
if ($replyOfReply->user_id === Auth::id()) {
$iReplied = true;
}
}
if ($staffReplied === false) {
if ($reply->replyFrom === "user" && $reply->replyFrom === "visitor") {
$reply->replied = "notReplied";
} else {
$reply->replied = "lastWords";
}
} else if ($staffReplied && $iReplied === false) {
$reply->replied = "notByMe";
} else if ($staffReplied) {
$reply->replied = "replied";
}
}
}
$groupAfterOrganized[$content] = $commentAndReplies;
}
$langSet[$lang] = $groupAfterOrganized;
}
$grouppedComments[$newType] = $langSet;
}
return $grouppedComments;
}
api.php
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::apiResources([
'languages' => 'API\LanguagesController',
'users' => 'API\UsersController',
'roles' => 'API\RolesController',
'tags' => 'API\TagsController',
'categories' => 'API\CategoryController',
'pictures' => 'API\PicturesController',
'posts' => 'API\PostsController',
'comments' => 'API\CommentsController'
]);
EDIT
I'm using the code down below in RedirectIfAuthenticated.php and when I try with
dd(Auth::user());
it returns null as well. BTW obviosly, redirect to backend doesn't work.
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if (Auth::user()->role->power > 5) {
return redirect('backend');
}
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
The solution to this problem is fairly simple . because you are using api request laravel default auth can not understand the user so here the passport comes :
https://laravel.com/docs/7.x/passport
as written in documenation you should go 3 steps :
composer require laravel/passport
php artisan migrate
php artisan passport:install
after that you can generate token for logged in users and use that token in api authentication to use for your api which is the only and more reliable way that laravel default auth .
this link can be helpful to you too :
https://laravel.io/forum/laravel-passport-vue-check-user-authentication
this way if you intent to use you api in mobile or any other application you can simply authenticate your user in that :)
hope this helps
EDIT
according To your comment now you must generate token for your vue api to use so this would be like below :
$token = $user->createToken(config('app.name'))->accessToken;
if ($this->isApiType()) {
$token = $user->createToken(config('app.name'))->accessToken;
} else {
Auth::login($user);
$redirect = $this->getRedirectTo($user);
}
this must be added in the end of your login method so if the request comes from api it generates a JWT token for you which can be used in vue for login
yes for getting the authencated user detail your API must under the auth:API middleware.
Route::group(['middleware' => 'auth:api'], function () {
}
As you are using Resource those are not under the Api middleware just put that into that and Auth::user will return the result set.
Route::group(['middleware' => 'auth:api'], function () {
Route::apiResources([
'comments' => 'API\CommentsController'
]);
}
will fix the issue.

How to compare otp number without reload page which send in sms?

I want to compare otp numbers, which i type in textbox and sms otp sent to the number through api calling controller in laravel.
i use laravel5.6 and php 7.2.3
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
i want to compare textbox otp number and sms otp number sent through api calling and redirect with another controller in laravel5.6
The thing is you must store your otp in database or in session variable.
(Documentation: https://laravel.com/docs/5.8/eloquent)
You can store otp in database like
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
//CHANGES
User::where('phone_number',$req->txtnumber)->update(['otp'=>$otp]);
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
you can retrieve it using eloquent in Laravel using
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
//CHANGES
$otp = User::where('phone_number', $phone_number)->first()->otp;
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}
after entering the correct otp clear that in database.
Or you can use session.you can use session in two ways
1.php default session
2.Laravel Session
let us see php default session
(documentation:https://www.php.net/manual/en/book.session.php)
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
//CHANGES
session_start();
$_SESSION['otp'] = $otp
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
you can retrieve it by
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
//CHANGES
session_start();
$otp = $_SESSION['otp']
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}
let us use laravel session
(documentation: https://laravel.com/docs/5.2/session)
//important
use Illuminate\Support\Facades\Session;
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
//CHANGES
Session::put('otp',$otp)
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
you can retrieve it by
//important
use Illuminate\Support\Facades\Session;
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
//CHANGES
$otp = Session::get('otp') //best way to use is flash. see the full documentation
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}

how to pass session variable into view using laravel4

I want to pass logged in id into my view page.i got the id in the function of user_login_submits.
Actually i want to get the id in one more function in the same controller.
how to get the session id in controller..
Normally session put its enough i did like that.
Here is my code anyone can check and tel me what need to change here
Controller
public function user_login_submits()
{
$inputs = Input::all();
$uname = Input::get('username');
$password = Input::get('password');
$logincheck=Userlogin::login_checks($uname,$password);
if($logincheck == 1)
{
$id=Session::get('customer_id');
return Redirect::to('businessprio/create_news?p=1');
}
else if($logincheck == 0)
{
//echo "fail";
return Redirect::to('businessprio/create');
}
}
Model
public static function login_checks($uname,$password)
{
$check = DB::table('customer_login')
->where('username','=',$uname)
->where('password','=',$password)->get();
if($check)
{
//Session::put(['customer_id'=>'value']);
Session::put('customer_id', $check[0]->customer_id);
Session::put('username', $check[0]->username);
return 1;
}
else
{
return 0;
}
}
I won't pass it to model, instead i would do it in controller itself,
public function user_login_submits()
{
$uname = Input::get('username');
$password = Input::get('password');
$check = DB::table('customer_login')
->where('username','=',$uname)
->where('password','=',$password)->count();
if($check==1)
{
$id=Session::get('customer_id');
return Redirect::to('businessprio/create_news?p=1');
}
else
{
return Redirect::to('businessprio/create');
}
}
Recommendation :
But i would strongly recommend you to do it by Auth::attempt i.e., to follow the clean one
public function user_login_submits()
{
if (Auth::attempt(['email' => $userEmail, 'password' => $userPassword])) {
return Redirect::to('businessprio/create_news?p=1');
}
else
{
return Redirect::to('businessprio/create');
}
}
If you do so, then you can access the Default checking for authenticated user
Auth::check()
Get the Logged in user details by
Auth::user()->id
Auth::user()->username
Note : To use default Auth::attempt you should use the User Model too.

laravel auth and session not persisting

The laravel session and auth I use have some problem in server, but working really fine in localhost . I will show.
Route
Route::get('/signin', 'PageController#signin');
Route::get('/signup', 'PageController#signup');
Route::get('/terms', 'PageController#terms');
Route::resource('/', 'PageController');
Route::controller('user', 'UserController');
PageController
public function index() {
if (Auth::check()) {
return View::make('user.index');
} else {
return View::make('landing');
}
}
UserController
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Redirect::to('/');
} else {
$data['success'] = false;
}
} else {
$data['success'] = false;
}
return $data;
}
Auth::check() fails in pagecontoller even after login succeds. But if I change the code to
UserController
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Return View::make(user.index);
} else {
$data['success'] = false;
}
} else {
$data['success'] = false;
}
return $data;
}
I get the index page and if I click the link of the home I get the landing page not the index page.
I guess I clarify my problem, I have gone through may solution replied earlier in same manner question nothing working.
I don't think its the server problem because another laravel application is working fine in same server.
Please help.
Your query seems to be incomplete, from what i understand you are able to get the index page after passing the authentication check only once, and that is by using this method:
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Return View::make(user.index);
}
else {
$data['success'] = false;
}
}
else {
$data['success'] = false;
}
return $data;
}
try using a different browser to make sure there is no cookie storage restrictions in the client side and check the app/config/session.php file and see if you have configured the HTTPS Only Cookies according to your needs.
and just on an additional note this line "return Return View::make(user.index);" looks vague.

Resources