Code Monkey home page Code Monkey logo

googleauth's Introduction

Build Status License

README

GoogleAuth is a Java server library that implements the Time-based One-time Password (TOTP) algorithm specified in RFC 6238.

This implementation borrows from Google Authenticator, whose C code has served as a reference, and was created upon code published in this blog post by Enrico M. Crisostomo.

Whom Is This Library 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.

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).

Requirements

The minimum Java version required to build and use this library is Java 7.

Installing

Add a dependency to your build environment.

If you are using Maven:

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

If you are using Gradle:

 compile 'com.warrenstrange:googleauth:1.4.0'

The required libraries will be automatically pulled into your project:

  • Apache Commons Codec.
  • Apache HTTP client.

Client Applications

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.

However, this 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.

Library Documentation

This library includes full JavaDoc documentation and a JUnit test suite that can be used as example code for most of the library purposes.

Texinfo documentation sources are also included and a PDF manual can be generated by an Autotools-generated Makefile:

  • To bootstrap the Autotools, the included autogen.sh script can be used.

    $ ./autogen.sh
    
  • Configure and build the documentation:

    $ ./configure
    $ make pdf
    

Since typical users will not have a TeX distribution installed in their computers, the PDF manuals for every version of GoogleAuth are hosted at this address.

Usage

The following code creates a new set of credentials for a user. 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.

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. A convenience method is provided to easily encode the secret key and the account information into a QRcode.

When a user wishes to log in, he will provide the TOTP password generated by his device. By default, a TOTP password is a 6 digit integer that changes every 30 seconds. Both the password length and its validity can be changed. However, many token devices such as Google Authenticator use the default values specified by the TOTP standard and they do not allow for any customization.

The following code checks the validity of the specified password against the provided Base32-encoded secretKey:

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

Since TOTP passwords are time-based, 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.

Client

This library can generate TOTP codes for testing or for use as a software-based client.

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

The codes generated in this way can be used as an alternative to the codes that would be generated by the Google Authenticator App (or other client device).

Scratch codes

By default 5 scratch codes are generated together with a new shared secret. Scratch codes are meant to be a safety net in case a user loses access to their token device. Scratch nodes are not a functionality required by the TOTP standard and it is up to the developer to decide whether they should be used in his application.

Storing User Credentials

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 this library.

The credential repository can be set in multiple ways:

  • The credential repository can be set on a per-instance basis, using the credentialRepository property of the IGoogleAuthenticator interface.

  • The library looks for instances of this interface using the Java ServiceLoader API (introduced in Java 6), that is, scanning the META-INF/services package looking for a file named com.warrenstrange.googleauth.ICredentialRepository and, if found, loading the provider classes listed therein.

Two methods needs to be implemented in the ICredentialRepository interface.

  • String getSecretKey(String userName).
  • void saveUserCredentials(String userName, ...).

The credentials repository establishes the relationship between a user name and its credentials. This way, API methods receiving only a user name instead of credentials can be used.

The following code creates a new set of credentials for the user Bob and stores them on the configured ICredentialRepository instance:

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

The following code checks the validity of the specified code against the secret key of the user Bob returned by the configured ICredentialRepository instance:

GoogleAuthenticator gAuth = new GoogleAuthenticator();
boolean isCodeValid = gAuth.authorizeUser("Bob", code);

If an attempt is made to use such methods when no credential repository is configured, an exception is thrown:

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

Bug Reports

Please, read the manual before opening a ticket. If you have read the manual and you still think the behaviour you are observing is a bug, then open a ticket on github.


Copyright (c) 2013 Warren Strange

Copyright (c) 2014-2019 Enrico M. Crisostomo

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  • Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

googleauth's People

Contributors

ari avatar chenzhang22 avatar dependabot[bot] avatar emcrisostomo avatar fcsean avatar jfonte-accesso avatar karanb192 avatar user4302 avatar wstrange avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

googleauth's Issues

Unit Tests Without Assertions?

I'm confused about the unit tests without assertions. I took a quick stab at writing some assertions, but since all of the (new) assertions fail, something's wrong with the code or (very likely) my assumptions.

jamiejackson@fb34c7b

How to instatiate a new GoogleAuthenticatorKey?

Hey,

I need to instatiate a new GoogleAuthenticatorKey because I want to generate a QR-Code:
String link = GoogleAuthenticatorQRGenerator.getOtpAuthURL("MyProgram", "[email protected]", <key>);

