A few months ago, looking for a replacement for Windows (which always finds new ways to get on my nerves), I spent a couple of weeks playing with Linux Mint with MATE desktop. During this test drive, one of the annoyances I came across was the inability to drag a URL from Chromium’s address bar to create a link on the desktop. I literally ended up asking for help, and still didn’t figure it out.
In Windows, this is something I’ve been doing for many, many years. It’s not rocket science. You drag the padlock icon next to the address bar onto your desktop and a shortcut is created, pointing to that URL.
Ubuntu 19.10
Since Ubuntu 19.10 was released a week and a half ago, I thought I’d try it out. The first thing I figured I’d make sure was that I could drag and drop links to the desktop. Ubuntu is one of the most popular and mature operating systems around. Surely they’d support such a basic usability feature, right?
Well, it turns out that dragging links from default browser Firefox to the desktop has no effect whatsoever. Odd, isn’t it? Let’s try dragging that link to some other folder instead.
That’s annoying. I mean, drag and drop is a really basic feature that has been around forever. Let’s try dragging a file from one folder to another… obviously that’s going to work, no?
As you drag the file, a little plus icon appears beneath the hand as if to tell you that something’s going to happen. Alas, however, this also has no effect.
And of course, dragging the file to the desktop similarly does not work:
So we can’t drag links from Firefox, and we can’t drag and drop files. Maybe we’ll have better luck with Chromium?
So it seems, like someone hinted in that original question about drag and drop in Linux Mint, that this has nothing to do with the browser and is something related to the desktop environment.
Once again, I had to swallow that feeling of incompetence and ask for help with this. Aside from the usual Stack Overflow treatment of getting my question closed as a duplicate, one of the comments led to other Q&As that uncovered a bitter truth: that drag and drop support was intentionally removed. Why would anyone in their right state of mind do that?
Kubuntu 19.10
Incredulous, I decided to try the KDE flavour of Ubuntu — Kubuntu. Drag and drop a link from browser to desktop? No problem:
Was that really so hard? I get it, there were reasons why GNOME decided to do away with desktop icons and the like. But surely there are better ways to solve the problem than to do away with a basic and essential usability feature.
A desktop environment without basic drag and drop support in… almost 2020… is just garbage.
If you’ve been following Gigi Labs for a while, you’ve no doubt noticed that things have somewhat slowed down in the last couple of years. This is the result of a number of things, not least of which is having spent a year and a half living and working in Dublin, Ireland. I have also had the opportunity to write blog posts on a professional, freelance basis, and I continue to get involved in other things that allow me to keep learning.
More importantly, however, I’ve been trying to focus on writing quality articles using the little free time I have available, rather than simply blogging about whatever everyone else is talking about.
In fact, while the past couple of years have seen a mixture of content, I think they have included the publication of some of the most interesting articles on this blog to date, such as:
Also worth mentioning are some “Getting Started” articles, including a few on Microsoft Orleans 2.x, one on Angular 8, and another on Umbraco 8. I have a lot of such step-by-step beginner articles at Gigi Labs which often tend to be a good starting point for people wanting to start learning about new technologies.
I have had the fortune of learning a lot in these last two years, and I hope I will get the chance to share some of that. Even if articles might not be published very regularly, I hope that you will find that they’re worth the wait.
I also continue to be involved in the local tech community in Malta — in fact, I launched a new website in June called Teknologija to keep track of events across the various groups. I am also open to getting involved with and speaking at events abroad, so get in touch if you’re interested.
Two-factor authentication (2FA) is becoming more and more important, as its adoption is driven by a need for major software companies to secure their systems against threats, as well as due to legal requirements of strong customer authentication, such as the PSD2 directive that came in force in Europe last month.
2FA can be implemented in a number of ways. Typically, it is a combination of the usual username/password login as well as something else, often being a one-time password (OTP) that is sent via SMS or email, or generated by an algorithm.
In this article, we’ll focus entirely on generating and verifying Time-Based One-Time Passwords (TOTP) using Google Authenticator and the Otp.NET library.
Update 20th October 2019: This also works if you use Microsoft Authenticator instead of Google Authenticator. Microsoft Authenticator requires more permissions on your device, sends usage data to Microsoft by default, and is slightly more confusing because you have to choose the type of account.
Update 22nd October 2019: I discovered another mobile app called Authy, and it works just as well to acquire the TOTP secret and generate codes. It is interesting because it has a mechanism to take encrypted backups in the cloud and synchronise across devices, addressing the problem of when you lose or change your phone.
About TOTP
TOTP is an algorithm used to generate one-time passwords based on a shared secret and the current time. It is defined in RFC6238, and is a variant of the HOTP algorithm (RFC4226) which uses a counter instead of time.
TOTP can be thought of as a function that takes the shared secret and current time as inputs, and generates a one-time password as output. Given that the client and server both know the same shared secret, and that their software clocks are more or less in sync without major clock skew, then they would generate the same code. This allows a code generated on a mobile device to be verified on the server side.
Generating a Shared Secret
We will use Otp.NET to perform most operations related to TOTP generation and verification. This can easily be installed in a .NET (Core) console application via NuGet:
Install-Package Otp.NET
It is then really easy to generate and output a shared secret using the following code:
var secret = KeyGeneration.GenerateRandomKey(20);
var base32Secret = Base32Encoding.ToString(secret);
Console.WriteLine(base32Secret);
The secret that we generated on the first line is an array of bytes. However, we output it in base32 encoding. This is important for the next step when we will pass the secret to the mobile device. As I learned the hard way, it does not work if the secret is an arbitrary string and not base32-encoded.
Running the above, I just got the following in the output:
6L4OH6DDC4PLNQBA5422GM67KXRDIQQP
Generating a QR Code for the Secret
Stefan Sundin made this great 2FA QR code generator. The two required fields are the Secret (where we paste the value generated above) and a Label (which is arbitrary and identifies the application — we’ll simply put “MFA Test 1” in there).
Setting up Google Authenticator
Find Google Authenticator in your phone’s app store and install it. It requires access to your camera as we’ll see in a second.
After installation and its brief in-built tutorial, you get to the point where you can set up your first TOTP code generator (they call it an “account”):
This step is where you enter the shared secret into Google Authenticator. You can do that by scanning a QR code (first option), or by typing it in (second option). The latter is slow and painful, especially on a mobile device, and should be kept as a fallback in case there is some kind of problem scanning the QR code. Scanning the QR code is really just a convenience mechanism and is an encoded version of the same secret.
Once you’ve scanned the QR code, Google Authenticator has acquired the shared secret and starts generating TOTP codes every 30 seconds:
Since you can have more than one of these code generators in here (for different applications), they come with a label. In this case, you’ll notice that we have “MFA Test 1”, which is exactly what we entered in the Label field when generating the QR code.
Generating TOTP codes from Otp.NET
If you need to generate TOTP codes from .NET code (essentially to do what Google Authenticator is doing), then Otp.NET makes it very easy to do that:
string base32Secret = "6L4OH6DDC4PLNQBA5422GM67KXRDIQQP";
var secret = Base32Encoding.ToBytes(base32Secret);
var totp = new Totp(secret);
var code = totp.ComputeTotp();
Console.WriteLine(code);
The ComputeTotp() method takes an optional DateTime parameter as the current time to use for the code generation algorithm. If not provided, it uses DateTime.UtcNow, which is typically what you want to use.
Since we are using Google Authenticator, we don’t actually need this at all, so this is just something to keep in mind if you ever actually need it. It also gives some assurance that we’re on the right track, because what we’re doing in C# and on the mobile device are evidently well in sync.
Verifying TOTP Codes
Like every other operation we’ve seen, verifying TOTP codes with Otp.NET is also very easy. The following code shows how to do this, although most of the code is actually handling input and output.
string base32Secret = "6L4OH6DDC4PLNQBA5422GM67KXRDIQQP";
var secret = Base32Encoding.ToBytes(base32Secret);
var totp = new Totp(secret);
while (true)
{
Console.Write("Enter code: ");
string inputCode = Console.ReadLine();
bool valid = totp.VerifyTotp(inputCode, out long timeStepMatched,
VerificationWindow.RfcSpecifiedNetworkDelay);
string validStr = valid ? "Valid" : "Invalid";
var colour = valid ? ConsoleColor.Green : ConsoleColor.Red;
Console.ForegroundColor = colour;
Console.WriteLine(validStr);
Console.ResetColor();
}
Here’s what it might look like while you test it out repeatedly:
As you can see above, I did a number of things:
I entered two invalid codes, and got invalid responses.
I entered a valid code, and got a valid response as expected.
I waited for a new code to be generated, then entered the same code as before, and it was accepted.
I entered the new code that was generated, and it was validated.
I entered another invalid code, and it was marked as such.
The most interesting part of the above is the third step, and it requires further explanation. Codes are generated in time windows, by default every 30 seconds. That doesn’t necessarily mean that the previous code should be rejected. The time window might have shifted just as the user was typing the code, or there could be network delays, etc. Typically, some leeway is allowed when validating these codes. The RFC recommends allowing codes from one time window in the past or future, and that’s what the value of VerificationWindow.RfcSpecifiedNetworkDelay that we passed in as the third parameter to VerifyTotp() does. If you want, you can pass in something different that is more lenient or more restrictive.
On the other hand, accepting the same code twice is wrong, considering we are supposed to be generating one time passwords. In order to make sure that a code isn’t used twice, we need to store something that we can later check to know whether a code has been used. That’s the reason for the second parameter to VerifyTotp(). It gives us back a number indicating the time step used, so we can save this whenever a code is used, and later check whether the same time step has already been used before.
Assuming a single shared secret, a very quick-and-dirty dummy implementation using a HashSet instead of real persistence could look something like this:
string base32Secret = "6L4OH6DDC4PLNQBA5422GM67KXRDIQQP";
var secret = Base32Encoding.ToBytes(base32Secret);
var totp = new Totp(secret);
var usedTimeSteps = new HashSet<long>();
while (true)
{
Console.Write("Enter code: ");
string inputCode = Console.ReadLine();
bool valid = totp.VerifyTotp(inputCode, out long timeStepMatched,
VerificationWindow.RfcSpecifiedNetworkDelay);
valid &= !usedTimeSteps.Contains(timeStepMatched);
usedTimeSteps.Add(timeStepMatched);
string validStr = valid ? "Valid" : "Invalid";
var colour = valid ? ConsoleColor.Green : ConsoleColor.Red;
Console.ForegroundColor = colour;
Console.WriteLine(validStr);
Console.ResetColor();
}
Like this, there’s no way you can ever have the same code be valid twice:
Conclusion
In this article we’ve seen how Time-Based One-Time Passwords can be generated and verified. We’ve focused mainly on:
Generating a shared secret using Otp.NET
Bringing it to a mobile device with Google Authenticator
Using Google Authenticator to generate TOTP codes
Using Otp.NET to validate these codes
In a two-factor authentication implementation, this is of course only one of the factors, and usually takes place after a regular username/password login.
"You don't learn to walk by following rules. You learn by doing, and by falling over." — Richard Branson