AdSense Mobile Ad

Wednesday, December 21, 2011

Google Authenticator: Using It With Your Own Java Authentication Server

The Google Authenticator application for mobile devices is a very handy application that implements the TOTP algorithm (specified in RFC 6238). Using Google Authenticator you can generate time passwords that can be used to authorize users in an authentication server that shares the secret key of the requesting users.

Google Authenticator is mainly used to access Google services using two-factor authentication. However, you can take advantage of Google Authenticator to generate time based password to be authenticated by a server of yours. The implementation of such a server is pretty simple in Java and you can get some inspiration getting the source code of the Google Authenticator PAM module. In this blog post, we will go through a simple implementation of the TOTP algorithm in a Java class.

Generating the Secret Key.

To generate the secret key we will use a random number generator to fill up a byte array of the required size. In this case, we want:

A 16 characters Base32 encoded secret key: since Base32 encoding of x bytes generate 8x/5 characters, we will use 10 bytes for the secret key.

Some scratch codes (using Google's jargon).

// Allocating the buffer

byte[] buffer =

new byte[secretSize + numOfScratchCodes * scratchCodeSie];

// Filling the buffer with random numbers.

// Notice: you want to reuse the same random generator

// while generating larger random number sequences.

new Random().nextBytes(buffer);

Now we want to extract the bytes corresponding to the secret key and encode it using the Base32 encoding. I'm using the Apache Common Codec library to get a codec implementation:

// Getting the key and converting it to Base32

Base32 codec = new Base32();

byte[] secretKey = Arrays.copyOf(buffer, secretSize);

byte[] bEncodedKey = codec.encode(secretKey);

String encodedKey = new String(bEncodedKey);

Loading the Key Into Google Authenticator

You can manually load the key into Google Authenticator, or generate a QR barcode to have the application loading it from it. If you want to generate a QR barcode using Google services, you can generate the corresponding URL with a code such as this:

Verifying a Code

Now that we've generated the key and our users can load them into their Google Authenticator application, we need the code required to verify the generated verification codes. Here's a Java implementation of the algorithm specified in the RFC 6238:

The t parameter of the check_code method and verify_code methods "is an integer and represents the number of time steps between the initial counter time t0 and the current Unix time." (RFC 6238, p. 3) The default size of a time step is 30 seconds, and it's the value that Google Authenticator uses too. Therefore, t can be calculated in Java as

t = new Date().getTime() / TimeUnit.SECONDS.toMillis(30);

Download the Library

A ready to use library can be downloaded from GitHub, where Mr. Warren Strange kindly started a repository with the code from this post and packaged it in a Maven project. The library contains a complete implementation of the server-side code, better documentation and some example code in the test cases.

Conclusion

You can now use the Google Authenticator applications and use it to generate time based passwords for your users, authenticated against your own authentication server.

As you can see, the required code is pretty simple and all of the required cryptographic functions are provided by the runtime itself. The only nuisance is dealing with signed types in Java.

Thanks to both of you for this - it's proven very useful for me to get this going.

By the way, creating a hyperlink using the generated Google Charts link may cause some HTTP 400 Malformed errors and the image may not load up. They will work pasting in the browser but not as an img src link (probably some redirects going on)

To fix this, simply change www.google.com in the url generation code to chart.googleapis.com

I made no reference about a license for the code published in this blog post (and in practically all the others) mainly because my goal was the code being illustrative.

On my part, please feel free to use the code in your project and I'm really, really glad you asked. If you want, you can put a mention in the source file. Nobody will ever se it, but nonetheless it's a memento. :)

Can you please clarify this ?In my mobile 'Google Authenticator' apps I registered the the generated QR code.And when I tried to test the authTest() method by invoking it continuously it returned true even after that code expired and I see a new code on my mobile. I tried continuously until 5 different codes were generated. It works fine with the initial code.

I am confused. I thought it should work only till that code is valid and displayed in my mobile. ?

As you can see in the code shown in the post, the verifyCode method is invoked in a loop whose purpose is verifying a code in a time window of size 6: 2 * window and window equals 3. That's why the code is valid even though the authenticator application is shown the next one.

Why this behaviour? Because a code generated by a client wouldn't pass the server validation unless the clock of the server and the client are synchronised within a very small error (much smaller than one minute). The code above validates a code if it's one of the codes which are generated in a 6 minutes "tolerance window" centred in the current time: [-3, 3]. You can adjust the size of the tolerance window by setting the window parameter to another value.

Which window size are you testing with? Keep into account that the code changes over time and if the two clocks are skewed, then the code won't be the same when calculated at the same instant. That's why the code is usually checked over a time window.

To keep thing simple and the jargon as well: in that loop you increase the coordinate of the "time period" on which you calculate the code. If we use a period of 30 seconds, you're checking 1 minute and a half in the past and 1 minute and a half in the future. Check your clock skew and see whether it's bigger than that. If it is, either you synchronise them or you raise the window size. The former is the better option between the two.

Yeah I changed it to 1000 but it still didn't work (plus I think it took like 10 sec or so to enter the code). I made 2 pastebins with my code, http://pastebin.com/s6xxCg3R & http://pastebin.com/aZdtVamd The first one verifies the code and the second one outputs a QR barcode link.

Really appreciate your help, I've tried to get this working for a week now :/

You're welcome. Which value are you passing to the t parameter or the check_code method? I suspect you're not passing the correct time_period. Google uses a 30-seconds period, so that you must take the UNIX time in milliseconds, divide it by 30.000 (the size of a 30-second window in milliseconds) and use that value as t.

I'm really glad that it helped. By the way, this made me realise that the blog post assumes that people know what the aforementioned RFC says. I'll correct it and add further information so that nobody else gets stuck on this issue.

