Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Two-Factor Authentication for VFP
Message
From
27/10/2022 02:30:06
Lutz Scheffler (Online)
Lutz Scheffler Software Ingenieurbüro
Dresden, Germany
 
 
To
26/10/2022 20:31:02
John Ryan
Captain-Cooker Appreciation Society
Taumata Whakatangi ..., New Zealand
General information
Forum:
Visual FoxPro
Category:
VFPX/Sedna
Miscellaneous
Thread ID:
01685145
Message ID:
01685146
Views:
52
Hi Ryan

While I count the kind of 2FA you do as data gathering by google and adding an external point of failure, also it exposes your mobile even more to google - it nicely connects the phone to the app, usage of the app by owner of the phone and so on, data you might freely hand to google or not (You will not believe what one can read from this data), others might think different.

Since LevelExtreme is hard to search, please consider to put this on VFPX, see https://vfpx.github.io/newproject/

Lutz

>Interested in MFA (Multi-factor Authentication) aka 2FA for your VFP App?
>
>Currently, the TOTP (Time-based One-Time Password) is regarded as one of the more secure 2FA options. Basically a TOTP is a code that updates regularly so that codes can't be reused and (hopefully) aren't available to a hacker. Some VFP developers have already deployed systems that send a TOTP via SMS or email... but both models are now regarded as less secure.
>
>Here's a TOTP implementation that could take only a few minutes to deploy. You don't need to store email addresses or cell phone numbers or actually anything extra if you have a user table with one or more static fields.
>
>This implementation uses Google Authenticator that generates a new TOTP every 30 seconds without need for mobile or internet connectivity. The validation code follows RFC-6238 which is the industry-standard TOTP protocol.
>
>The process is:
>
>- User installs Google Authenticator on their device.
>- To activate 2FA, the VFP App displays a QR code to the user.
>- The user scans the QR code using Google Authenticator. This creates an Application account in Google authenticator, with a 6-digit validation code that updates every 30 seconds.
>- When logging in, the user is asked to enter their 6 digit code from Google Authenticator; they simple read the current validation code from their device.
>
>Secret Code
>Each user needs an 80-bit (10 character binary) secret code. This should be unique and treated like a password- so never stored, only ever Hashed. Ideally it would be hashed with more than just username, so it can't be easily guessed. It needs to use static fields because otherwise a data change will break the secret code and the user won't be able to authenticate.
>
>A good example of a user secret code using vfpencryption.fll's Hash function would be something like
>
>lcSecret=left(hash(username+ttoc(date_initiated+1276,1)+chrtran(rtrim(UPPER(username)),"AEIOU","@#$*&"),5),10)
>
>
>(Yes this uses MD5 that is no longer considered cryptographically safe; but the resulting 80-bit/10 byte secret code doesn't care how impressively long the hash was that it came from)
>
>Note that many 2FA systems that use Google authenticator use the Google Charts API to generate the QR code, followed by another url to validate what the user enters. This breaches cryptographic principles, since it passes the user's secret code across the internet to a third party. In addition, Google deprecated the Google Chart API in 2012 so while it works today, there's no guarantee it will tomorrow.
>
>This VFP implementation produces the QR code locally and does not pass the user's secret code to any third party.
>
>QR Code creation is easy using VFPX's very nice QR Code project: https://github.com/VFPX/FoxBarCodeQR
>
>Note that in this code, Application, User and Issuer are only used for the account label in Google Authenticator, not for authentication. Only the secret code is used for authentication. So you can experiment with these other parameters to see how they affect the Google Authenticator label.
>
>Also, your binary secret code needs to be converted to Base32 encoding for the barcode; this is handled in the attached code.
>
>To display the QR code:
>
>
>ShowQR("MyApp","Username","BinarySecr","MyApp") &&10-byte binary secret code
>
>function ShowQR(lcApp,lcUser,lcSecret,lcIssuer)
>
>SET PROCEDURE TO FoxBarcodeQR.prg ADDITIVE
>LOCAL lcString,loFbc,lcQRImage
>
>loFbc = CREATEOBJECT("FoxBarcodeQR")
>
>*---consider transforming user for security
>lcuser=LEFT(m.lcuser,1)+"***"+RIGHT(RTRIM(m.lcuser),1)
>
>lcString="otpauth://totp/"+m.lcApp+":"+m.lcUser+;
>	"?secret="+Base32Encode(m.lcSecret)+"&issuer="+m.lcIssuer
>
>lcQRImage = loFbc.FullQRCodeImage(lcString, , 333)
>
>*-- Create form
>LOCAL loForm AS FORM
>loForm = CREATEOBJECT("Form")
>WITH m.loForm
>  .WIDTH = 600
>  .HEIGHT = 600
>  .AUTOCENTER = .T.
>  .ADDOBJECT("Image1", "Image")
>  WITH .Image1
>    .WIDTH = 600
>    .HEIGHT = 600
>    .STRETCH = 0
>    .PICTURE = m.lcQRImage
>    .TOP = 20
>    .LEFT = 20
>    .VISIBLE = .T.
>  ENDWITH
>  .SHOW(1)
>ENDWITH
>
>Function Base32Encode(tcString as String) as String
>   Local lnCode, lnEncoded, lcEncoded, lnBits, ln5Bits
>   lcEncoded = ''
>   lnEncoded = 0
>   lnBits = 0
>   Do While !Empty(tcString)
>      lnCode = Asc(tcString)
>      tcString = Substr(tcString,2)
>      lnEncoded = BitLshift(lnEncoded,8)+lnCode
>      lnBits = lnBits + 8
>      Do While lnBits>=5
>         * Take the highest 5 bits of the so far encoded value.
>         ln5Bits = BitRshift(lnEncoded,lnBits-5)%32
>         lcEncoded = lcEncoded + Chr(IIF(ln5Bits<26,65+ln5Bits,24+ln5Bits))
>         lnEncoded = lnEncoded % 128
>         lnBits = lnBits - 5
>      EndDo
>   Enddo
>   Return lcEncoded
>EndFunc   
>
>
>If you scan the displayed QR code in Google Authenticator, you'll see a new Application account with a 6-digit validation code that updates every 30 seconds.
>
>Application Validation
>Obviously your VFP app needs to let the user enter their validation code, then validate it.
>
> Some implementations submit code and secret to a 3rd party URL, but that (again) results in the secret code being shared. Instead, just a few lines of code and Craig Boyd's vfpencryption.fll allows your app to validate locally.
>
>If you run the following code, it should match the validation code you see in Google Authenticator. Note that this uses VFPA's SYS(9028) function to generate UTC time; Rick Strahl's Web Connection and other resources have VFP9 functions to do the same if you're not using VFPA. The code also uses the HMAC() function in vfpencryption.fll.
>
>
>? CurrentRFC6238("BinarySecr")
>
>Function CurrentRFC6238(lcSecret)
>  *Set Library to vfpencryption.fll
>   Local lnMessage,lcMessage, lcHash, lcTruncatedHash, lnCode
>   lnMessage = Floor((SYS(9028)-{^1970-01-01:00:00})/ 30) &&Unix time
>   lcMessage = Replicate(Chr(0),4)+BinToC(m.lnMessage,'4S') 
>   lcHash = HMAC(m.lcMessage,m.lcSecret, 1)
>   lnOffset = Asc(Right(lcHash,1)) % 16
>   lcTruncatedHash = SubStr(m.lcHash,m.lnOffset+1,4)
>   lnCode = BitAND(CtoBIN(m.lcTruncatedHash,'4S'),0x7fffffff)
>   return PadL(m.lnCode % 1000000,6,'0')
>EndFunc
>
>
>NOTE!!!!!!!
>As this is a time-sensitive code, the DateTime on the Google Authenticator device needs to be synced with the VFP app's PC DateTime.. Time zone doesn't matter since machine time gets converted to UTC time- but UTC time needs to match or else the validation fails and the user won't be able to log in. If validation fails, a common response is to check a few 30-second intervals before and after in case there's network latency or slight time drift; this does make it easier to brute force/guess the validation code, but only if users are allowed multiple attempts.
>
>Summary
>The above few lines of code allow VFP developers to implement 2FA in their apps with relative ease. The implementation uses Google Authenticator and industry-standard RFC-6238, and does not share or transmit the user's secret code.
>
>Is Google Authenticator Secure?
>There are criticisms, since it uses the default RFC-6238 SHA-1 and has included SMS or emailed credentials in the past. Theoretically the QR code url can include additional parameters for cryptographic strength (e.g. SHA128/256) and validation code lengths longer than 6, but those parameters appear to be ignored by the Google authenticator application.
Words are given to man to enable him to conceal his true feelings.
Charles Maurice de Talleyrand-Périgord

Weeks of programming can save you hours of planning.

Off

There is no place like [::1]
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform