A One Time Password Authentication package, compatible with Google Authenticator.

Overview

Google2FA

Google Two-Factor Authentication for PHP

Google2FA is a PHP implementation of the Google Two-Factor Authentication Module, supporting the HMAC-Based One-time Password (HOTP) algorithm specified in RFC 4226 and the Time-based One-time Password (TOTP) algorithm specified in RFC 6238.


Latest Stable Version License Code Quality Build Downloads

Monthly Downloads Coverage PHP


Menu

Version Compatibility

PHP Google2FA
5.4 7.x LTS
5.5 7.x LTS
5.6 7.x LTS
7.1 8.x
7.2 8.x
7.3 8.x
7.4 8.x
8.0 (β) 8.x

Laravel bridge

This package is agnostic, but there's a Laravel bridge.

About QRCode generation

This package does not generate QRCodes for 2FA.

If you are looking for Google Two-Factor Authentication, but also need to generate QRCode for it, you can use the Google2FA QRCode package, which integrates this package and also generates QRCodes using the BaconQRCode library, or check options on how to do it yourself here in the docs.

Demos, Example & Playground

Please check the Google2FA Package Playground.

playground

Here's an demo app showing how to use Google2FA: google2fa-example.

You can scan the QR code on this (old) demo page with a Google Authenticator app and view the code changing (almost) in real time.

Requirements

  • PHP 7.1 or greater

Installing

Use Composer to install it:

composer require pragmarx/google2fa

To generate inline QRCodes, you'll need to install a QR code generator, e.g. BaconQrCode:

composer require bacon/bacon-qr-code

Usage

Instantiate it directly

use PragmaRX\Google2FA\Google2FA;
    
$google2fa = new Google2FA();
    
return $google2fa->generateSecretKey();

How To Generate And Use Two Factor Authentication

Generate a secret key for your user and save it:

$user->google2fa_secret = $google2fa->generateSecretKey();

Generating QRCodes

The securer way of creating QRCode is to do it yourself or using a library. First you have to install a QR code generator e.g. BaconQrCode, as stated above, then you just have to generate the QR code url using:

$qrCodeUrl = $google2fa->getQRCodeUrl(
    $companyName,
    $companyEmail,
    $secretKey
);

Once you have the QR code url, you can feed it to your preferred QR code generator.

// Use your own QR Code generator to generate a data URL:
$google2fa_url = custom_generate_qrcode_url($qrCodeUrl);

/// and in your view:

<img src="{{ $google2fa_url }}" alt="">

And to verify, you just have to:

$secret = $request->input('secret');

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

QR Code Packages

This package suggests the use of Bacon/QRCode because it is known as a good QR Code package, but you can use it with any other package, for instance Google2FA QRCode, Simple QrCode or Endroid QR Code, all of them use Bacon/QRCode to produce QR Codes.

Usually you'll need a 2FA URL, so you just have to use the URL generator:

$google2fa->getQRCodeUrl($companyName, $companyEmail, $secretKey)

Examples of Usage

Google2FA QRCode

Get a QRCode to be used inline:

$google2fa = (new \PragmaRX\Google2FAQRCode\Google2FA());

$inlineUrl = $google2fa->getQRCodeInline(
    'Company Name',
    '[email protected]',
    $google2fa->generateSecretKey()
);

And use in your template:

<img src="{{ $inlineUrl }}">

Simple QrCode

<div class="visible-print text-center">
    {!! QrCode::size(100)->generate($google2fa->getQRCodeUrl($companyName, $companyEmail, $secretKey)); !!}
    <p>Scan me to return to the original page.</p>
</div>

Endroid QR Code Generator

Generate the data URL

$qrCode = new \Endroid\QrCode\QrCode($value);
$qrCode->setSize(100);
$google2fa_url = $qrCode->writeDataUri();

And in your view

<div class="visible-print text-center">
    {!! $google2fa_url !!}
    <p>Scan me to return to the original page.</p>
</div>

Bacon/QRCode

<?php

use PragmaRX\Google2FA\Google2FA;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;

$google2fa = app(Google2FA::class);

$g2faUrl = $google2fa->getQRCodeUrl(
    'pragmarx',
    '[email protected]',
    $google2fa->generateSecretKey()
);

