Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork56
How to implement your own QR Code provider
This library comes with three 'built-in' QR-code providers. SomeTwoFactorAuth constructor overloads accept anIQrCodeProvider argument which lets you specify a built-in or custom QR-code provider. All three built-in providers do a simple HTTP request to retrieve an image using aWebClient and implement theIQrCodeProvider interface which is all you need to implement to write your own QR-code provider.
The default provider is theImageChartsQrCodeProvider which uses theimage-charts.com drop-in replacement for Google Chart Tools to render QR-codes. Then we have theQrServerQrCodeProvider which uses thegoqr.me API and finally we have theQRicketQrCodeProvider which uses theQRickit API. All three inherit from a common (abstract) baseclassBaseHttpQrCodeProvider because all three share the same functionality: retrieve an image from a 3rd party over HTTP. All three classes have constructors that allow you to tweak some settings and most, if not all, arguments should speak for themselves. If you're not sure which values are supported, click the links in this paragraph for documentation on the API's that are utilized by these classes.
If you don't like any of the built-in classes, because you don't want to, or can't, rely on external resources for example, or because you're paranoid about sending the TOTP secret to these 3rd parties (which is useless to them since they miss at least one other factor in theMFA process), feel tree to implement your own. TheIQrCodeProvider interface couldn't be any simpler. All you need to do is implement 2 methods:
byte[]GetQrCodeImage(stringtext,intsize);stringGetMimeType();
TheGetMimeType() method should return theMIME type of the image that is returned by our implementation ofGetQrCodeImage(string text, int size). In this example it's simplyimage/png. TheGetQrCodeImage() method is passed two arguments:text andsize. The latter,size, is simply the width/height in pixels of the image desired by the caller. The first,text is the text that should be encoded in the QR code. An example of such a text would be:
otpauth://totp/LABEL:alice@google.com?secret=XANIK3POC23RCRYN&issuer=ISSUER
All you need to do is return the QR code as binary image data and you're done. All parts of thetext have been escaped for you (but note: you may need to escape the entiretext just once more when passing the data to another server as GET-parameter).
Let's try implementing our own!
- Create a class
MyQRProvider.cs
usingSystem;namespaceMyNameSpace{publicclassMyQRProvider{}}
- Implement the
IQrCodeProviderinterface:
usingSystem;usingTwoFactorAuthNet.Providers.Qr;namespaceMyNameSpace{publicclassMyQRProvider:IQrCodeProvider{}}
- To install QrCode.Net, run the following command in thePackage Manager Console
PM>Install-Package QrCode.Net
NOTE: Explaining the actual process of generating a QR code is far beyond the scope of this document, so for that we'll useQrCode.Net in this example. However, it is up to you tofind a library that suits your needs and demands (or write your own QR code generator if you're up for it!) if you don't like QrCode.Net.
- Implement the
IQrCodeProviderinterface members:
usingGma.QrCodeNet.Encoding;usingGma.QrCodeNet.Encoding.Windows.Render;usingSystem.Drawing.Imaging;usingSystem.IO;usingTwoFactorAuthNet.Providers.Qr;namespaceMyNameSpace{publicclassMyQRProvider:IQrCodeProvider{publicstringGetMimeType(){return"image/png";}publicbyte[]GetQrCodeImage(stringtext,intsize){varencoder=newQrEncoder();varqrCode=encoder.Encode(text);varrenderer=newGraphicsRenderer(newFixedCodeSize(size,QuietZoneModules.Two));byte[]result;using(varstream=newMemoryStream()){renderer.WriteToStream(qrCode.Matrix,ImageFormat.Png,stream);result=stream.ToArray();}returnresult;}}}
Note that this library does not require an external 3rd party and the QR code generation is handled by the QrCode.Net library. This way we don't need (outgoing) internet access and the shared secret is only known by you. No more external dependencies, no more unnecessary latencies.
- Pass your newly created QR code provider to a TwoFactorAuth constructor overload that accepts an
IQrCodeProviderargument.
vartfa=newTwoFactorAuth("MyCompany",newMyQRProvider());
From here on thetfa instance will use your QR code provider.