antonioribeiro / google2fa

A One Time Password Authentication package, compatible with Google Authenticator.
MIT License
1.83k stars 199 forks source link

Uncaught Error: Call to a member function input() on null in #102

Closed ghost closed 6 years ago

ghost commented 6 years ago

I have sort of the same problem as what JordyKroeze had. Even if I have entered the TOTP from Authenticator Plus after I scanned the QR code, it only generate Uncaught Error: Call to a member function input() on null in .... Why?

Here's is my current code:

use PragmaRX\Google2FA\Google2FA;

$google2fa = new Google2FA();
$tfa_secretkey = $google2fa->generateSecretKey();
$input = $_POST['textfield-verify-code'];    # This is the input that the user enters theirs TOTP
$secret = $request->input($input);
$window = 8;
$valid = $google2fa->verifyKey($tfa_secretkey, $secret, $window);

echo $valid;
nztim commented 6 years ago

$secret = $request->input('secret'); is an example of how to get the user input. In your code, the equivalent line is $input = $_POST['textfield-verify-code']; so you would supply $input to the verifyKey method as the secret.

There is another issue with the code:

$tfa_secretkey = $google2fa->generateSecretKey();
$input = $_POST['textfield-verify-code'];
$valid = $google2fa->verifyKey($tfa_secretkey, $secret, $window);

If you generate a new, random secret key the user input won't verify against it. $tfa_secretkey needs to have been the one the user previously scanned into their authentication app.

In the documentation it looks like this:

$valid = $google2fa->verifyKey($user->google2fa_secret, $secret);

$user->google2fa_secret is referring to the user's existing secret key.

ghost commented 6 years ago

Thank you, but I keep getting the same error message. Have I missed something?

use PragmaRX\Google2FA\Google2FA;

$google2fa = new Google2FA();
$tfa_secretkey = $google2fa->generateSecretKey();
$input = $_POST['textfield-verify-code'];    # This is the input that the user enters theirs TOTP
$secret = $request->input('secret');
# $window = 8;
$valid = $google2fa->verifyKey($user->google2fa_secret, $secret);

echo $valid;

UPDATE 1 I got now a new error message from the code below: Uncaught PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException: Secret key is too short. Must be at least 16 base32 characters in

use PragmaRX\Google2FA\Google2FA;

$google2fa = new Google2FA();
$tfa_secretkey = $google2fa->generateSecretKey(16);
$input = $_POST['textfield-verify-code'];    # This is the input that the user enters theirs TOTP
# $secret = $request->input('secret');
# $window = 8;
$valid = $google2fa->verifyKey($user->google2fa_secret, $input);

echo $valid;

UPDATE 2 I have read your answer once more and changed a lot in my code. Still, I'm getting the same error message as in update 1.

site-settings.php

    require_once $url_homebase.'vendor/autoload.php';

    # USE
    use Swap\Builder;
    use DeviceDetector\DeviceDetector;
    use DeviceDetector\Parser\Device\DeviceParserAbstract;
    use Hackzilla\PasswordGenerator\Generator\ComputerPasswordGenerator;
    use PragmaRX\Google2FA\Google2FA;

    # VARIABLES
    $google2fa = new Google2FA();
    $secretKey = $google2fa->generateSecretKey(64);
    $generator = new ComputerPasswordGenerator();
    $generator->setUppercase()->setLowercase(false)->setNumbers()->setSymbols(false)->setLength(18);
    $generate_password = $generator->generatePasswords(1);
    $builder = new Builder();
    $swap = $builder->add('fixer')->build();
    # $rate = $swap->historical('SEK/'.$currency_to, (new \DateTime())->modify('-1 day'));

?>

site-settings-twfa.php

<?php

    # REQUIRE
    # require_once '../../configs/site-settings.php';
    require_once '../../configs/site-connection.php';
    require_once '../../configs/site-functions.php';
    require_once '../../configs/site-database.php';
    require_once '../../vendor/autoload.php';
    use PragmaRX\Google2FA\Google2FA;
    $google2fa = new Google2FA();

    # VARIABLES
    $secret = $_POST['textfield-verify-code'];
    $valid = $google2fa->verifyKey($user['data_tfa_secret'], $secret, 4);

    echo $valid;

?>

If I change $secretKey = $google2fa->generateSecretKey(64); to the following:

$prefix = str_pad($user['id_user'], 10, 'X');
$secretKey = $google2fa->generateSecretKey(32, $prefix);

I'll get the following error message:

Fatal error: Uncaught PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException: This secret key is not compatible with Google Authenticator. in H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php:118 Stack trace: #0 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php(105): PragmaRX\Google2FA\Google2FA->checkGoogleAuthenticatorCompatibility('GFMFQWCYLBMFQWC...') #1 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php(29): PragmaRX\Google2FA\Google2FA->validateSecret('GFMFQWCYLBMFQWC...') #2 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php(70): PragmaRX\Google2FA\Google2FA->generateBase32RandomKey(32, '1XXXXXXXXX') #3 H:\www\min-ekonomi\configs\site-settings.php(80): PragmaRX\Google2FA\Google2FA->generateSecretKey(32, '1XXXXXXXXX') #4 H:\www\min-ekonomi\index.php(4): require_once('H:\\www\\min-ekon...') #5 {main} thrown in H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php on line 118
nztim commented 6 years ago

