GoToWebinar Webhook Signature verification fails - laravel

I am trying to verify webhook signature for GoToWebinar webinar.created event.
Docs: https://developer.goto.com/guides/HowTos/08_HOW_webhooks/
My Middleware (Laravel):
public function handle(Request $request, Closure $next)
{
if (! $this->verifyGoToWebinarWebhookSignature($request)) {
abort(401);
}
return $next($request);
}
private function verifyGoToWebinarWebhookSignature(Request $request):bool
{
return ($request->header('x-webhook-signature') == $this->calculateHmac($request));
}
private function calculateHmac(Request $request):string
{
$secret = '12345';
$signature = $request->header('x-webhook-signature-timestamp');
$payload = json_encode($request->all(), true);
$signaturePayload = $signature . ':' . $payload;
return base64_encode(hash_hmac('sha256', $signaturePayload, $secret, true));
}
The comparison always returns false. Tested on real data. Can't figure out what I did wrong.

Was using the wrong secret, the API allows to create multiple secret keys but if you do not store them there is not way to match them to the x-webhook-secretkey-id in the request header.

Related

I want to download a excel file through Checkbox Unique ID in laravel, I am using Maatwebsite\Excel Here

My Controller File
public function enquiryExport($id, Request $request)
{
$id[] = $request->explode(",",$id);
return Excel::download(new EnquiryExport($id), 'enquiry.xlsx');
}
and My Export File
protected $id;
function __construct($id) {
$this->id = $id;
}
public function collection()
{
return Enquiry::whereIn('id',explode(",",$this->id))->get();
/* return Enquiry::all(); */
}
Route is like
Route::get('enquiryExport', 'enquiryController#enquiryExport');
Still I am getting this error
"message": "Too few arguments to function App\\Http\\Controllers\\enquiryController::enquiryExport(), 1 passed and exactly 2 expected",
I am checkbox id through AJAX here.
The problems is your Route method.
Get method: the query string (name/value pairs) is sent in the URL of a GET request
Post method: the data sent to the server with POST is stored in the request body of the HTTP request
If you use Get method: try this (I have just read it, not tried)
Route::get('enquiryExport/{id}', 'enquiryController#enquiryExport')->name('enquiryExport');
Submit
If you use Post method: try this (I am used to use this)
Route::post('enquiryExport', 'enquiryController#enquiryExport');
public function enquiryExport(Request $request)
{
return Excel::download(new EnquiryExport($request->input('id')), 'enquiry.xlsx');
}
You can read more here: https://www.w3schools.com/tags/ref_httpmethods.asp
Try this
In controller:
public function enquiryExport(Request $request, $id)
{
return Excel::download(new EnquiryExport($request->id), ''.date('Y-m-d'). '.xlsx', \Maatwebsite\Excel\Excel::XLSX);
}
In Export File:
protected $id;
function __construct($id) {
$this->id = $id;
}
public function collection()
{
return Enquiry::where('id', $this->id)->get();
}
public function map($enquiry): array
{
return [
// $enquiry->WRITE YOUR RECORDS,
// ...
];
}
public function headings(): array
{
return [
//NAME HEADINGS(TITLE) OF YOUR RECORDS IN SIDE SINGLE QUOTATION,
// ...
];
}
In Route:
Route::get('enquiryExport/{id}', 'enquiryController#enquiryExport');

How to verifiy JWT on a single route in Laravel

