# Two-Factor Authentication
[![npm](https://img.shields.io/npm/v/2fa-utils?style=for-the-badge)](https://www.npmjs.com/package/2fa-utils)
[![Build](https://img.shields.io/github/actions/workflow/status/boranseckin/2fa-utils/node.js.yml?style=for-the-badge)](https://github.com/boranseckin/2fa-utils/actions/workflows/node.js.yml)
[![Codecov](https://img.shields.io/codecov/c/gh/boranseckin/2fa-utils?style=for-the-badge)](https://codecov.io/gh/boranseckin/2fa-utils)

Using the algorithm provided in [RFC 4226](https://tools.ietf.org/rfc/rfc4226), can generate and verify HMAC-based one-time password (HOTP) and time-based one-time password (TOTP).

## Features
- Generate base-32 encoded secrets.
- Generate HMAC-based one-time passwords (HOTP) at a specific length.
- Generate time-based HOTPs at a specific amount of windows.
- Verify generated tokens.

## Usage
### Generating Secret
For each account, a secret must be generated and shared between the server and the client. This secret will be used to create and verify HOTPs.
```js
const secret = twoFA.generateSecret();
```

### Generating HOTP
HOTP requires a base32-encoded secret and a counter with time-step.
```js
// Generate base32 secret
const secret = twoFA.generateSecret();
// Create counter with 30 seconds interval 
const counter = Math.floor(Date.now() / 30000);

const hotp = twoFA.generateHOTP(secret, counter, 6)
```

### Generating TOTP
Generating TOTP allows you to get a HOTP in a specific time window.
```js
const secret = twoFA.generateSecret();

// Get the current time window's token
const currentTotp = twoFA.generateTOTP(secret, 0);

// Get the future time window's token (1 window ahead)
const futureTotp = twoFA.generateTOTP(secret, 1);

// Get the past time window's token (1 window behind)
const pastTotp = twoFA.generateTOTP(secret, -1);
```

### Verifying HOTP
Verify tokens supplied via user input.
```js
function verifyHOTP(inputToken) {
  const secret = twoFA.generateSecret();
  const counter = Math.floor(Date.now() / 30000);

  // Actual token generated by the server
  const actualToken = twoFA.generateHOTP(secret, counter)

  if (inputToken === actualToken) return true;
  return false
}
```

### Verifying TOTP
Verify tokens supploed via user input with a time tolerance.
```js
const secret = twoFA.generateSecret();

const inputToken = '111111';

/* This will return true if the input token 
  - is currently valid,
  - was previously valid in the last window,
  - will be valid in the next window.
*/
const isTokenValid = twoFA.verifyTOTP(inputToken, secret, 1);
```

## Dependencies
- [hi-base32](https://www.npmjs.com/package/hi-base32)

## Author
- Boran Seckin

## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
