Two- / Multi- Factor Authenication (2FA / MFA / OTP) for node.js
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
5.7 KiB

9 years ago
Node.js Authenticator
=====================
6 years ago
| Sponsored by [ppl](https://ppl.family)
9 years ago
Two- and Multi- Factor Authenication (2FA / MFA) for node.js
9 years ago
![](https://blog.authy.com/assets/posts/authenticator.png)
9 years ago
There are a number of apps that various websites use to give you 6-digit codes to increase security when you log in:
9 years ago
* Authy (shown above) [iPhone](https://itunes.apple.com/us/app/authy/id494168017?mt=8) | [Android](https://play.google.com/store/apps/details?id=com.authy.authy&hl=en) | [Chrome](https://chrome.google.com/webstore/detail/authy/gaedmjdfmmahhbjefcbgaolhhanlaolb?hl=en) | [Linux](https://www.authy.com/personal/) | [OS X](https://www.authy.com/personal/) | [BlackBerry](https://appworld.blackberry.com/webstore/content/38831914/?countrycode=US&lang=en)
* Google Authenticator [iPhone](https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8) | [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en)
* Microsoft Authenticator [Windows Phone](https://www.microsoft.com/en-us/store/apps/authenticator/9wzdncrfj3rj) | [Android](https://play.google.com/store/apps/details?id=com.microsoft.msa.authenticator)
9 years ago
* GAuth [FxOS](https://marketplace.firefox.com/app/gauth/)
There are many [Services that Support MFA](http://lifehacker.com/5938565/heres-everywhere-you-should-enable-two-factor-authentication-right-now),
9 years ago
including Google, Microsoft, Facebook, and Digital Ocean for starters.
9 years ago
This module uses [`notp`](https://github.com/guyht/notp) which implements `TOTP` [(RFC 6238)](https://www.ietf.org/rfc/rfc6238.txt)
(the *Authenticator* standard), which is based on `HOTP` [(RFC 4226)](https://www.ietf.org/rfc/rfc4226.txt)
to provide codes that are exactly compatible with all other *Authenticator* apps and services that use them.
8 years ago
Browser & Commandline Authenticator
9 years ago
---------------------
8 years ago
You may also be interested in
9 years ago
6 years ago
* [Browser Authenticator](https://git.coolaj86.com/coolaj86/browser-authenticator) over at <https://git.coolaj86.com/coolaj86/browser-authenticator>
* [Commandline Authenticator](https://git.coolaj86.com/coolaj86/authenticator-cli) over at <https://git.coolaj86.com/coolaj86/authenticator-cli>
8 years ago
Install
9 years ago
=====
8 years ago
**node.js api**
9 years ago
```bash
npm install authenticator --save
```
8 years ago
**command line**
```bash
npm install authenticator-cli --global
```
Usage
=====
**node.js api**
9 years ago
```javascript
'use strict';
var authenticator = require('authenticator');
var formattedKey = authenticator.generateKey();
// "acqo ua72 d3yf a4e5 uorx ztkh j2xl 3wiz"
var formattedToken = authenticator.generateToken(formattedKey);
// "957 124"
authenticator.verifyToken(formattedKey, formattedToken);
// { delta: 0 }
authenticator.verifyToken(formattedKey, '000 000');
// null
9 years ago
authenticator.generateTotpUri(formattedKey, "john.doe@email.com", "ACME Co", 'SHA1', 6, 30);
//
// otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
```
9 years ago
8 years ago
**command line**
```
# see help
authenticator --help
# generate a key and display qr code
authenticator --qr
```
9 years ago
API
---
9 years ago
8 years ago
```javascript
generateKey() // generates a 32-character (160-bit) base32 key
9 years ago
8 years ago
generateToken(formattedKey) // generates a 6-digit (20-bit) decimal time-based token
9 years ago
8 years ago
verifyToken(formattedKey, formattedToken) // validates a time-based token within a +/- 30 second (90 seconds) window
// returns `null` on failure or an object such as `{ delta: 0 }` on success
8 years ago
// generates an `OTPAUTH://` scheme URI for QR Code generation.
generateTotpUri(formattedKey, accountName, issuer, algorithm, digits, period)
```
**OTPAuth Scheme**
* <https://github.com/google/google-authenticator/wiki/Key-Uri-Format>
* `otpauth://totp/<<ISSUER>>:<<ACCOUNT_NAME>>?secret=<<BASE32_KEY>>&issuer=<<ISSUER>>`
* `otpauth://totp/<<ISSUER>>:<<ACCOUNT_NAME>>?secret=<<BASE32_KEY>>&issuer=<<ISSUER>>&algorithm=<<ALGO>>&digits=<<INT>>&period=<<SECONDS>>`
Note that `ISSUER` is specified twice for backwards / forwards compatibility.
9 years ago
QR Code
-------
9 years ago
9 years ago
See <https://davidshimjs.github.io/qrcodejs/> and <https://github.com/soldair/node-qrcode>.
9 years ago
![](http://cdn9.howtogeek.com/wp-content/uploads/2014/10/sshot-7-22.png)
9 years ago
Example use with `qrcode.js` in the browser:
9 years ago
```javascript
'use strict';
var el = document.querySelector('.js-qrcode-canvas');
var link = "otpauth://totp/{{NAME}}?secret={{KEY}}";
var name = "Your Service";
// remove spaces, hyphens, equals, whatever
var key = "acqo ua72 d3yf a4e5 uorx ztkh j2xl 3wiz".replace(/\W/g, '').toLowerCase();
var qr = new QRCode(el, {
text: link.replace(/{{NAME}}/g, name).replace(/{{KEY}}/g, key)
});
```
Formatting
----------
All non-alphanumeric characters are ignored, so you could just as well use hyphens
or periods or whatever suites your use case.
These are just as valid:
* "acqo ua72 d3yf a4e5 - uorx ztkh j2xl 3wiz"
* "98.24.63"
0, 1, 8, and 9 also not used (so that base32).
To further avoid confusion with O, o, L, l, I, B, and g
you may wish to display lowercase instead of uppercase.
TODO: should this library replace 0 with o, 1 with l (or I?), 8 with b, 9 with g, and so on?
90-second Window
----------------
The window is set to +/- 1, meaning each token is valid for a total of 90 seconds
(-30 seconds, +0 seconds, and +30 seconds)
to account for time drift (which should be very rare for mobile devices)
and humans who are handicapped or otherwise struggle with quick fine motor skills (like my grandma).
Why not SpeakEasy?
------------------
9 years ago
It doesn't use native node crypto and there are open security issues which have been left unaddressed.