I have a single route in Laravel on which I need to verify the JWT on header if it is authorized and not expired. How can I do that?
In Javascript its really easy, but don`t know how in Laravel.
Here's the code:
public function update(Request $request){
$header = $request->header('Authorization');
$token = $request->bearerToken();
$secret = env('EXAMPLE_SECRETE');
$verified = here i want to verify the jtw /$token
if (!verified)
return 'something here'
else
>>code here after verified
}
First of install below package
composer require firebase/php-jwt
And then you can create a middleware in order to verify Token or expired, below is a complete code of middlware
namespace App\Http\Middleware;
use Closure;
use Exception;
use App\User;
use Firebase\JWT\JWT;
use Firebase\JWT\ExpiredException;
class JwtTokenMiddleware
{
public function handle($request, Closure $next, $guard = null)
{
$token = $request->bearerToken();
if (!$token) {
// Unauthorized response if token not there\
}
try {
$credentials = JWT::decode($token, env('JWT_SECRET'), ['HS256']);
//You can get credentials that you have set up while generating token
$user = User::findOrFail($credentials->sub)->setAuthUser();
$request->auth = $user;
} catch (ExpiredException $e) {
// Token expired response
} catch (Exception $e) {
// Handle unknow error while decoding token
return response()->json([
}
return $next($request);
}
}

Response must be a string on socialite facebook

UnexpectedValueException
The Response content must be a string or object implementing __toString(), "object" given.
public function redirectToProvider()
{
/* echo "redirect checking";*/
return Socialite::driver('facebook');
}
public function handleProvidercallback()
{
/* echo "callback coming";*/
$user = Socialite::driver('facebook')->user();
dd($user);
//return $user->name;
}
You need to call the redirect function on the driver
return Socialite::driver('facebook')->redirect();
From the docs
Hope this helps

JWT Authentication user_not_found Tymon

I have set up Tymon Package for JWT Authentication. In case of new user sign up or login I get the token successfully. But when I pass the token to the Laravel JWT I get an error as user not found.
controller code
public function authenticate()
{
$credentials = request()->only('user_name','password');
try{
$token = JWTAuth::attempt($credentials);
if(!$token){
return response()->json(['error'=>'invalid_credentials'],401);
}
}
catch(JWTException $e){
return response()->json(['error'=>'something went wrong'],500);
}
return response()->json(['token'=>$token],200);
}
public function register()
{
$user_name = request()->user_name;
$c_name = request()->company_name;
$accessibility_level = request()->accessability_level;
$password = request()->password;
$contact_number = request()->contact_number;
$address = request()->address;
$user = User::create([
'user_name'=>$user_name,
'c_name'=>$c_name,
'accessibility_level'=>$accessibility_level,
'password'=>bcrypt($password),
'contact_number'=>$contact_number,
'address'=>$address
]);
$token = JWTAuth::fromUser($user);
return response()->json(['token'=>$token],200);
}
no problem with the above code works fine.
But when I try to access some data with JWT validation I get an error as USER_NOT_FOUND. I have passed the Token which I have got as an header through Postman.
Route Code
Route::get('/some_route','some_controller#index')->middleware('jwt.auth');
And the jwt.php is also set with the correct identifier which I have used in the model(Primary key)
'identifier' => 'user_name',
The JWT identifier doesn't work by simply modifying the config because it's hardcoded as id in the code for some reason
You can of course use the setIdentifier method before calling any other JWTAuth methods to set the identifier.
Here's how:
public function authenticate()
{
$credentials = request()->only('user_name','password');
try{
$token = JWTAuth::setIdentifier('user_name')->attempt($credentials);
if(!$token){
return response()->json(['error'=>'invalid_credentials'],401);
}
}
catch(JWTException $e){
return response()->json(['error'=>'something went wrong'],500);
}
return response()->json(['token'=>$token],200);
}
Then create a custom middleware for jwt authentication:
public function handle($request, \Closure $next)
{
if (! $token = $this->auth->setIdentifier('user_name')->setRequest($request)->getToken()) {
return $this->respond('tymon.jwt.absent', 'token_not_provided', 400);
}
try {
$user = $this->auth->authenticate($token);
} catch (TokenExpiredException $e) {
return $this->respond('tymon.jwt.expired', 'token_expired', $e->getStatusCode(), [$e]);
} catch (JWTException $e) {
return $this->respond('tymon.jwt.invalid', 'token_invalid', $e->getStatusCode(), [$e]);
}
if (! $user) {
return $this->respond('tymon.jwt.user_not_found', 'user_not_found', 404);
}
$this->events->fire('tymon.jwt.valid', $user);
return $next($request);
}

Laravel API-Auth-Guard is not case-sensitive?

i'm prototyping an API with Laravel and noticed that the API-Token is not case-sensitive when using the standard Auth-Guard for API. So api_tokens like 'CVC' and 'cvc' are treated the same.
Is that an expected behaviour? Is that ideal in regard of security? Dont think so, even with a 60-byte-string, or what do you think? And is there a way to change that?
Thanks for your thoughts!
Carsten
This shouldn't be the case. Laravel attempts to resolve the token in several ways first
* Get the token for the current request.
*
* #return string
*/
public function getTokenForRequest()
{
$token = $this->request->query($this->inputKey);
if (empty($token)) {
$token = $this->request->input($this->inputKey);
}
if (empty($token)) {
$token = $this->request->bearerToken();
}
if (empty($token)) {
$token = $this->request->getPassword();
}
return $token;
}
Where that method is invoked when attempting to resolve an instance of the user:
/**
* Get the currently authenticated user.
*
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
$user = null;
$token = $this->getTokenForRequest();
if (! empty($token)) {
$user = $this->provider->retrieveByCredentials(
[$this->storageKey => $token]
);
}
return $this->user = $user;
}
And the provider in this case is the DatabaseUserProvider, which the method retrieveByCredentials performs a strict case-sensitive check using the Database Factories ->where() method, no like is used, you can see that here:
public function retrieveByCredentials(array $credentials)
{
// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// generic "user" object that will be utilized by the Guard instances.
$query = $this->conn->table($this->table);
foreach ($credentials as $key => $value) {
if (! Str::contains($key, 'password')) {
$query->where($key, $value);
}
}
// Now we are ready to execute the query to see if we have an user matching
// the given credentials. If not, we will just return nulls and indicate
// that there are no matching users for these given credential arrays.
$user = $query->first();
return $this->getGenericUser($user);
}
So no, your case is not typical, and likely there are other components in play here that we're not privy to.

Resources