$writer = new Writer(
    new ImageRenderer(
        new RendererStyle(400),
        new ImagickImageBackEnd()
    )
);

$qrcode_image = base64_encode($writer->writeString($g2faUrl));

And show it as an image:

<img src="data:image/png;base64, <?php echo $qrcode_image; ?> "/>

HMAC Algorithms

To comply with RFC6238, this package supports SHA1, SHA256 and SHA512. It defaults to SHA1, so to use a different algorithm you just have to use the method setAlgorith():

$google2fa->setAlgorithm(Constants::SHA512);

Server Time

It's really important that you keep your server time in sync with some NTP server, on Ubuntu you can add this to the crontab:

sudo service ntp stop
sudo ntpd -gq
sudo service ntp start

Validation Window

To avoid problems with clocks that are slightly out of sync, we do not check against the current key only but also consider $window keys each from the past and future. You can pass $window as optional third parameter to verifyKey, it defaults to 4. A new key is generated every 30 seconds, so this window includes keys from the previous two and next two minutes.

$secret = $request->input('secret');

$window = 8; // 8 keys (respectively 4 minutes) past and future

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

An attacker might be able to watch the user entering his credentials and one time key. Without further precautions, the key remains valid until it is no longer within the window of the server time. In order to prevent usage of a one time key that has already been used, you can utilize the verifyKeyNewer function.

$secret = $request->input('secret');

$timestamp = $google2fa->verifyKeyNewer($user->google2fa_secret, $secret, $user->google2fa_ts);

if ($timestamp !== false) {
    $user->update(['google2fa_ts' => $timestamp]);
    // successful
} else {
    // failed
}

Note that $timestamp either false (if the key is invalid or has been used before) or the provided key's unix timestamp divided by the key regeneration period of 30 seconds.

Using a Bigger and Prefixing the Secret Key

Although the probability of collision of a 16 bytes (128 bits) random string is very low, you can harden it by:

Use a bigger key

$secretKey = $google2fa->generateSecretKey(32); // defaults to 16 bytes

You can prefix your secret keys

You may prefix your secret keys, but you have to understand that, as your secret key must have length in power of 2, your prefix will have to have a complementary size. So if your key is 16 bytes long, if you add a prefix it must be also 16 bytes long, but as your prefixes will be converted to base 32, the max length of your prefix is 10 bytes. So, those are the sizes you can use in your prefixes:

1, 2, 5, 10, 20, 40, 80...

And it can be used like so:

$prefix = strpad($userId, 10, 'X');

$secretKey = $google2fa->generateSecretKey(16, $prefix);

Window

The Window property defines how long a OTP will work, or how many cycles it will last. A key has a 30 seconds cycle, setting the window to 0 will make the key lasts for those 30 seconds, setting it to 2 will make it last for 120 seconds. This is how you set the window:

$secretKey = $google2fa->setWindow(4);

But you can also set the window while checking the key. If you need to set a window of 4 during key verification, this is how you do:

$isValid = $google2fa->verifyKey($seed, $key, 4);

Key Regeneration Interval

You can change key regeneration interval, which defaults to 30 seconds, but remember that this is a default value on most authentication apps, like Google Authenticator, which will, basically, make your app out of sync with them.

$google2fa->setKeyRegeneration(40);

Google Authenticator secret key compatibility

To be compatible with Google Authenticator, your (converted to base 32) secret key length must be at least 8 chars and be a power of 2: 8, 16, 32, 64...

So, to prevent errors, you can do something like this while generating it:

$secretKey = '123456789';
  
$secretKey = str_pad($secretKey, pow(2,ceil(log(strlen($secretKey),2))), 'X');

And it will generate

123456789XXXXXXX

By default, this package will enforce compatibility, but, if Google Authenticator is not a target, you can disable it by doing

$google2fa->setEnforceGoogleAuthenticatorCompatibility(false);

Google Authenticator Apps:

To use the two factor authentication, your user will have to install a Google Authenticator compatible app, those are some of the currently available:

Deprecation Warning

Google API for QR generator is turned off. All version of that package prior to 5.0.0 are deprecated. Please upgrade and check documentation regarding QRCode generation.

Testing

The package tests were written with PHPUnit. There are some Composer scripts to help you run tests and analysis:

PHPUnit:

composer test

PHPStan analysis:

composer analyse

Authors

License

Google2FA is licensed under the MIT License - see the LICENSE file for details.

Contributing

Pull requests and issues are more than welcome.

Comments
  • Relicensing to MIT

    Relicensing to MIT

    Dear contributors,

    To allow this package to be adopted by other projects, I'm trying to move the license of this package from the original GPLv3 to something more permissive, like MIT, but I need you and the original developer (Phil), to approve it.

    So, I'm listing all of you (up to today) and ask for a YAY/NAY comment in this thread, from each one of you.

    If you have any questions or something to say about this change, please do.

    If you have a really good understanding of licensing (which I do not), please jump in and help us.

    • [x] Phil - phil [at] xqi [dot] cc
    • [x] @antonioribeiro
    • [x] @barryvdh
    • [x] @GrahamCampbell
    • [x] @SebastianS90
    • [x] @aik099
    • [ ] @medinae
    • [x] @taichunmin
    • [x] @jbrooksuk
    • [x] @drbyte
    • [x] @mikerockett
    • [ ] @zhiyi7
    • [ ] @PixellUp
    • [ ] @bram1028
    • [x] @proshanto
    • [ ] @cnanney
    • [x] @ashnewmanjones
    • [ ] @kalfheim
    • [x] @it-can
    • [x] @tshafer
    • [x] @adeelx
    • [x] @ngyikp
    • [x] @domodwyer
    • [x] @leandro-lugaresi
    opened by antonioribeiro 20
  • Google2FA::generateSecretKey() is not compatible with Google 2FA

    Google2FA::generateSecretKey() is not compatible with Google 2FA

    The Problem

    Google 2FA requires a minimum of 20 bytes for a secret key. Google2FA::generateSecretKey() only produces 16 bytes by default.

    image

    The Solution

    Up the default to 20.

    opened by hopeseekr 14
  • feature request: using qrcodejs to remove dependency simplesoftwareio/simple-qrcode

    feature request: using qrcodejs to remove dependency simplesoftwareio/simple-qrcode

    feature request: using qrcodejs to remove dependency simplesoftwareio/simple-qrcode

    show QRCode is a front-end need, so it is reasonable to achieve it in Client Side with javascript. qrcodejs is a perfect solution for this. (leave the show QRCode task to the front-end guy :jack_o_lantern: ) ext-gd and simplesoftwareio/simple-qrcode are heavy dependency for 2fa server side package

    opened by ryh 13
  • Middleware for L5

    Middleware for L5

    If this package had middleware you could require 2fa for certain routes (like /admin & /settings) or all routes.

    It would redirect to a screen to enter that info then redirect back to the intended resource just like login.

    opened by tomschlick 13
  • Made all exceptions inherit from a base exception

    Made all exceptions inherit from a base exception

    Implements changes proposed in #115.

    Currently you have to catch every single exception this package throws. If you make a generic exception, say Google2FAException and have all other exceptions extend this one it is much easier for consumers of this package to catch anything thrown by it. Sometimes you don't care exactly what exception was thrown but you'd like to identify the general area (or package) of the problem.

    Changes in tests:

    Unit tests used the @expectedException to test for exceptions. There is nothing wrong with this approach except that we now want to test two things:

    1. That the exception is a subclass of Google2FAException
    2. That the exception is an instance of each particular exception.

    In order to achieve both, I wrapped the test calls in a try/catch block which catches with the generalized exception, and then checks for the specific exception.

    opened by poisa 11
  • Code clean

    Code clean

    • Remove .idea/ folder this should be in your global .gitignore file.
    • Trailing lines have been striped.
    • Should all be PSR-2.
    • composer.lock should be committed for a package.
    • phpunit is required for dev?
    opened by jbrooksuk 9
  • Support bacon-qr-code 2.0.0

    Support bacon-qr-code 2.0.0

    Add support of bacon-qr-code v2.0.0

    Class Png does not exist anymore. We have to use ImagickImageBackEnd instead - which require imagick php extension.

    I've also added the support of svg image, by adding a new parameter to getQRCodeInline.

    PS: the test on line https://github.com/antonioribeiro/google2fa/blob/master/tests/Google2FATest.php#L220 does not work on my computer: I hav php 7.1, and I get QRCODEPHPABOVE72 result...

    opened by asbiin 8
  • Uncaught Error: Call to a member function input() on null in

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

    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;
    
    opened by ghost 8
  • Not found class PragmaRX\Google2FA\Google2FA

    Not found class PragmaRX\Google2FA\Google2FA

    use PragmaRX\Google2FA\Google2FA;
    
            $gFA = new Google2FA();
    
            $imageDataUri = $gFA->getQRCodeInline(
                $request->getHttpHost(),
                $user->email,
                $secret,
                200
            );
    

    Class 'PragmaRX\Google2FA\Google2FA' not found How to fix for Laravel 5.3 ?

    opened by sozonets 8
  • Add functionality to prevent reuse of keys.

    Add functionality to prevent reuse of keys.

    See the patched readme files for details.

    I also added a getter for KEY_REGENERATION in order to allow using the facade like this: $ts * Google2FA::getKeyRegenerationTime()

    opened by SebastianS90 8
  • Using a bigger key results in

    Using a bigger key results in "Invalid barcode"

    FYI: https://github.com/antonioribeiro/google2fa#use-a-bigger-key

    Setting a 32-byte key (with prefix) results in an Invalid barcode error in the Google Authenticator app whereas 16-byte key seems to work fine.

    opened by rdev5 7
  • composer error: The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)     Unzip with 7z command failed, falling back to ZipArchive class

    composer error: The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems) Unzip with 7z command failed, falling back to ZipArchive class

    Under Windows 10, I try to install with composer require bacon/bacon-qr-code but get this error:

    C:\inst>composer require bacon/bacon-qr-code Using version ^2.0 for bacon/bacon-qr-code ./composer.json has been created Running composer update bacon/bacon-qr-code Loading composer repositories with package information Updating dependencies Lock file operations: 2 installs, 0 updates, 0 removals

    • Locking bacon/bacon-qr-code (2.0.8)

    • Locking dasprid/enum (1.0.3) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 2 installs, 0 updates, 0 removals

    • Installing dasprid/enum (1.0.3): Extracting archive

    • Installing bacon/bacon-qr-code (2.0.8): Extracting archive 0/2 [>---------------------------] 0% Failed to extract dasprid/enum: (7) D:\Lua\5.1\7z.EXE x -bb0 -y C:\inst\vendor\composer\tmp-00ee02c8f4af9f85331dd569cf5cc4fb -oC:\inst\vendor\composer\ef3967dc

      The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems) Unzip with 7z command failed, falling back to ZipArchive class Failed to extract bacon/bacon-qr-code: (7) D:\Lua\5.1\7z.EXE x -bb0 -y C:\inst\vendor\composer\tmp-657cd265e68422b530a8a1796bfb8cdf -oC:\inst\vendor\composer\a6e8c1f9

      The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems) Unzip with 7z command failed, falling back to ZipArchive class 1 package suggestions were added by new dependencies, use composer suggest to see details. Generating autoload files No security vulnerability advisories found

    opened by PVI-Bat 0
  • (Old) Demo page is broken

    (Old) Demo page is broken

    The (old) demo page reference in the readme (https://antoniocarlosribeiro.com/technology/google2fa) shows an exception error page rather then anything useful.

    The previous playground link works very well, so unless the old page was doing something very different I don't think you really need it.

    Anyway, just a FYI it needs fixing or removing! 😉

    opened by paulhennell 0
Releases(8.0.0)
Owner
Antonio Carlos Ribeiro
Antonio Carlos Ribeiro
JWT Authenticator for symfony

HalloVerdenJwtAuthenticatorBundle This bundle provides a JWT authenticator for Symfony applications. It's using PHP JWT Framework for parsing and vali

Hallo Verden 0 Jul 8, 2022
Laravel Users (Roles & Permissions, Devices, Password Hashing, Password History).

LARAVEL USERS Roles & Permissions Devices Password Hashing Password History Documentation You can find the detailed documentation here in Laravel User

Pharaonic 8 Dec 14, 2022
Google Two-Factor Authentication Package for Laravel

Google2FA for Laravel Google Two-Factor Authentication Package for Laravel Google2FA is a PHP implementation of the Google Two-Factor Authentication M

Antonio Carlos Ribeiro 785 Dec 31, 2022
Rinvex Authy is a simple wrapper for @Authy TOTP API, the best rated Two-Factor Authentication service for consumers, simplest 2fa Rest API for developers and a strong authentication platform for the enterprise.

Rinvex Authy Rinvex Authy is a simple wrapper for Authy TOTP API, the best rated Two-Factor Authentication service for consumers, simplest 2fa Rest AP

Rinvex 34 Feb 14, 2022
It's a Laravel 8 authentication markdown that will help you to understand and grasp all the underlying functionality for Session and API Authentication

About Auth Starter It's a Laravel 8 authentication markdown that will help you to understand and grasp all the underlying functionality for Session an

Sami Alateya 10 Aug 3, 2022
phpCAS is an authentication library that allows PHP applications to easily authenticate users via a Central Authentication Service (CAS) server.

phpCAS is an authentication library that allows PHP applications to easily authenticate users via a Central Authentication Service (CAS) server.

Apereo Foundation 780 Dec 24, 2022
Simple PHP Google Authentication Template

php-google-auth A php google authentication page project View Demo · Report Problems About The Project This is a small and easy project that I made to

Antonio 4 Nov 21, 2021
Social OAuth Authentication for Laravel 5. drivers: facebook, github, google, linkedin, weibo, qq, wechat and douban

Social OAuth Authentication for Laravel 5. drivers: facebook, github, google, linkedin, weibo, qq, wechat and douban

安正超 330 Nov 14, 2022
Enables Google Authentication for YOURLS

google-auth-yourls Enables Google Authentication for YOURLS Proper documentation coming soon. For now, here is the very rough documentation: Download

8th Wall 14 Nov 20, 2021
Opauth strategy for Google authentication

Opauth-Google Opauth strategy for Google authentication.

Opauth – PHP Auth Framework 84 Dec 4, 2022
A minimal package that helps you login with any password on local environments

Laravel Anypass Built with ❤️ for every "lazy" laravel developer ;) It is always painful to remember and type in the correct password in the login for

