How can I get Google Auth working with Laravel? - laravel

I'd like to know if there's an easy fix for this error that I'm getting while trying to add support for Google sign-in to my website, since I can only reproduce it while on a Laravel-based environment. Vanilla PHP applications do run just fine.
This is my relevant code:
if ($request->has('googleToken')) {
$client = new Google_Client(['client_id' => env('GOOGLE_PLATFORM_CLIENT_ID') ]);
$payload = $client->verifyIdToken($credentials['googleToken']);
if (!$payload) {
return response([ 'error' => 'Invalid token, please try using form-based authentication.' ], Response::HTTP_FAILED_DEPENDENCY);
}
$user['googleToken'] = $credentials['googleToken'];
}
I know I'm doing too relaxed validations, but please just focus on the fact that I'm just testing and I plan to change this code in the near future.
The code above, receives its data through an Axios PUT request from the frontend with the payload looking like this:
{
googleToken: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5ZmUyYTdiNjc5NTIzOTYwNmNhMGE3NTA3OTRhN2JkOWZkOTU5NjEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTkyODkzNjE3ODYzLXRscDdvaDByaTk2dTZxZGxrOXYwbHAyanQyNDlkdDNsLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTkyODkzNjE3ODYzLXRscDdvaDByaTk2dTZxZGxrOXYwbHAyanQyNDlkdDNsLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE1NTg0MDg0NTE2OTMxOTQzODU..."
mailAddress: "user#mail.com"
}
The problem is that the payload would simply return false. I decided to try to investigate the issue, so I went to the definition of verifyIdToken contained within Google_Client and, from there, jumped over to the function that finally returns to its parent, which is verifyIdToken from the class Verify.
Inside of that class, there's a pretty loose try/catch block in which I decided to try adding a generic exception case so that I could quickly print the error message for debugging. I did, and this is the output I got:
OpenSSL unable to verify data: error:0909006C:PEM routines:get_name:no start line
This is what's failing internally, and from this point on, I don't really have an idea about how to proceed since the error feels very cryptic, or at least it's not in my field of knowledge.

The OpenSSL error you quoted indicates that your client was not able to read any/further PEM-encoded data. Refer to https://www.openssl.org/docs/man1.1.1/man3/PEM_read.html.
OpenSSL unable to verify data: error:0909006C:PEM routines:get_name:no start line
Here,
'PEM routines' represents the library within OpenSSL
'get_name' is the function
'no start line' is the reason
Is you client able to access the necessary certificates/keys?

Related

Trouble faking a Laravel HttpClient response

