I'm working on integrating 2-factor authentication using https://github.com/ChristianRiesen/otp on a Laravel 4.1.23 site: the secret gets generated fine, the QR code image too, and Google Authenticator is able to scan the image.
However, the code generated on my iPhone inside the Google Authenticator application does not validate. I've followed the example from the README.md.
In my Controller, I have code like the following:
$secret = GoogleAuthenticator::generateRandom();
$url = GoogleAuthenticator::getQrCodeUrl('totp', 'MySite:'.Auth::user()->email, $secret);
// Save the secret with the user's data
if (!Auth::user()->secret) {
Auth::user()->secret = $secret;
Auth::user()->save();
}
return View::make('2fa')->with('secret', $secret)->with('url', $url);
Then in my view (2fa.blade.php), I have code like the following:
<strong>Secret Key:</strong> {{ $secret }}
<strong>QR Code</strong> <br/>
<img src="{{ $url }}" />
<form action="/confirm_key" method="post">
<label for="key">Enter the generated key:</label>
<input type="text" name="key" id="key"/>
<input type="submit" id="submit" value="Confirm Key"/>
</form>
That all appears to be working. The form posts to the following controller function:
public function postTwoFactorAuthentication() {
// Now how to check
$otp = new Otp();
if ($otp->checkTotp(Base32::decode(Auth::user()->secret), Input::get('key'))) {
return 'Verified!';
}
// Wrong key
else {
return 'Invalid key!'
}
}
This is following usage example from the repo pretty closely, but the key (token) never validates. Am I missing something here? Is Laravel screwing with something?
Any help is appreciated.
Related
I'm new to programming, currently searching for ways to only send a single email like what Web lesson had taught me (bulk email I don't want), here is the link:'How to Send Bulk Email in PHP using PHPMailer with Ajax JQuery'.
I have two places to run this function, one is index.blade.php, and one is ClientController.
index.blade.php
<form action="{{ route('clients.destroy',$client->id) }}" method="POST">
<a href="{{ route('clients.edit',$client->id) }}">
<i class="fas fa-pencil-alt"></i>
</a>
<button type="button" name="email_button" class="email_button"
id="{{ $client->_id }}"
method="post" action="single" email_data="{{ $client->email }}">
<i class="fas fa-envelope"></i>
</button>
#csrf
#method('DELETE')
<button type="submit"><i class="far fa-trash-alt"></i></button>
</form>
here's my JQuery and Ajax at the bottom of index.blade.php
<script>
$(document).ready(function(){
$('.email_button').click(function(){
$(this).attr('disabled', 'disabled');
var id = $(this).attr("id");
var action = $(this).data("action");
var email_data = $(this).data("email_data");
$.ajax({
url:'{{ route('send-email-test') }}',
method:'POST',
data:{email_button: email_data, _token: '{{csrf_token()}}'},
beforeSend:function(){
$('#'+id).html('Sending...');
$('#'+id).addClass('uk-text-danger');
},
success:function(data){
if(data = 'ok')
{
$('#'+id).text('Success');
$('#'+id).removeClass('uk-text-danger');
$('#'+id).removeClass('uk-text-info');
$('#'+id).addClass('uk-text-success');
}
else
{
$('#'+id).text(data);
}
$('#'+id).attr('disabled', false);
}
});
});
});
</script>
Here's my route and script
// Here's my script in layout
<script src="{{ asset('js/jquery.min.js') }}" type="text/javascript"></script>
// Here's my route
Route::post('send-email-test','ClientController#send_mail')->name('send-email-test');
After creating the index, I'm trying to use ajax to route to my controller.
ClientController
namespace App\Http\Controllers;
use App\Models\Company\Client\Client;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
class ClientController extends Controller
{
public function send_mail()
{
if(isset($_POST["email_data"]))
{
require 'vendor/phpmailer/phpmailer/src/Exception.php';
require 'vendor/phpmailer/phpmailer/src/PHPMailer.php';
require 'vendor/phpmailer/phpmailer/src/SMTP.php';
require 'class/class.phpmailer.php';
$output = '';
foreach($_POST['email_data'] as $row)
{
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->Port = '587'; //Initially is 465, doesn't work
$mail->SMTPAuth = true;
$mail->Username = 'xxxxxxx#gmail.com';
$mail->Password = 'xxxxxxx';
$mail->SMTPSecure = 'tls'; //Initially is SSL, doesn't work either
$mail->From = 'xxxxxxxx#gmail.com';
$mail->FromName = 'Coverage Giant';
$mail->addAddress($row["email_data"]);
$mail->To($row["email_data"]);
$mail->WordWrap = 50;
$mail->IsHTML(true);
$mail->Subject = 'Welcome To Coverage Giant';
$mail->Body = '
<p>Sed at odio sapien. Vivamus efficitur</p>
';
$mail->AltBody = '';
$client_email = $mail->Send();
if($$client_email["code"] == '400')
{
$output .= html_entity_decode($client_email['full_error']);
}
}
if($output == '')
{
echo 'ok';
}
else
{
echo $output;
}
}
}
}
As you can see, I'm doing something opposite from the Web lesson because Webslesson uses index.php and send_mail.php, I'm using index.blade.php and ClientController. Since after applying what Websleeson has shown to me, it doesn't function well, so I reverse the engine a bit, thinking maybe it might work the other way round.
My problem now is, my JQuery and Ajax are functioning correctly, and it's able to route to ClientController from index.blade.php. Still, after routing to the controller, it seems that I can't send a single email using PHPMailer; maybe something is wrong with my controller and PHPMailer?
I was also wondering, is there a better way to send a single email?
BTW, I'm using MongoDB and Laravel. My UI is Uikit instead of Boostrap.
Since you're using Laravel, it is indeed easier to use Laravel's built-in mail classes, but you've got this far with PHPMailer so I'll help you clean this up...
You're loading two different copies of PHPMailer at the same time. This is very likely to cause major problems! class.phpmailer.php is from a very old version that you should not be using. It also looks like you have based your code on a very old PHPMailer example – use the latest ones from the repo.
If you're using composer properly (which you should be given you've set up a Laravel project), you should not need any of those require lines - the autoloader will load the classes for you if you added phpmailer/phpmailer to your composer.json requires, as described in the readme.
Port should be an integer, not a string:
$mail->Port = 465;
There is no To() method; call addAddress to add recipients.
When sending multiple messages in a loop, create the instance outside the loop, and re-use it for each message, remembering to call $mail->clearAddresses(); at the end of each iteration, as shown in the mailing list example.
This is peculiar code, and wrong because send() returns a boolean, not an array:
if($$client_email["code"] == '400')
and it doesn't provide code or full_error properties. You're looking for ErrorInfo, as shown in all the examples.
Overall, always refer to the original docs and examples when using any open source package – making up random stuff and expecting it to work is not going to serve you well.
i dont know how hidden password on url
i got problem like this http://127.0.0.1:8000/bulletin/%201/edit?passwordC=11111&page=1
My View
<form>
<div class="form-row" style="specified-width:200; position: absolute; bottom:0; margin-bottom:10">
<input style="width:150px" type="password" placeholder="Password" name="passwordC">
<input type="hidden" value="{{$buletin->currentPage()}}" name="page">
<button style="margin:0 5px" formAction="/bulletin/ {{ $tampil_B->id }}/deleteOper" type="submit" class="btn btn-danger">Delete</button>
<button formAction='(url(edit))' type="submit" class="btn btn-primary">Edit</button>
</div>
</form>
My Router
route::get('/bulletin/{id}/edit','BulletinController#edit');
my controller
public function edit (Request $request, $id)
{
$buletin = \App\Dashboard::find($id);
$url = "/?page={$request->page}";
if(is_null($buletin->password)){
$request->session()->flash('failed', 'Cant Edit Because this post not had been set password ');
return view('bulletin.edit_nopass', ['buletin' => $buletin,'url'=> $url]);
}
if (hash::check($request->passwordC,$buletin->password)){
return view ('bulletin.edit', ['buletin' => $buletin, 'url'=> $url]);//save and go back to card
} else {
$request->validate([
'passwordC' => 'required|required_with:password|same:password'
],[
'passwordC.required_with' => "Password not match",
'passwordC.required' => "Password Required",
'passwordC.same' => "The Password You Entered Do Not Match.Please Try Again"
]);
}
The issue is a byproduct of how you have written this solution. To remove the password from the URL, you will have to find a different mechanism to get to the edit page.
As it currently stands, you are doing a GET request to the edit page from the form, and because it is a GET request, the form parameters are sent in the URL.
From the edit controller method you are then returning a view, so the URL is never re-written.
That is why you have this problem, as to how you could solve this, there are many options; you could post to an endpoint that stores the approval in a session that you then check in middleware, or in the controller, and then return the view. You could use the reconfirm password middleware from Laravel. Or even a POST-REDIRECT-GET pattern, where you post the form and then redirect to the edit page from there with whatever you need to do to protect the edit endpoint.
There are many options, but its impossible to tell you how to solve this problem given that you need to rethink how you will solve it.
First of all it is not correct to send with GET .But if it is very vital you have two way:
1.use encrypt .but it is not safe too.because there is even online sites that can decrypte .
2.use Hash:make . Hashing is an unilateral.It means that you can not dehash it
so I've got this weird problem where if I make a Put request through axios in Vue, it's sending it to the wrong route.
It's part of a simple CRUD through a Laravel APIresource. Get and post work fine.
This is the form:
<form #submit.prevent="editType" method="post" class="mb-4">
<label v-if="user.gender === 'man'" for="single_male">Enkel<input type="checkbox" name="type" :id="single_male" :value="types.single_male" v-model="checkedType" #change="showSaveButton = true"></label>
<label v-if="user.gender === 'vrouw'" for="single_female">Enkel<input type="checkbox" name="type" :id="single_female" :value="types.single_female" v-model="checkedType" #change="showSaveButton = true"></label>
<label v-if="user.gender === 'man'" for="double_male">Dubbel mannen<input type="checkbox" name="type" :id="double_male" :value="types.double_male" v-model="checkedType" #change="showSaveButton = true"></label>
<label v-if="user.gender === 'vrouw'" for="double_female">Dubbel vrouwen<input type="checkbox" name="type" :id="double_female" :value="types.double_female" v-model="checkedType" #change="showSaveButton = true"></label>
<label for="double_mix">Dubbel gemengd<input type="checkbox" name="type" :id="double_mix" :value="types.double_mix" v-model="checkedType" #change="showSaveButton"></label>
<button type="submit" v-if="showSaveButton">Opslaan</button>
</form>
My update function:
public function update(Request $request, $id)
{
$user_id = auth('api')->user()->id;
$type = Type::where('user_id' ,'=', $user_id)->first();
$type->single_male = $request->input('single_male');
$type->single_female = $request->input('single_female');
$type->double_male = $request->input('double_male');
$type->double_female = $request->input('double_female');
$type->double_mix = $request->input('double_mix');
$type->save();
return redirect()->back();
}
my method:
editType() {
let types = this.types;
let data = {
single_male: this.single_male,
single_female: this.single_female,
double_male: this.double_male,
double_female: this.double_female,
double_mix: this.double_mix,
};
axios.put('/types/'+types.id, data)
.then(request => this.successfulEdit(request))
.catch(() => this.failed())
},
successfulEdit() {
alert("Voorkeuren succesvol bijgewerkt!");
}
and my route:
Route::apiresource('types','TypeController');
When I make a put request, I can see in the Developer Tools that it tries to make the request to the current url, which of course gives a 405 method not allowed error.
When I change the axios request to just ('/types', data), it does follow the specified route but of course gives the 405 error too since the put method requires an id. Hardcoding to e.g. '/types/4/' also leads to using the current url.
Am I missing somethng or what's wrong? Thanks in advance guys!
Found the problem. The return redirect()->back(); was the culprit. Thanks y'all!
From Laravel docs. https://laravel.com/docs/5.8/routing
Routes defined in the routes/api.php file are nested within a route
group by the RouteServiceProvider. Within this group, the /api URI
prefix is automatically applied
So try to add /api before your current request URL like
axios.put('/api/types/'+types.id, data)
Hi i am trying to integrate adyen payment gateway in my project.
I have used following PHP SDK Adyen PHP SDK
i have followed the steps mentioned in the sdk to generate client side encryption and passed those encrypted value to server side to perform payment. But i was stuck with a error message "Unable to Decrypt data"
Following is my sample code,
Frontend :
<script type="text/javascript" src="https://test.adyen.com/hpp/cse/js/MY_LIBRARY_TOKEN.shtml"></script>
<form method="POST" id="adyen-encrypted-form">
<input placeholder="number" type="text" size="20" data-encrypted-name="number" value="2223520443560010" />
<input placeholder="holderName" type="text" size="20" data-encrypted-name="holderName" value="Ashok" />
<input placeholder="expiryMonth" type="text" size="2" data-encrypted-name="expiryMonth" value="10" />
<input placeholder="expiryYear" type="text" size="4" data-encrypted-name="expiryYear" value="2020" />
<input placeholder="cvc" type="text" size="4" data-encrypted-name="cvc" value="737" />
<input type="hidden" value="<?php echo date('Y-m-d\TH:i:sO'); ?>" data-encrypted-name="generationtime"/>
<input type="submit" value="Pay"/>
</form>
<script>
// The form element to encrypt.
var form = document.getElementById('adyen-encrypted-form');
var options = {};
// Bind encryption options to the form.
var encryptedBlobFieldName = "myFieldName";
options.name = encryptedBlobFieldName;
options.onsubmit = function(e) {
var encryptedData = form.elements[encryptedBlobFieldName].value;
// Encrypted form detials
console.log(encryptedData);
e.preventDefault();
};
var result = adyen.createEncryptedForm(form, options);
</script>
I get the encrypted value from above submit action with the test deails as i have populated in the form. (i.e) encryptedData
Server Code :
$client = new \Adyen\Client();
$client->setApplicationName("Adyen PHP Api Library Example");
$client->setUsername("WS_USERNAME");
$client->setPassword("WS_USER_PASSWORD");
$client->setEnvironment(\Adyen\Environment::TEST);
$service = new \Adyen\Service\Payment($client);
$result = $service->authorise($params);
Following is the values i pass to authorise method,
Array(
[amount] => Array
(
[value] => 19
[currency] => GBP
)
[reference] => payment-test
[merchantAccount] => MERCHANT_ACCOUNT_CODE
[additionalData] => Array
(
[card.encrypted.json] => 'ENCRYPTED_DATA_FROM_FRONT_END'
)
)
Am not sure what am i doing wrong, from the server side i receive a error as unable to decrypt the data. Please assist me to resolve this issue
Are you trying to make a payment without a page refresh?
In that case you should indeed create the field to encrypt yourself, in your case you called it 'myFieldName'. If you add that to your form you should be good to go. Let me know when that doesn't work.
You need to be using a offset with a colon seperating hour and minute.
Change your date generation from
echo date('Y-m-d\TH:i:sO');
to
echo date('Y-m-d\TH:i:sP');
I found the problem. The problem is after generating the token from frontend via CSE i have passed those values to server side via GET api. So there is some additional characters added in the encrypted string. (the data passed in url was encrypted using url encryption) .
I have changed the server API method to post and it worked perfectly.
In account form fields or user registration page form fields for First name and Last name, when i place the following JS code :
<script>alert("Here")</script>
It is saved and is run on page load. This is very strange, because i checked the template files and values are escaped as below:
<?php echo $this->escapeHtml($this->getObject()->getFirstname()) ?>
I have also confirmed if i am in correct template file by changing the label of field.
I have read the following questions and tried to used them but did not worked for me.
https://magento.stackexchange.com/questions/569/how-to-escape-output-data
https://magento.stackexchange.com/questions/8179/is-there-a-generic-way-i-can-apply-input-filtering-to-magento-form-processing
Regarding to the observer method, it works, but when i try to login to magento admin, i cant, but when iremove the observer, i can login again.
Check the two attached screenshots.
Kindly help me with this issue.
Thank you
I have created an observer. For login forms at admin and front end (and may be some other forms), the form fields for user name and password are in array format like below:
<input type="text" id="username" name="login[username]" value="" class="required-entry input-text">
<input type="password" id="login" name="login[password]" class="required-entry input-text" value="">
TO fix this issue, i have modified the code in observer as below:
public function sanitizeParams($observer)
{
if(!Mage::app()->getStore()->isAdmin())
{
$post = Mage::app()->getRequest()->getParams();
foreach($post as $pkey => $pvalue)
{
if(is_array($post[$pkey]))
{
foreach($post[$pkey] as $key => $value)
{
$post[$pkey][$key] = filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
}
}
else
{
$post[$pkey] = filter_var($pvalue, FILTER_SANITIZE_SPECIAL_CHARS);
}
}
$_POST = $post;
}
}
And it fixed my problem, and is working fine now.
Thanks.