Library / SDK
wstrange/GoogleAuth avatar
wstrange/GoogleAuth

GoogleAuth: TOTP verification for Java services, with a credential repository hook

Google Authenticator Server side code

1,110 stars333 forksJavaBSD-3-Clause

At a glance

What is it?
GoogleAuth is a Java server library that implements the RFC 6238 time-based one-time password algorithm, and it covers the enrolment flow, the verification window and a pluggable repository for storing shared secrets. It is BSD licensed and dates from the era when Google Authenticator was the default second factor.
Who is it for?
Adopt GoogleAuth if you are on a Java 7 era stack, you already have TOTP tokens in the field, and you want a library whose credential storage you can plug into your own repository layer rather than one that dictates a database. Do not adopt it for a new service, because the code is old, the version in the README's dependency snippet is newer than the published tags, and the ecosystem has moved to libraries that support WebAuthn and passkeys.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 70 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the library does, and the standard it implements

GoogleAuth is a Java server library that implements the Time-based One-time Password algorithm specified in RFC 6238. The README gives the provenance, which is worth knowing: the implementation borrows from Google Authenticator, whose C code has served as a reference, and was created upon code published in a blog post by Enrico M. Crisostomo.

The scope is stated plainly in the section on whom this library is for: any developer who wants to add TOTP multi-factor authentication to a Java application and needs the server-side code to create TOTP shared secrets, generate and verify TOTP passwords.

On the client side, the README is clear about the options. Users may use TOTP-compliant token devices, such as those you get from your bank, or a software-based token application such as Google Authenticator. Both the Google Authenticator client applications, available for iOS, Android and BlackBerry, and its PAM module can be used to generate codes to be validated by this library. And the library can also be used to build custom client applications if Google Authenticator is not available on your platform or if it cannot be used.

That last sentence is the interesting one, because it explains why the library ships a code generator. The client section says the library can generate TOTP codes for testing or for use as a software-based client:

java
GoogleAuthenticator gAuth = new GoogleAuthenticator();
int code = gAuth.getTotpPassword(secretKey);

Those codes can be used as an alternative to the codes that would be generated by the Google Authenticator app or another client device. For a server-side test suite, that means you can drive an enrolment and verification flow without asking a developer to scan a QR code with a phone.

The primary language is Java, the licence is BSD-3-Clause, and the default branch is master. The repository is not archived and the last push was on 2026-08-14. The release list shows 1.2.0 and 1.1.5 both from 2018-07-24 and 1.1.4 from 2017, which is the timeline to keep in mind when evaluating the current state of the code.

The enrolment flow, and who is responsible for storing the secret

The usage section starts with a design decision that is stated early and that shapes everything else: no user name is provided to the API and it is a responsibility of the caller to save it for later use during the authorisation phase.

java
GoogleAuthenticator gAuth = new GoogleAuthenticator();
final GoogleAuthenticatorKey key = gAuth.createCredentials();

The user should be given the value of the shared secret, returned by key.getKey(), so that the new account can be configured into its token device, and a convenience method is provided to easily encode the secret key and the account information into a QR code.

The separation of responsibilities here is the point. The library creates the secret and hands it to you, and you decide where it lives. That is a good default for a security library, because a library that also owns your credential storage is a library that has opinions about your database schema and your key management.

When the user wishes to log in, they provide the TOTP password generated by their device. By default it is a 6 digit integer that changes every 30 seconds, and both the password length and its validity can be changed. The README immediately notes the constraint: many token devices such as Google Authenticator use the default values specified by the TOTP standard and they do not allow for any customization.

That note is a real operational constraint rather than a caveat. If you shorten the password length or change the period to make the codes easier to type, the token devices your users already have will stop working, because the device is the one generating the code and it is not reading your server's configuration. The defaults are the interoperability surface, and changing them trades compatibility for a marginal usability gain.

Verification itself is a single call:

java
GoogleAuthenticator gAuth = new GoogleAuthenticator();
boolean isCodeValid = gAuth.authorize(secretKey, password);

checking the validity of the specified password against the provided Base32-encoded secretKey.

Clock drift, and the window that decides whether a code is accepted

Since TOTP passwords are time-based, the README says it is essential that the clock of both the server and the client are synchronised within the tolerance used by the library. The tolerance is set by default to a window of size 3 and can be overridden when configuring a GoogleAuthenticator instance.