I am trying to test the following bit of code:
DimonaClient is just a simple wrapper around a Laravel HttpClient; simplified function here:
The getDeclaration() response is a \Illuminate\Http\Client\Response
What I am trying to do in my test is:
Mock the DimonaClient class so I don't create an actual api call
"Mock" (use Laravel's Http::response()) the response I want so that I can test that a 200 w/ certain statuses dispatches the appropriate event (also mocked, but not relevant here)
My test code looks like this:
My issue(s) seem to be:
the getDeclaration() has an expectation of Illuminate\Http\Client\Response but I can't seem to create anything that will satisfy that (a new Response wants a MessageInterface, etc, etc... )
I don't actually need getDeclaration() to return anything for my testing, so I wonder if I should be mocking this differently in any case (I base this assumption on Http::response handling the internal code I'm testing for things like $response->ok(), instead of a Mockery expectation)
I feel like I'm one small step away from making this work, but going round in circles trying to hook it up correctly.
TIA!
If you are using Http Facade, you don't need to mock DimonaCient. You are nearly there with your test, but let me show you what you would have done:
/** #test */
public function it_can_handle_an_approved_submission(): void
{
Http::fake([
'*' => Http::response([
'declarationStatus' => [
'result' => DimonaDeclarationStatus::ACCEPTED,
'dimonaPeriodId' => $this->faker->numerify('############'),
],
],
]);
$dimonaDeclarationId = $this->faker->numerify('############');
// Do your normal call, and then assertions
}
Doing this, you will tell Http to fake any URL, because we are using *. I would recommend you use $this->endpoint/$declarationId so if it does not match, you will also know you did not hit the right endpoint.
I am not sure what Laravel you are using but this is available since Laravel 6+, check Http fake URLs.

Entity not Found Error in Google Classroom when creating assignment with STUDENT_COPY material

I'm programmatically submitting a Google Classroom assignment, and I'm seeing different behavior when attach a Material using the STUDENT_COPY shareMode than when I use the VIEW shareMode.
The following code seems to be working fine:
var resource = {
title: name,
description: explanation,
workType: 'ASSIGNMENT',
state: 'PUBLISHED'
};
resource.materials = [];
resource.materials.push({
driveFile: {
driveFile: {
id: 'fileId'
},
shareMode: 'VIEW'
}
});
var params = {auth: creds, courseId: courseId, resource: resource};
classroom.courses.courseWork.create(params, function (err, courseWorkResponse) {
/* handle response */
}
With that code, the assignment gets created and I can see it in Google Classroom. However, if I set the shareMode to STUDENT_COPY instead of VIEW, I get the following error:
{ Error: Requested entity was not found.
at Request._callback (/Users/.../node_modules/googleapis/node_modules/google-auth-library/lib/transporters.js:85:15)
at Request.self.callback (/Users/.../node_modules/googleapis/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/Users.../node_modules/googleapis/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/Users/.../node_modules/googleapis/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:292:16)
at emitNone (events.js:91:20)
code: 404,
errors:
[ { message: 'Requested entity was not found.',
domain: 'global',
reason: 'notFound' } ] }
The assignment is not being created in Google Classrom. However, I am seeing a [Template] copy of the Google Doc I specified in the driveFile.id being placed into my Google Drive.
I've tried this with several different documents, some of which were basically "Hello World"-level google docs, so I doubt the issue is related to the document.
Other than that, I'm not sure what could be going on. I assume there must be some sort of permissions issue somewhere, but does anybody else have a clue what might be going on?
EDIT: Further information
It seems to be an issue with "publishing" the assignment. If I set the resource.state to DRAFT, I'm able to successfully execute the coursework.create API call. I get back an instance of a CourseWork object as expected.
The problem is I need to ultimately PUBLISH the assignment. And when I try to execute the classroom.courses.courseWork.patch() api call to simply change the state from DRAFT to PUBLISHED, I end up getting the same Requested entity was not found error.
However I am able to go into Google Classroom itself, view my drafts, and click on the ASSIGN button in the application. If I do that, everything finally works! That UI flow is no good for me, though. But it does indicate that there's nothing inherently wrong, as far as I can tell, with the assignment. I just seem to be missing some (undocumented?) step that's necessary in my case.
This happens because entity does not exist yet because the students haven't accessed the assignmend yet in the classroom. So make sure they do and try again.
Reference:
Drive files that correspond to materials with a share mode of
STUDENT_COPY may not exist yet if the student has not accessed the
assignment in Classroom.

cfajaxproxy is sending invalid parameters?

For some reason that I don't understand, on my development machine can't call to function of a cfc component from a cfajaxproxy.
In my cfm document:
<cfajaxproxy cfc="#Application.CfcPath#.empleado"
jsclassname="ccEmpleado">
This works, and also I can instantiate an object to get all the functions of that cfc component:
var cfcEmpleado = new ccEmpleado();
But, when I try to call a function of that object:
var nb_Empleado = cfcEmpleado.RSEmpeladoNombreBIND(1,1);
Debug complains:
Error: The ID_EMPRESA parameter to the RSEmpeladoNombreBIND function is required but was not passed in.
I got this from Network tab on Chrome and figured out that something is generating an invalid parameter:
http://127.0.0.1/vpa/componentes/empleado.cfc?method=RSEmpeladoNombreBIND&_cf_ajaxproxytoken=[object%20Object]&returnFormat=json&_cf_nodebug=true&_cf_nocache=true&_cf_clientid=41C92098C98042112AE2B3AAF523F289&_cf_rc=0
As you can see, there's a parameter [object%20Object], that is messing around my request, and that's why it fails. I don't why is happening this. Other people has tested this, and it works, but in mine doesn't.
I have Coldfusion 9, Apache, Windows 8. Is is some configuration issue on Coldfusion, or a bug?
I can't tell if this is your error or not, but it might be. This was a problem that we had for awhile. You should consider using explicit names to avoid any confusion. Add the "js" in there.
<cfajaxproxy cfc="cfcEmpleado" jsclassname="proxyEmpleado">
var jsEmpleado = new proxyEmpleado();
I will try to find a link to an article about this very thing.

Codeception API testing: stuck at passing json payload to REST service

I found this cool tool called codeception for testing in PHP. I am liking it a lot. I started writing API test cases. But I am stuck at POSTING json payload to a REST service. How can I perform this?
I have a REST end point called /order, which accepts a JSON payload. The service is build on Laravel4, so I accept the payload in Laravel4 using Input::json()->all().
I have tried something like this
$filename = __DIR__.'/createOrder.json';
$I->haveHttpHeader('Content-Type', 'application/json');
**$I->sendPOST('order', null, array($filename));**
$I->seeResponseCodeIs(200);
$I->seeResponseIsJson();
But it gives me 500 internal server error, as my service accepts json payload and not in the form of file.
Anyone has worked on something like this before?
Thanks in advance.
I know this is an old question but for others who stumble on this, try:
$I->haveHttpHeader('Content-Type','application/json');
it definitely should work.
I got it working by doing this
$exampleData = [
'name' => 'adam',
'age' => 99
];
$json = json_encode($exampleData);
$I->sendPOST('/endpoint', $json);
For more details see this Github issues
# Sameer, I have tried and faced similar issue. I then went with a work around for this.
$filename = __DIR__.'/createOrder.json';
$I->sendPOST('order', getPostParams($filename));
Now create a new folder called "helpers" inside your suite and add "<suiteName>Helper.php" to it.
Add the following code there
function getPostParams($filename){
if(!file_exists($filename)){
print "MISSING FILE ".$filename."\n";
return;
}
$jsonData= json_decode(file_get_contents($filename));
if(!$jsonData){
print "INVALID JSON CONTENT ".$filename."\n";
return;
}
return (array)($jsonData);
}
Go to _bootstrap.php inside "tests" folder and add this
require_once('<suiteName>/helpers/<suiteName>Helper.php');
Now do a build and run the test suite. you should be able to get pass the error :)

Meteor 0.5.9: replacement for using Session in a server method?

So, I was attempting to do something like the following:
if(Meteor.isServer){
Meteor.methods({connect_to_api: function(vars){
// get data from remote API
return data;
}});
}
if(Meteor.isClient){
Template.myTpl.content = function(){
Meteor.call('connect_to_api', vars, function(err,data){
Session.set('placeholder', data);
});
return Session.get('placeholder');
};
}
This seemed to be working fine, but, of course, now breaks in 0.5.9 as the Session object has been removed from the server. How in the world do you now create a reactive Template that uses a server-only (stuff we don't want loading on the client) method call and get data back from that Method call. You can't put any Session references in the callback function because it doesn't exist on the server, and I don't know of any other reactive data sources available for this scenario.
I'm pretty new to Meteor, so I'm really trying to pin down best-practices stuff that has the best chance of being future-proof. Apparently the above implementation was not it.
EDIT: To clarify, this is not a problem of when I'm returning from the Template function. This is a problem of Session existing on the server. The above code will generate the following error message on the server:
Exception while invoking method 'connect_to_api' ReferenceError: Session is not defined
at Meteor.methods.connect_to_api (path/to/file.js:#:#)
at _.extend.protocol_handlers.method.exception ... etc etc
Setting the session in the callback seems to work fine, see this project I created on github: https://github.com/jtblin/meteor_session_test. In this example, I return data in a server method, and set it in the session in the callback.
There are 2 issues with your code:
1) Missing closing brace placement in Meteor.methods. The code should be:
Meteor.methods({
connect_to_api: function(vars) {
// get data from remote API
return data;
}
});
2) As explained above, you return the value in the session, before the callback is completed, i.e. before the callback method had the time to set the session variable. I guess this is why you don't see any data in the session variable yet.
I feel like an idiot (not the first time, not the last). Thanks to jtblin for showing me that Session.set does indeed work in the callback, I went back and scoured my Meteor.method function. Turns out there was one spot buried in the code where I was using Session.get which was what was throwing the error. Once I passed that value in from the client rather than trying to get it in the method itself, all was right with the world.
Oh, and you can indeed order things as above without issue.

Resources