I think the first code block looked good apart from the $secret = $request->input('secret');

Update 1: the user input will not be able to validate against a secret key that has been just created. If $user->google2fa_secret is not defined that would explain the error.

Update 2: The first two code blocks have issues but this should work, check that everything is defined:

$secret = $_POST['textfield-verify-code'];
$valid = $google2fa->verifyKey($user['data_tfa_secret'], $secret, 4);

The last error is caused by the code not producing a GA-compatible secret key. Applying the solution provided in the docs:

$prefix = str_pad($user['id_user'], 10, 'X');
$prefix = str_pad($prefix, pow(2,ceil(log(strlen($prefix),2))), 'X');
$secretKey = $google2fa->generateSecretKey(32, $prefix);

My suggestion would be to keep things as simple as possible to start with in order to get it working properly. Just do the bare minimum with defaults and go from there.

ghost commented 6 years ago

Thank you for your answer. Unfortunately I'll get the same error message when I tested your code. Everything is defined, as you can see in UPDATE 1.

I tested to add $google2fa->setEnforceGoogleAuthenticatorCompatibility(false); which removed the error message that is mentioned in UPDATE 2. I scanned the QR-code that had this key: GFMFQWCYLBMFQWCYLBMFQWCYLASYUJG2A5YY5I7XJFWPOL27OAHFQN6DZ7. After that, I tested to enter the TOTP from the app. Here's the result from the console:

<br />
<b>Notice</b>:  Undefined variable: user in <b>H:\www\min-ekonomi\ajax\post\save-settings-twfa.php</b> on line <b>16</b><br />
<br />
<b>Fatal error</b>:  Uncaught PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException: Secret key is too short. Must be at least 16 base32 characters in H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php:194
Stack trace:
#0 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php(49): PragmaRX\Google2FA\Google2FA-&gt;oathHotp('', 50777019)
#1 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php(332): PragmaRX\Google2FA\Google2FA-&gt;findValidOTP(NULL, '273234', 4, 50777019, 50777023, '__not_set__')
#2 H:\www\min-ekonomi\ajax\post\save-settings-twfa.php(16): PragmaRX\Google2FA\Google2FA-&gt;verifyKey(NULL, '273234', 4)
#3 {main}
  thrown in <b>H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php</b> on line <b>194</b><br />

site-settings.php

    require_once $url_homebase.'vendor/autoload.php';

    # USE
    use Swap\Builder;
    use DeviceDetector\DeviceDetector;
    use DeviceDetector\Parser\Device\DeviceParserAbstract;
    use Hackzilla\PasswordGenerator\Generator\ComputerPasswordGenerator;
    use PragmaRX\Google2FA\Google2FA;

    # VARIABLES
    $google2fa = new Google2FA();
    $google2fa->setEnforceGoogleAuthenticatorCompatibility(false);
    $prefix = str_pad($user['id_user'], 10, 'X');
    $prefix = str_pad($prefix, pow(2, ceil(log(strlen($prefix), 2))), 'X');
    $secretKey = $google2fa->generateSecretKey(32, $prefix);
    $generator = new ComputerPasswordGenerator();
    $generator->setUppercase()->setLowercase(false)->setNumbers()->setSymbols(false)->setLength(18);
    $generate_password = $generator->generatePasswords(1);
    $builder = new Builder();
    $swap = $builder->add('fixer')->build();
    # $rate = $swap->historical('SEK/'.$currency_to, (new \DateTime())->modify('-1 day'));

?>

I am sorry, but I am totally new to this kind of security method.

nztim commented 6 years ago

H:\www\min-ekonomi\ajax\post\save-settings-twfa.php(16): PragmaRX\Google2FA\Google2FA-&gt;verifyKey(NULL, '273234', 4)

That looks to me like you called verifyKey() with NULL as the secret key. Check the value of the secret key before this is called.

ghost commented 6 years ago

Aha! The file couldn't fetch user's information. That is now fixed, but it still give me an error message.


<b>Fatal error</b>:  Uncaught PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException: This secret key is not compatible with Google Authenticator. in H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php:118
Stack trace:
#0 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php(105): PragmaRX\Google2FA\Google2FA-&gt;checkGoogleAuthenticatorCompatibility('GFMFQWCYLBMFQWC...')
#1 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php(47): PragmaRX\Google2FA\Google2FA-&gt;validateSecret('GFMFQWCYLBMFQWC...')
#2 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php(191): PragmaRX\Google2FA\Google2FA-&gt;base32Decode('GFMFQWCYLBMFQWC...')
#3 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php(49): PragmaRX\Google2FA\Google2FA-&gt;oathHotp('GFMFQWCYLBMFQWC...', 50777087)
#4 H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Google2FA.php(332): PragmaRX\Google2FA\Google2FA-&gt;findValidOTP('GFMFQWCYLBMFQWC...', '726255', 4, 50777087, 50777091, '__not_set__')
#5 H:\www\min-ek in <b>H:\www\min-ekonomi\vendor\pragmarx\google2fa\src\Support\Base32.php</b> on line <b>118</b><br />```
nztim commented 6 years ago

Can you just use $secretKey = $google2fa->generateSecretKey(); to get things working?

ghost commented 6 years ago

Oh my! Now it's finally working! Many thanks for your help!

NaysKutzu commented 9 months ago

it is not Secret key is too short. Must be at least 16 base32 characters