How are the scratch codes work/are supposed to work? I can't find a lot of good information on how they work. I see that they are supposed to be used in some manner to gain access if the MFA is lost or broken. However, I can't really find how

I see that they are generated in a some complicated manner. What I don't see is why that is done, and then what one does with them after they are generated. The credentials repository is passed the scratch codes, ostensibly to store them.

Is the idea that when a MFA is lost or broken, the user is provided an alternate link, where they verify a scratch code? Once the scratch code is verified, do we reset the MFA so they can set up a new one?

Scratch codes are emergency passwords you can use to log into your account, for example when you can't use the Google Authenticator application for some reason. If and how to use them is up to your backend. You could ignore them or allow each of them once (as Google does), etc. Google, in fact, suggests you print them and take them with you in case Google Authenticator is inaccessible (you lost the phone) even temporarily (the battery is dead).

The credential repository is passed the scratch codes because they indeed are passwords, but as I said the policy is yours.

Yes, it works because it does not depend on any time zone. Since the time frame is calculated as the elapsed time from the the UNIX epoch, the time zone delta is zeroed by the difference. That is: if you describe the UNIX epoch in any time zone, the number of milliseconds elapsed form that moment up to now will be the same no matter which time zone you are using.

I am in a bizzare situation where Google Authenticator is generating a number with leading zero and this implementation is not handling it as in Java numbers with leading zeros are not possible. Just wondering if there is any way of solving this issue.

where verificationCode is the integer to verify. The string you get from compliant TOTP implementations is a 0-padded integer in base 10. Hence, you have to remove the leading zeroes, convert the remaining String to int and invoke authorize.

I am sorry i didn't get it exactly.e.g. if ValidattionCode generated by google authenticator is 002314and secret is ABDCD342434DD then what do i have to do exactly in authorize method. The validation is already changed to 2314 with no lead ing zeros when this method is called. Please advise.

Alright here is what i meant. The authorize(String secret, int verificationCode) takes verificationCode as int and when i call i convert string value (003456) coming from ui to int it will be changed to 3456 and therefore authorize() method will be called with validationCode 3456.

Hi Enrico,My case is, Authenticator is working fine when both client phone and server time is same. But when there is a difference in time between client and server, code generated in mobile is not working, when i enter in server to verify.(like server in US and client in India). Mobile time and server running time will be different in this case.plz help me...Is this scenario possible in Google Authenticator?

Of course it's possible. The error here is using local time: both your server and your client must agree on a time representation and RFC-6238 mandates the use of UTC. Make sure the server is using the number of seconds elapsed from midnight of 1970/01/01 UTC (the UNIX epoch).

I'm sorry but your question is too general: it's a needle in a haystack. I have no idea what your "server" is, what applications you are running and which one of them is involved into TOTP authentication.

Sorry about that...above question is related to your last comment on march 29.I copied same code what u provided in the link and passed my secret code to my android mobile GAuthenticator app through qrcode.In some servers it is working fine. I can't able to trace correct problem in some servers that code(Gauth app generated) is not matching with the code generated in your code.

That's really weird. Can you dump the value of new Date().getTime() in both a server that is working correctly and one that is not and see if they are correct? That's the only moment in which time information is used.

In your first comment you hinted at a "difference in time" that I interpreted as a timezone difference. Now I guess that's not the problem. Are server clocks kept in sync with NTP? This algorithm is time sensible: if the skew is too big, you won't be able to validate a TOTP password.

Hi Enrico, I downloaded your code and ran Unit Tests mentioned in GoogleAuthTest.java. for both authorise(), authoriseUser() unit tests i got following message. "Check VALIDATION_CODE = false". Is there any thing am i missing related to time settings in my system. I am using Windows, eclipse , jre7.Thanks

Unfortunately since TOTP password are a function of time, the only way for unit tests to work would be generating a TOTP password and validate it straight away (which BTW it does in another test). Those failures can be ignored since they require some refactoring.

Hi, the emergency codes are managed by the application: they are not validated using TOTP. Hence, I guess you would just look up the provided password against the list of scratch codes still active and if you find a match you will authenticate the user (and mark the code as used).

Hi, and if the application happens to be the login shell? How do we get the shell to respond to the emergency keys? It probably needs to be handlesd before it reaches the application. Perhaps the google authenticator PAM should take care of this. Consider what happens if the time daemon dies at the target host. There's got to be a configuration for this without a work around...

Hi, Just carried out an experiment after this comment. By setting the time off by a day on the server I got locked out of the system for all values provided by the authenticator on my phone. However, when I provided an emergency key it logged me in. I guess the default settings for google authenticator PAM work. -- A

I've been successfully using your GoogleAuth library for quite a while but now have a need to be able to generate validation codes (i.e., for sending via SMS). All the bits and pieces are there in the GoogleAuth project but are package private (it actually looks like the pieces are there but just wasn't finished). Since I know what changes need to be made, would you be open to me making them and you reviewing them for inclusion in the github project? Thanks!

Hi All,I Have taken your code as Reference and Created the sample JAVA Web Application and using the same in my Project and the Code is working like charm in my system (India). But the same code is not working in the Singapore. I am trying a lot but not getting the reason . Can anybody please help on this.Reference from : https://github.com/wstrange/GoogleAuth1. Is there any dependency with the Country name .Thanks in Advance..

Works nicely. One gotcha: If the verification code from Google Authenticator is not matching the server-side generated code it might be that the Authenticator internal clock is out of sync with Google's servers. To correct this on Android, open the Authenticator app, open top-right menu > Settings > Time correction for codes > Sync now.