Iman 208 Jan 1, 2023
Single Sign-On for PHP (Ajax compatible)

Single Sign-On for PHP (Ajax compatible) Jasny SSO is a relatively simply and straightforward solution for single sign on (SSO). With SSO, logging int

Arnold Daniels 1.4k Jan 6, 2023
StartZ oauth2-etsy compatible League of PHP OAuth2

Etsy Provider for OAuth 2.0 Client This package provides Etsy OAuth 2.0 support for the PHP League's OAuth 2.0 Client. Requirements The following vers

StartZ 2 Nov 10, 2022
Helps you securely setup a master password and login into user accounts with it.

?? Make your Login form smart in a minute! Built with ❤️ for every smart laravel developer Helps you set a master password in .env file and login into

Iman 341 Jan 1, 2023
Laravel Passport is an OAuth2 server and API authentication package that is simple and enjoyable to use

Introduction Laravel Passport is an OAuth2 server and API authentication package that is simple and enjoyable to use. Official Documentation Documenta

The Laravel Framework 3.1k Dec 31, 2022
PHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging

Thruway is an open source client and router implementation of WAMP (Web Application Messaging Protocol), for PHP. Thruway uses an event-driven, non-blocking I/O model (reactphp), perfect for modern real-time applications.

Voryx 662 Jan 3, 2023
Discord-oauth2 - At the end of oAuth2, which I have been researching and reading for a long time,

Discord-oauth2 - At the end of oAuth2, which I have been researching and reading for a long time, I finally found the way to connect with discord and get information, that's how I did it. If I'm wrong, feel free to email me so I can correct it.

Uğur Mercan 2 Jan 1, 2022
All in one monitoring for NKN.org Crypto currency Miners!

nWatch - All in one NKN Crypto currency Miner & wallets monitoring NKN network is based on miners cheap and easy to deploy (from VPS to Raspberry Pi)

null 14 Dec 24, 2022
Multi-provider authentication framework for PHP

Opauth is a multi-provider authentication framework for PHP, inspired by OmniAuth for Ruby. Opauth enables PHP applications to do user authentication

Opauth – PHP Auth Framework 1.7k Jan 1, 2023