I already know that it's not possible to do new GoogleAuthenticatorKey(). I already stored the Key in a Credentials Manager.

My Question: How can I get that GoogleAuthenticatorKey variable / Get the QR-Code URL without having an GoogleAuthenticatorKey variable?

Thanks in advance,
Niklas

Feature request

I might be missing out on something here, but ... would it be possible to make the calculateCode() method public?
I'm using your lib on the server side, and for testing purposes, it would be great if I could use the same lib for the client side code as well. Others might be interested to use your code when writing client applications.

I worked around it by shamelessly borrowing from your code and basically copying the checkCode() method. I just changed the return type from "boolean" to "String[]", so it now returns an array of the calculated hashes instead of a "isValid".

The signature of my method now looks like this:

/**
 * Creates a set of One Time Passwords for the given secret.
 *
 * @param aSecret the secret for which OTPs shall be generated
 * @param aNumberOfOTPs the number of OTPs to be generated. The one "in the middle" is the "most current one". 
 * @return an array of OTPs.
 */
public static String[] createOTP(String aSecret, int aNumberOfOTPs) {
      ...
    }

And, in any case: Thanks for putting this together!

Allow regeneration of QR code

My apologies if I missed something in the API.

Right now, you can only generate a QR code with a GoogleAuthenticatorKey object. This object can only be created by a call to createCredentials(). My use case is that I need to recreate the QR code with a preexisting secret (that has been persisted to the database), but there doesn't seem to be any way to do that with the existing API, as I cannot create a GoogleAuthenticatorKey object, or call the QR code methods with just the key. It would be sufficient to overload getOtpAuthURL() to take 3 strings (including the key).

Please advise...

Hi,
First of all thank you for creating such a great tool. I am currently in my University final year and are using your API to implement two factor authentication in my final year project.

However there is an issue; the storage of the secret key. Since the program requires the secret key in order to generate TOTP, I cannot possibly just store the hash, and if I were to encrypt the secret key that would means that I will have to hard code the decryption key. Furthermore my application is designed to work offline (i.e. cannot host an authentication server).

I remember our lecturer taught us in class that it is a bad practice to hard code secret key and should also never store key in clear.

I will greatly appreciate your help if you could give me some advice and will be really grateful.

Best Regards,
Jacky

GoogleAuthenticator.authorize need parameter TimeZone

Hi,

the method public boolean authorize(String secret, int verificationCode) need has a TimeZone parameter, because my timezone default not is UTC, so the possible best implementation is :
TimeZone tz = TimeZone.getTimeZone(timeZoneParameter);

ICredentialRepository getters

The asymmetry of this interface bothers me. It seems to serve no purpose the way it is written since either the library takes care of the whole getting/setting for us, or it doesn't. One option is:

gAuth.authenticate(username, code)

Which will call a getter in the interface to fetch the appropriate secret key from the data store. What do you think of this approach?

Note also that 'authorise' is the wrong word since it often means something different. Authentication is about identifying a user. Authorisation is about determine the level of access to provide that user.

Create an interface for GoogleAuthenticator class

GoogleAuthenticator class is currently defined as final and it doesn't implement any interface which would create a contract for this class. As a result the class can't be easily mocked in unit tests.

For example line like this:
GoogleAuthenticator googleAuthenticator = EasyMock.createMock(GoogleAuthenticator.class);

ends with an exception:
java.lang.IllegalArgumentException: Cannot subclass final class class com.warrenstrange.googleauth.GoogleAuthenticator

GoogleAuthenticator class could implement an interface (e.g. IGoogleAuthenticator) with signatures of it's public methods.

Secrets in Base32 are case-sensitive

Took me a while to find out what's wrong. Google prints the codes in lowercase but the library decodes them wrong because of this issue. After doing .toUpperCase() the codes match. Probably best not to confuse people and uppercase it anyway at this line. While it could be patched on the Apache's side I think it's nice to cover this default Google behavior on the library's side.

Unable to authorize codes that have a leading zero

Because they are typed to be an int, attempting to authorize a code that has a leading zero will throw an exception. Leading zeros aren't allowed in non-decimal numbers.

[ERROR] GoogleAuth/src/test/java/com/warrenstrange/googleauth/GoogleAuthTest.java:[66,48] integer number too large: 098775

How to fix the length of the TOTP ?

I am just trying this library for generating random TOTP of 6 digits by setting the code digits property but sometimes I am getting the 4/5 digit TOTP.

Can somebody help out how to fix the length of the TOTP?

