I'm attempting to create a Google 2 Factor Authorisation just as an experiment not for any real practical reason.
I'm using the code supplied from: here
I build a QR Code URL via a function which has two parameters, $username and $secret
$qrcode_url = "https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/{$username}%3Fsecret%3D{$secret}";
This correctly builds a URL.
The $username parameter is the user being logged in.
The $secret parameter is generated by Google2FA::generate_secret_key()
However, when I load a page which requests the QR Code, Google proclaims it 'Your client has issued a malformed or illegal request'. This is where is gets annoying. If I click the address bar and send the request again it will load the QR Code which supplies a correct OTP (one time password). Then if I reload the page with the QR Code on it, this will also load correctly.
Any ideas as to what is causing this issue? It wouldn't be anything to do with the fact I'm running it on XAMPP locally, does it?
Thanks in advance! :]
EDIT: Just to let you know, I don't think it's a Cache issue as I've cleared that and it still borks up.
I appear to have fixed this issue with a mixture of cURL and a different URL to access the image.
Here is my complete solution:
<?php
public static function get_qr_code_url( $username, $secret )
{
$h = 100;
return 'http://chart.apis.google.com/chart?chs=' . $h . 'x' . $h .
'&chld=M|0&cht=qr&chl=' . urlencode( 'otpauth://totp/' . $username . '@' . $_SERVER['HTTP_HOST'] . '?secret=' . $secret );
}
public static function get_qr_code( $username, $secret )
{
if( FALSE === $secret )
{
return FALSE;
}
$url = self::get_qr_code_url( $username, $secret );
$curl_handle = curl_init();
$headers = array( 'Expect:' );
$options = array(
CURLOPT_URL => $url,
CURLOPT_CONNECTTIMEOUT => 2,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_USERAGENT => 'My-Google-Auth',
CURLOPT_HTTPHEADER => $headers
);
curl_setopt_array( $curl_handle, $options );
$query = curl_exec( $curl_handle );
curl_close( $curl_handle );
$base_64= chunk_split( base64_encode( $query ) );
return '<img class="google_qrcode" src="data:image/gif;base64,' . $base_64 . '" alt="QR Code" />';
}
?>
I guess the only way I could maybe improve upon this is to actually save the image to the server and keep a local copy until the key was regenerated or something. But that's if I was to ever implement this in a proper environment! :]
Thanks for the help @Brad!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With