An open API service indexing awesome lists of open source software.

https://github.com/samdjstevens/java-totp

A java library for implementing Time-based One Time Passwords for Multi-Factor Authentication.
https://github.com/samdjstevens/java-totp

2fa authy google-authenticator java mfa totp-tfa

Last synced: 20 days ago
JSON representation

A java library for implementing Time-based One Time Passwords for Multi-Factor Authentication.

Awesome Lists containing this project

README

        

# Time-based One Time Password (MFA) Library for Java

[![CircleCI](https://circleci.com/gh/samdjstevens/java-totp/tree/master.svg?style=svg&circle-token=10b865d8ba6091caba7a73a5a2295bd642ab79d5)](https://circleci.com/gh/samdjstevens/java-totp/tree/master) [![Coverage Status](https://coveralls.io/repos/github/samdjstevens/java-totp/badge.svg)](https://coveralls.io/github/samdjstevens/java-totp) [![Maven Central](https://img.shields.io/maven-central/v/dev.samstevens.totp/totp.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22dev.samstevens.totp%22%20AND%20a:%22totp%22)

A java library to help generate and verify time-based one time passwords for Multi-Factor Authentication.

Generates QR codes that are recognisable by applications like Google Authenticator, and verify the one time passwords they produce.

Inspired by [PHP library for Two Factor Authentication](https://github.com/RobThree/TwoFactorAuth), a similar library for PHP.

## Requirements

- Java 8+

## Spring Boot

The quickest way to start using this library in a Spring Boot project is to require the TOTP Spring Boot Starter. See [Using Java-TOTP with Spring Boot](totp-spring-boot-starter/README.md) for more information, or read on to learn about the library.

## Installation

#### Maven

To add this library to your java project using Maven, add the following dependency:

```xml

dev.samstevens.totp
totp
1.7.1

```

#### Gradle

To add the dependency using Gradle, add the following to the build script:

```
dependencies {
compile 'dev.samstevens.totp:totp:1.7.1'
}
```

## Usage

- [Generating secrets](#generating-a-shared-secret)
- [Generating QR codes](#generating-a-qr-code)
- [Verifying one time passwords](#verifying-one-time-passwords)
- [Using different time providers](#using-different-time-providers)
- [Recovery codes](#recovery-codes)

### Generating a shared secret

To generate a secret, use the `dev.samstevens.totp.secret.DefaultSecretGenerator` class.
```java
SecretGenerator secretGenerator = new DefaultSecretGenerator();
String secret = secretGenerator.generate();
// secret = "BP26TDZUZ5SVPZJRIHCAUVREO5EWMHHV"
```

By default, this class generates secrets that are 32 characters long, but this number is configurable via

the class constructor.

```java
// Generates secrets that are 64 characters long
SecretGenerator secretGenerator = new DefaultSecretGenerator(64);
```

### Generating a QR code

Once a shared secret has been generated, this must be given to the user so they can add it to an MFA application, such as Google Authenticator. Whilst they could just enter the secret manually, a much better and more common option is to generate a QR code containing the secret (and other information), which can then be scanned by the application.

To generate such a QR code, first create a `dev.samstevens.totp.qr.QrData` instance with the relevant information.

```java
QrData data = new QrData.Builder()
.label("[email protected]")
.secret(secret)
.issuer("AppName")
.algorithm(HashingAlgorithm.SHA1) // More on this below
.digits(6)
.period(30)
.build();
```

Once you have a `QrData` object holding the relevant details, a PNG image of the code can be generated using the `dev.samstevens.totp.qr.ZxingPngQrGenerator` class.

```java
QrGenerator generator = new ZxingPngQrGenerator();
byte[] imageData = generator.generate(data)
```

The `generate` method returns a byte array of the raw image data. The mime type of the data that is generated by the generator can be retrieved using the `getImageMimeType` method.

```java
String mimeType = generator.getImageMimeType();
// mimeType = "image/png"
```

The image data can then be outputted to the browser, or saved to a temporary file to show it to the user.

#### Embedding the QR code within HTML

To avoid the QR code image having to be saved to disk, or passing the shared secret to another endpoint that generates and returns the image, it can be encoded in a [Data URI](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), and embedded directly in the HTML served to the user.

```java
import static dev.samstevens.totp.util.Utils.getDataUriForImage;
...
String dataUri = getDataUriForImage(imageData, mimeType);
// dataUri = data:image/png;base64,iVBORw0KGgoAAAANSU...
```

The QR code image can now be embedded directly in HTML via the data URI. Below is an example using [Thymeleaf](https://www.thymeleaf.org/):

```html

```

### Verifying one time passwords

After a user sets up their MFA, it's a good idea to get them to enter two of the codes generated by their app to verify the setup was successful. To verify a code submitted by the user, do the following:

```java
TimeProvider timeProvider = new SystemTimeProvider();
CodeGenerator codeGenerator = new DefaultCodeGenerator();
CodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);

// secret = the shared secret for the user
// code = the code submitted by the user
boolean successful = verifier.isValidCode(secret, code)
```

This same process is used when verifying the submitted code every time the user needs to in the future.

#### Using different hashing algorithms

By default, the `DefaultCodeGenerator` uses the SHA1 algorithm to generate/verify codes, but SHA256 and SHA512 are also supported. To use a different algorithm, pass in the desired `HashingAlgorithm` into the constructor:

```java
CodeGenerator codeGenerator = new DefaultCodeGenerator(HashingAlgorithm.SHA512);
```

When verifying a given code, **you must use the same hashing algorithm** that was specified when the QR code was generated for the secret, otherwise the user submitted codes will not match.

#### Setting the time period and discrepancy

The one time password codes generated in the authenticator apps only last for a certain time period before they are re-generated, and most implementations of TOTP allow room for codes that have recently expired, or will only "become valid" soon in the future to be accepted as valid, to allow for a small time drift between the server and the authenticator app (discrepancy).

By default on a `DefaultCodeVerifier` the time period is set to the standard 30 seconds, and the discrepancy to 1, to allow a time drift of +/-30 seconds. These values can be changed by calling the appropriate setters:

```java
DefaultCodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);
// sets the time period for codes to be valid for to 60 seconds
verifier.setTimePeriod(60);

// allow codes valid for 2 time periods before/after to pass as valid
verifier.setAllowedTimePeriodDiscrepancy(2);
```

Like the hashing algorithm, **the time period must be the same** as the one specified when the QR code for the secret was created.

#### Setting how many digits long the generated codes are

Most TOTP implementations generate codes that are 6 digits long, but codes can have a length of any positive non-zero integer. The default number of digits in a code generated by a `DefaultCodeGenerator` instance is 6, but can be set to a different value by passing the number as the second parameter in the constructor:

```java
CodeGenerator codeGenerator = new DefaultCodeGenerator(HashingAlgorithm.SHA1, 4);
```

The above generator will generate codes of 4 digits, using the SHA1 algorithm.

Once again, **the number of digits must be the same** as what was specified when the QR code for the secret was created.

### Using different time providers

When verifying user submitted codes with a `DefaultCodeVerifier`, a `TimeProvider` is needed to get the current time (unix) time. In the example code above, a `SystemTimeProvider` is used, but this is not the only option.

#### Getting the time from the system

Most applications should be able to use the `SystemTimeProvider` class to provide the time, which gets the time from the system clock. If the system clock is reliable, it is reccomended that this provider is used.

#### Getting the time from an NTP Server

If the system clock cannot be used to accurately get the current time, then you can fetch it from an NTP server with the `dev.samstevens.totp.time.NtpTimeProvider` class, passing in the NTP server hostname you wish you use.

```java
TimeProvider timeProvider = new NtpTimeProvider("pool.ntp.org");
```

The default timeout for the requests to the NTP server is 3 seconds, but this can be set by passing in the desired number of milliseconds as the second parameter in the constructor:

```java
TimeProvider timeProvider = new NtpTimeProvider("pool.ntp.org", 5000);
```

**Using this time provider requires that the [Apache Commons Net](https://commons.apache.org/proper/commons-net) library is available on the classpath**. Add the dependency to your project with Maven/Gradle like this:

**Maven**:

```xml

commons-net
commons-net
3.6

```

**Gradle**:

```
dependencies {
compile 'commons-net:commons-net:3.6'
}
```

### Recovery Codes

Recovery codes can be used to allow users to gain access to their MFA protected account without providing a TOTP, bypassing the MFA process. This is usually given as an option to the user so that in the event of losing access to the device which they have registered the MFA secret with, they are still able to log in.

Usually, upon registering an account for MFA, several one-time use codes will be generated and presented to the user, with instructions to keep them very safe. When the user is presented with the prompt for a TOTP in the future, they can opt to enter one of the recovery codes instead to gain access to their account.

Most of the logic needed for implementing recovery codes (storage, associating them with a user, checking for existance, etc) is implementation specific, but the codes themselves can be generated via this library.

The default implementation provided in this library generates recovery codes :

- of 16 characters
- composed of numbers and lower case characters from latin alphabet (for a total of 36 possible characters)
- split in groups separated with dash for better readability

Thoses settings guarantees recovery codes security (with an entropy of 82 bits) while keeping codes simple to read and enter by end user when needed.

```java
import dev.samstevens.totp.recovery.RecoveryCodeGenerator;
...
// Generate 16 random recovery codes
RecoveryCodeGenerator recoveryCodes = new RecoveryCodeGenerator();
String[] codes = recoveryCodes.generateCodes(16);
// codes = ["tf8i-exmo-3lcb-slkm", "boyv-yq75-z99k-r308", "w045-mq6w-mg1i-q12o", ...]
```

## Running Tests

To run the tests for the library with Maven, run `mvn test`.

## License

This project is licensed under the [MIT license](https://opensource.org/licenses/MIT).