Strange results

Hey,
I used the code as is my main is

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

GoogleAuthenticator gAuth = new GoogleAuthenticator();
boolean isCodeValid = gAuth.authorize(key.getKey(), key.getVerificationCode);

isCodeValid = false. Why ?
chaning setWindowSize(1000000) cause it to return true, but calling gAuth.authorize(key.getKey(), key.getVerificationCode + 1) also return true !!!

Thanks,
Baruch

Fail to authorize

I have include GoogleAuth in scala

org.scalatest.exceptions.TestFailedException: false was not equal to true

    val gAuth = new GoogleAuthenticator()

    val key = gAuth.createCredentials()

    Thread.sleep(5 * 1000)

    val isCodeValid = gAuth.authorize(key.getKey, key.getVerificationCode)

    isCodeValid shouldBe true

Great project.

How's license?
But jus could use?

Let me know us.
Thanks.

Creating app password

Does this library support creating app password?
If it does, can you give me an example?

Thanks,

Setting timeout to passcode

How can we restrict the passcode's lifetime?
I am trying it by using the setTimeStepSizeInMillis method but it doesn't seem to be working.
Can anyone help me with this?

totp not validating with other library

I'm trying to ensure this lib will work with a ruby/python implemented totp library: pyotp. If I use their example secret value base32secret3232 in your library - the totp won't validate. but if I uppercase the secret in both libraries, it validates.

Verification codes starting with 0 handled incorrectly

Due to the usage of integers in the code comparison of a hash starting with a zero is handled incorrectly.

This causes the 0 at the start of the verification code to be truncated and therefore not used in the comparison.

To summarize we have the following situation
Expected verification code = 012345
Entered verification code = 12345
Result = valid verification code
Expected result = verification code is invalid

The RFC returns strings when generating the totp code.

totp password

Hey,

This a feature request for exporting the methods to create TOTP passwords.

Thanks,
Baruch

Replacement for Google Charts usage

Google image charts seems to be deprecated since 2012 and getting permanently shut down on March 14th, 2019