This is the single most important operational detail in the library, and it is worth being precise about what a window of size 3 means. A TOTP code is derived from a time step, and the server accepts a code if it matches the expected value for any step in the accepted window. With the default, three adjacent steps are acceptable, since the period is 30 seconds.

The security trade is explicit and unavoidable. A window of one rejects any code whose time step differs even slightly, and a code typed at the boundary of a step fails. A larger window accepts more stale codes, which widens the replay opportunity, since a code that was valid a minute ago is still accepted. There is no setting that fixes both, and a library that hid the choice would be worse than one that exposes it.

The practical consequence is that the window is a claim about your infrastructure. If you have not verified your clock synchronisation with NTP monitoring, a wider window is buying you reliability at the cost of a wider replay window. This is a deployment concern, and the library cannot verify it for you.

The scratch codes feature interacts with the same reasoning. By default 5 scratch codes are generated together with a new shared secret, and they are meant to be a safety net in case a user loses access to their token device. The README is careful that scratch codes are not a functionality required by the TOTP standard and it is up to the developer to decide whether they should be used in their application. Generating five fallback codes per enrolment means five more secrets to store and to protect, and if they are not consumed they become a standing liability, so treating them as optional is the right reading.

The ICredentialRepository contract, and why it throws when unset

The credential repository is the extension point that makes the library usable in a real application, and it is the piece of the design that most deserves attention.

The library can assist with fetching and storing user credentials, and a hook is provided to users who want to integrate this functionality. The ICredentialRepository interface defines the contract between a credential repository and the library, and it establishes the relationship between a user name and its credentials, so that API methods receiving only a user name instead of credentials can be used.

Two methods need to be implemented: `String getSecretKey(String userName)` and `void saveUserCredentials(String userName, ...)`.

The repository can be set in two ways. It can be set on a per-instance basis, using the credentialRepository property of the IGoogleAuthenticator interface, or the library looks for instances of this interface using the Java ServiceLoader API, introduced in Java 6, scanning the META-INF/services package looking for a file named `com.warrenstrange.googleauth.ICredentialRepository` and loading the provider classes listed therein.

The ServiceLoader route is the interesting choice, because it means your credential store is discovered rather than configured. An application that already has a user secrets table can implement the two methods, publish a service file, and every GoogleAuthenticator instance in the process finds it. The per-instance route exists for the cases where you want a different store in a different part of the system.

What the library does not do is hide the failure. If an attempt is made to use the user-name-based methods when no credential repository is configured, an exception is thrown:

java
java.lang.UnsupportedOperationException: An instance of the
  com.warrenstrange.googleauth.ICredentialRepository service must be
  configured in order to use this feature.

An UnsupportedOperationException rather than a null check returning false, and the message names the interface and the mechanism. That is the right behaviour for a security component. A silent failure here would mean an authentication check that appears to pass or to fail for the wrong reason, and the explicit exception means the misconfiguration is found in development rather than in an audit.

The two convenience methods that use the repository are createCredentials("Bob"), which creates a new set of credentials for the user and stores them on the configured repository instance, and authorizeUser("Bob", code), which checks the validity of the code against the secret key of that user returned by the repository.

Building it, and the documentation that ships as a PDF manual

The installing section is the part every Java developer wants, and it is two build systems and a couple of transitive dependencies.

For Maven:

xml
<dependency>
  <groupId>com.warrenstrange</groupId>
  <artifactId>googleauth</artifactId>
  <version>1.4.0</version>
</dependency>

and for Gradle:

code
compile 'com.warrenstrange:googleauth:1.4.0'

The required libraries are automatically pulled into your project: Apache Commons Codec and Apache HTTP client.

Note the version discrepancy before you copy it. The dependency snippet in the README asks for 1.4.0, while the release list in the repository metadata stops at 1.2.0 from 2018-07-24. The library documentation also says it includes full JavaDoc documentation and a JUnit test suite that can be used as example code for most of the library purposes, which is the documentation route most Java users will take.

The build system is an unusual hybrid, and it is a legacy of the project's age. The repository has a pom.xml, an mvnw and an mvnw.cmd wrapper, and a .mvn/ directory, so Maven is the build for the library itself. Alongside that there is configure.ac, an autogen.sh script, a Makefile.am and a doc/ directory, and the documentation sources are Texinfo files from which a PDF manual can be generated by an Autotools-generated Makefile. The bootstrap sequence is:

code
$ ./autogen.sh
$ ./configure
$ make pdf

The README explains why the PDF is generated at all: since typical users will not have a TeX distribution installed on their computers, the PDF manuals for every version of GoogleAuth are hosted at a separate address instead. The Autotools half exists for the documentation, not for the library.

The practical read is that a modern Java project can take the artifact from Maven Central and ignore the build system entirely, and that the PDF manual is the thing to read if you want the full contract rather than the README's summary.

Where GoogleAuth is the wrong choice today

There are three limits, and the first one is about the age of the artefact rather than any specific defect.

The first is that this is a TOTP-only library from a period when TOTP was what you had. The README's own client list ends at BlackBerry, and the release history stops in 2018. TOTP remains a valid second factor and plenty of deployments use it, but the direction of travel for consumer and enterprise second factors is towards WebAuthn and passkeys, where the credential is bound to an authenticator and there is no shared secret to store at all. A new service built today would be choosing a mechanism whose main weakness, that the server holds a symmetric secret which is enough to mint valid codes, is exactly the property WebAuthn was designed to remove.

The second is the age of the dependency footprint. Apache Commons Codec and Apache HTTP client are pulled in automatically, and the minimum Java version to build and use the library is Java 7. On a modern JVM that is a floor rather than a ceiling, and the Gradle snippet uses the old `compile` configuration, which has been removed from Gradle in favour of `implementation`. A build that copies that line verbatim will fail on a current Gradle, and the README has not been updated to reflect that. The same applies to the 1.4.0 version in the snippet, which does not correspond to any published tag in the repository's release list.

The third is the maintenance story. The last push was on 2026-08-14, so the repository is not abandoned, but the release tags are from 2018 and the README instructs bug reporters to read the manual before opening a ticket, which is a sign of a project with a long tail of unresolved issues. Adopting a library whose published artefacts are years behind its branch is a decision that has to be made with your own eyes on the source, not from the README's version number.

The alternative is not to do nothing. Every current TOTP library for Java can do the same three jobs, secret creation, code verification and a pluggable secret store, and the mainstream ones are maintained. What GoogleAuth still has to offer is its simplicity, the ServiceLoader wiring for credential repositories, and a licence that is not LGPL, which matters if you are embedding it in a product you distribute.

Editorial conclusion

Adopt GoogleAuth if you are on a Java 7 era stack, you already have TOTP tokens in the field, and you want a library whose credential storage you can plug into your own repository layer rather than one that dictates a database. Do not adopt it for a new service, because the code is old, the version in the README's dependency snippet is newer than the published tags, and the ecosystem has moved to libraries that support WebAuthn and passkeys. Verify first that your Java runtime meets the stated Java 7 minimum, that the credential repository you implement satisfies the two-method contract, and that your server clock synchronisation is good enough for the tolerance window you configure.

Frequently asked questions

What does the GoogleAuth Java library implement?

It implements the Time-based One-time Password algorithm specified in RFC 6238, and provides the server-side code to create TOTP shared secrets, generate TOTP passwords and verify them. The implementation borrows from Google Authenticator, whose C code served as a reference.

How do I add GoogleAuth to a Maven or Gradle project?

For Maven, add the com.warrenstrange:googleauth dependency, and for Gradle use `compile 'com.warrenstrange:googleauth:1.4.0'`. Apache Commons Codec and Apache HTTP client are pulled in automatically, and the minimum Java version to build and use the library is Java 7.

How does GoogleAuth store and fetch user secrets?

Through the ICredentialRepository interface, which requires implementing `String getSecretKey(String userName)` and `void saveUserCredentials(String userName, ...)`. It can be set per instance or discovered through the Java ServiceLoader API by listing providers in META-INF/services, and calling the user-based methods without one throws UnsupportedOperationException.

What tolerance does GoogleAuth allow for clock drift?

The README says the clock of both the server and the client must be synchronised within the tolerance used by the library, which is set by default to a window of size 3 and can be overridden when configuring a GoogleAuthenticator instance.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. README
  4. Releases
  5. wstrange/GoogleAuth on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wstrange-googleauth.svg)](https://hysenlabs.com/projects/wstrange-googleauth)

Was this useful?