Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork56
.Net library for Two Factor Authentication (TFA / 2FA)
License
RobThree/TwoFactorAuth.Net
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
.Net library, available asNuGet package, fortwo-factor (or multi-factor) authentication usingTOTP andQR-codes. This is a .Net port of thePHP TwoFactorAuth library (staying as close as possible to the PHP implementation, but using .Net conventions and codestyles).
- .NET Framework 4.6.1+ or.Net Core 2.0+ (.Net Standard 2.0+)
- Access to internet may be required if you use aQrCodeProvider that retrieves data/images from the web.
To install TwoFactorAuth.Net, run the following command in thePackage Manager Console
PM>Install-Package TwoFactorAuth.Net
When a user wants to setup two-factor auth (or, more correctly, multi-factor auth) you need to create asecret. This will be yourshared secret. Thissecret will need to be entered by the user in their app. This can be done manually, in which case you simply display thesecret and have the user type it in the app:
vartfa=newTwoFactorAuth("MyCompany");// Though the default is an 80 bits secret (for backwards compatibility reasons) we// recommend creating 160+ bits secrets (see RFC 4226 - Algorithm Requirements)varsecret=tfa.CreateSecret(160);
TheCreateSecret() method accepts two arguments:bits (default:80) andcryptoSecureRequirement (default:RequireSecure). The former is the number of bits generated for the shared secret. Make sure this argument is a multiple of 8 and, again, keep in mind that not all combinations may be supported by all apps. Google Authenticator seems happy with 80 and 160, the default is set to 80 because that's what most sites (that I know of) currently use; however a value of 160 or higher is recommended (seeRFC 4226 - Algorithm Requirements). The latter is used to ensure that the secret is cryptographically secure; if you don't care very much for cryptographically secure secrets you can specifyAllowInsecure and use a non-cryptographically secure RNG provider.
// Display shared secret<p>Please enter the following secretin your app: @secret</p>
This results in:
Please enter the following secret in your app: XANIK3POC23RCRYN
Another, more user-friendly, way to get the shared secret into the app is to generate aQR-code which can be scanned by the app. To generate these QR codes you can use any one of the built-in QRProvider classes:
...use a3rd party one orimplement your own QR Code provider. To implement your own provider all you need to do is implement theIQrCodeProvider interface. You can use the built-in providers mentioned before to serve as an example or read the next chapter in this file. The built-in classes all use a 3rd (e.g. external) party (Google, QRServer and QRicket) for the hard work of generating QR-codes (note: each of these services might at some point not be available or impose limitations to the number of codes generated per day, hour etc.). You could, however, easily useany library to generate your QR-codes without depending on external sources. SeeHowTo: Implement your own QR Code provider on how to do this.
The built-in providers all have some provider-specific 'tweaks' you can 'apply'. Some provide support for different colors, others may let you specify the desired image-format etc. What they all have in common is that they return a QR-code as binary blob which, in turn, will be turned into adata URI by theTwoFactorAuth class. This makes it easy for you to display the image without requiring extra 'roundtrips' from browser to server and vice versa.
// Display QR code to user<p>Scan the following imagewith your app:</p><p><img src="@tfa.GetQrCodeImageAsDataUri("Bob Ross", secret)"></p>
This results in:
Scan the following image with your app:
When the shared secret is added to the app, the app will be ready to start generating codes which 'expire' eachperiod number of seconds. To make sure the secret was entered, or scanned, correctly you need to verify this by having the user enter a generated code. To check if the generated code is valid you call theVerifyCode() method:
// Verify codetfa.VerifyCode((string)Session["secret"],code);
VerifyCode() will return eithertrue (the code was valid) orfalse (the code was invalid; no points for you!). You may need to storesecret in a session or other persistent storage between requests. TheVerifyCode() accepts, aside fromsecret andcode, two more arguments. The first beingdiscrepancy. Since TOTP codes are based on time("slices") it is very important that the server (but also client) have a correct date/time. But because the two may differ a bit we usually allow a certain amount of leeway. Because generated codes are valid for a specificperiod (remember theperiod argument in the TwoFactorAuth's constructor?) we usually check theperiod directly before and the period directly after the current time when validating codes. So when the current time is14:34:21, which results in a 'current timeslice' of14:34:00 to14:34:30 we also calculate / verify the codes for14:33:30 to14:34:00 and for14:34:30 to14:35:00. This gives us a 'window' of14:33:30 to14:35:00. Thediscrepancy argument specifies how many periods (or: timeslices) we check in either direction of the current time. The defaultdiscrepancy of 1 results in (max.) 3 period checks: -1, current and +1 period. Adiscrepancy of 4 would result in a larger window (or: bigger time difference between client and server) of -4, -3, -2, -1, current, +1, +2, +3 and +4 periods.
The second,dateTime ortimestamp (depending on which overload you use), allows you to check a code for a specific point in time. This argument has no real practical use but can be handy for unittesting etc. Unless specifiedTwoFactorAuth uses the current time.
The third,timeSlice, is an out-argument; the value returned intimeSlice is the value of the timeslice that matched the code (if any). This value will be 0 when the code doesn't match and non-zero when the code matches. This value can be stored with the user and can be used to prevent replay-attacks. All you need to do is, on successful login, make suretimeSlice is greater than the previously stored timeslice.
Ok, so now the code has been verified and found to be correct. Now we can store the secret with our user in our database (or elsewhere) and whenever the user begins a new session, after logging in, we ask for a code generated by the authentication app of their choice. All we need to do is callVerifyCode() again with the sharedsecret we stored with the user and the entered code and we'll know if the user is legit or not.
Simple as 1-2-3!
- How to implement your own QR Code provider
- How to implement your own RNG provider
- Time providers
- 3rd Party providers
- PHP version of this library
You'll need to haveSandcastle Help File Builder (SHFB) installed if you want to build the helpfile. Other than that you only need Visual Studio 2015 (or higher).
Licensed under MIT license. SeeLICENSE for details.
Logo / icon under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication (Archived page)
About
.Net library for Two Factor Authentication (TFA / 2FA)
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors3
Uh oh!
There was an error while loading.Please reload this page.