GoogleAuthenticatorQRGenerator.TOTP_URI_FORMAT seems to use this (https://chart.googleapis.com) to generate QR code and will fail to work after March 14th.

Is this issue known and is up to the developers using this library to find an alternative to generate QR code after getting otpauth or are there any plans to update this library with another QR code generator?

not working for me

The google authenticator app and this code are generating different code not the same one. it always says false . :(

GoogleAuthenticator gAuth = new GoogleAuthenticator();
final GoogleAuthenticatorKey key = gAuth.createCredentials();
System.out.println(key.getKey());

System.out.println("Enter your code: ");
Scanner scanner = new Scanner(System.in);
String code = scanner.nextLine();
int CodInt = Integer.parseInt(code);
System.out.println("Your code is " + code);
boolean isCodeValid = gAuth.authorize(key.getKey(), CodInt);

Not setting scratch codes to GoogleAuthenticatorKey builder throws NPE

When using the builder for GoogleAuthenticatorKey, the scratch codes are passed into the ArrayList constructor:
this.scratchCodes = new ArrayList<>(scratchCodes);

However, if the scratch codes were not set in the builder, the ArrayList constructor throws NullPointerException on this line. If the scratch codes are required, I would suggest that the builder initialize the value to an empty list.

Setting valid time to OTP

I want to restrict the valid time of OTP to 5 min and I am using setTimeStepSizeInMillis method to set the valid time for the generated OTP. But the generated OTP is getting invalidated before 5 min.

Please help me with this...Thanks

Enhance the GoogleAuthenticator.authorise() to support scratchCodes?

This will require that the interface ICredentialRepository to include a method:
String getScratchCodes(String userName)

It is natural to have save and get in the same class/interface.

Alternatively, we can add a method GoogleAuthenticator.authoriseWithScratchCodes() and keep authorise() unchanged.

Are GoogleAuthenticator methods thread safe?

Hi @wstrange

Sorry for posting an issue I could not find any other place to post my question but I was wondering if GoogleAuthenticator methods are thread safe particularly getTotpPassword() and authorize()

BTW google drive folders where pre-built docs should be are all blank

thanks
Alex

Doesn't work for some reason

Hi
Tried to implement this code to my project, but all the times the verification code was invalid. I used a
GoogleAuthenticatorConfigBuilder instance with the different settings (digits, windows, key representations), but always failure.

I use your code with Google Authenticator. I don't know. May be there are a special settings for it ?
Can you help me ?

By default I use code bellow.

  1. Here is creation user's creditians
      val builder = new GoogleAuthenticatorConfigBuilder()
      val gAuth = new GoogleAuthenticator(builder.build())
      gAuth.setCredentialRepository(new CreditRepository)

      val creditiands = gAuth.createCredentials("sa")
      val otpAuthURL = GoogleAuthenticatorQRGenerator.getOtpAuthURL("SomeSite", "sa", creditiands)

As CreditRepository I just used a something like a Mock object:

class CreditRepository extends ICredentialRepository{ 
  override def getSecretKey(userName: String): String = {
    return "KR52HV2U5Z4DWGLJ"
  }
  override def saveUserCredentials(
                            userName: String, 
                            secretKey: String, 
                            validationCode: Int, 
                            scratchCodes: util.List[Integer]): Unit = { }
}
  1. Here is a checking:
      var builder = new GoogleAuthenticatorConfigBuilder()
      var gAuth = new GoogleAuthenticator(builder.build())
      gAuth.setCredentialRepository(new CreditRepository)

      val isCodeValid =  gAuth.authorizeUser("sa", <verificationCode>)

Base64 encoding provider

Hi @wstrange
It could be a bit far fetched but I am trying to reduce dependencies. since JDK8 has built in Base64 and many server environments also have some Base64 utilities does it make sense to make this dependency optional and allow configuring Authenticator with an implementation of your internal Base64 interface.
This way with httputils made optional your library will be a little sweet no dependencies library. otherwise bringing it int server environment may cause jar conflicts

problem in implementation

I have dropped the created jar in the installation in opt/alfresco_installation/tomcat/lib folder but nothing happens.No extra field for capturing the passcode appears on the alfresco share page except the username and password.
I have also tried by just dropping the dependencies in my repo and share maven projects.But still nothing happens.

and I am little confused that this GoogleAuth is just the code for the backened validation that creates and verifies OTPs or is it the complete code that has to be integrated with our maven code?what about the UI part.how to render the extra input field in alfresco share page.
Basically.I am confused with its complete implementation in alfresco.

Any help would be greatly appreciated.

Contributor request

Hi Warren,

How's all going?

I wanted to ask you about adding me as a contributor of GoogleAuth, so it's easier for both of us to keep this library going.

Cheers,
-- Enrico

new GoogleAuthenticator() is no response in Linux Server

I run this lib in Mac is ok ,but when I run in Linux ,something wrong is happen

When I run this code:

GoogleAuthenticator gAuth=new GoogleAuthenticator()

I'am in long time waiting,and no response

Is there something lib I need to install to Linux first?

Or something else?

What is the verificationCode at UNIX Epoch for?

The key object (GoogleAuthenticatorKey) has a secret (the purpose of which is clear), scratch codes (the purpose is clear) and a verificationCode at UNIX Epoch. The purpose of the last one is not documented, and it's not used or passed anywhere (except to the repository).

Is there any purpose of that one and do we have to store it. If yes - please add to the documentation. If not - maybe get rid of it?

Clarification please

Many thanks for the great effort.
I tried your code and it works fine.

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. ?

Thanks
Jay

Add validation code generation support

Currently, the library has the pieces to support the generation of validation codes but they are package private and not tied together. I have identified the changes that would be required and think this would be valuable to add.

Java 6

Hi @wstrange

Is it possible to support java 6?
This library currently is compiled with java 7 (see pom.xml 1.7)
I looked in the source code and saw a few java 7 code constructs (about 8 or 9):

  • a few empty <> for example new ArrayList<>() this should be easily converted to new ArrayList<Integer>()
  • underscore in number, removing underscore makes it compatible with java 6.

Dependency httpclient supports java6 if i'm correct.

Hope you consider it.

Same API Code is not working in Singapore

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/GoogleAuth

  1. Is there any dependency with the Country name .
    Thanks in Advance..

Remove dependency on Preconditions

Can we remove the hidden dependency on com.google.common.base.Preconditions?

Also, I can't find the dependency on JAX-RS. Why is that there?

Differents codes with differents mobiles

Hi Warren

I´ve tried your lib with differents mobiles and I got always an invalid code with a
"Samsung GT-I8160" (samsung galaxy mini 2) device. All devices had the same google authenticator, version 2.49.
I used the QR and the manual configuration with google auth in my tests without success. Any ideas about my problem?

Thanks in advance.
Al

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.