@levminer/speakeasy
Advanced tools
Comparing version 1.0.7 to 1.1.0
MIT License | ||
Copyright (c) 2020 Levminer | ||
Copyright (c) 2020 Lőrik Levente | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
11
main.js
@@ -434,2 +434,4 @@ const base32 = require("base32.js") | ||
* @param {String} [options.name] The name to use with Google Authenticator. | ||
* @param {String} [options.issuer] The provider or service with which the | ||
* secret key is associated. | ||
* @param {Boolean} [options.qr_codes=false] (DEPRECATED. Do not use to prevent | ||
@@ -449,2 +451,3 @@ * leaking of secret to a third party. Use your own QR code implementation.) | ||
const name = encodeURIComponent(options.name || "SecretKey") | ||
const issuer = options.issuer | ||
const qr_codes = options.qr_codes || false | ||
@@ -484,2 +487,3 @@ const google_auth_qr = options.google_auth_qr || false | ||
label: name, | ||
issuer: issuer, | ||
}) | ||
@@ -576,3 +580,3 @@ } | ||
let secret = options.secret | ||
const label = options.label | ||
let label = options.label | ||
const issuer = options.issuer | ||
@@ -610,3 +614,6 @@ const type = (options.type || "totp").toLowerCase() | ||
const query = { secret: secret } | ||
if (issuer) query.issuer = issuer | ||
if (issuer) { | ||
query.issuer = issuer | ||
label = `${issuer}:${label}` | ||
} | ||
@@ -613,0 +620,0 @@ // validate algorithm |
{ | ||
"name": "@levminer/speakeasy", | ||
"description": "Two-factor authentication for Node.js. Generate One-time passcode generator (HOTP/TOTP) with support for Google Authenticator.", | ||
"version": "1.0.7", | ||
"version": "1.1.0", | ||
"homepage": "http://github.com/Levminer/speakeasy", | ||
@@ -6,0 +6,0 @@ "bugs": "https://github.com/Levminer/speakeasy/issues", |
100
README.md
@@ -5,11 +5,13 @@ # @levminer/speakeasy | ||
- Use Buffer.alloc() instead new Buffer | ||
1. Use Buffer.alloc() and Buffer.from() instead deprecated new Buffer | ||
- ES6 syntax: let, const, arrow functions | ||
1. ES6 syntax: let, const, arrow functions | ||
- Fixed some known bugs | ||
1. Fixed some known bugs | ||
1. Import syntax | ||
--- | ||
**Jump to** — [Install](#install) · [Two-Factor Usage](#two-factor) · [General Usage](#general-usage) · [Documentation](#documentation) · [Contributing](#contributing) · [License](#license) | ||
**Jump to** — [Install](#install) · [General Usage](#general-usage) · [Documentation](#documentation) · [Contributing](#contributing) · [License](#license) | ||
@@ -40,88 +42,2 @@ --- | ||
<a name="two-factor"></a> | ||
## Two-Factor Usage | ||
Let's say you have a user that wants to enable two-factor authentication, and you intend to do two-factor authentication using an app like Google Authenticator, Duo Security, Authy, etc. This is a three-step process: | ||
1. Generate a secret | ||
2. Show a QR code for the user to scan in | ||
3. Authenticate the token for the first time | ||
### Generating a key | ||
Use Speakeasy's key generator to get a key. | ||
```js | ||
let secret = speakeasy.generateSecret() | ||
// Returns an object with secret.ascii, secret.hex, and secret.base32. | ||
// Also returns secret.otpauth_url, which we'll use later. | ||
``` | ||
This will generate a secret key of length 32, which will be the secret key for the user. | ||
Now, we want to make sure that this secret works by validating the token that the user gets from it for the first time. In other words, we don't want to set this as the user's secret key just yet – we first want to verify their token for the first time. We need to persist the secret so that we can use it for token validation later. | ||
So, store one of the encodings for the secret, preferably `secret.base32`, somewhere temporary, since we'll use that in the future to authenticate the user's first token. | ||
```js | ||
// Example for storing the secret key somewhere (varies by implementation): | ||
user.two_factor_temp_secret = secret.base32 | ||
``` | ||
### Displaying a QR code | ||
Next, we'll want to display a QR code to the user so they can scan in the secret into their app. Google Authenticator and similar apps take in a QR code that holds a URL with the protocol `otpauth://`, which you get automatically from `secret.otpauth_url`. | ||
Use a QR code module to generate a QR code that stores the data in `secret.otpauth_url`, and then display the QR code to the user. This is one simple way to do it, which generates a PNG data URL which you can put into an `<img>` tag on a webpage: | ||
```js | ||
// Use the qrcode package | ||
// npm i qrcode | ||
const QRCode = require("qrcode") | ||
// Get the data URL of the authenticator URL | ||
QRCode.toDataURL(secret.otpauth_url, (err, data_url) => { | ||
console.log(data_url) | ||
// Display this data URL to the user in an <img> tag | ||
// Example: | ||
write('<img src="' + data_url + '">') | ||
}) | ||
``` | ||
Ask the user to scan this QR code into their authenticator app. | ||
### Verifying the token | ||
Finally, we want to make sure that the token on the server side and the token on the client side match. The best practice is to do a token check before fully enabling two-factor authenticaton for the user. This code applies to the first and subsequent token checks. | ||
After the user scans the QR code, ask the user to enter in the token that they see in their app. Then, verify it against the secret. | ||
```js | ||
// Let's say the user says that the token they have is 132890 | ||
let userToken = "132890" | ||
// Let's say we stored the user's temporary secret in a user object like above: | ||
// (This is specific to your implementation) | ||
let base32secret = user.two_factor_temp_secret | ||
``` | ||
```js | ||
// Use verify() to check the token against the secret | ||
let verified = speakeasy.totp.verify({ secret: base32secret, encoding: "base32", token: userToken }) | ||
``` | ||
`verified` will be true if the token is successfully verified, false if not. | ||
If successfully verified, you can now save the secret to the user's account and use the same process above whenever you need to use two-factor to authenticate the user, like during login. | ||
```js | ||
// Example for saving user's token (varies by implementation): | ||
user.two_factor_secret = user.two_factor_temp_secret | ||
user.two_factor_enabled = true | ||
``` | ||
Now you're done implementing two-factor authentication! | ||
<a name="general-usage"></a> | ||
@@ -132,3 +48,7 @@ | ||
```js | ||
//require | ||
const speakeasy = require("@levminer/speakeasy") | ||
//import | ||
import speakeasy from "@levminer/speakeasy" | ||
``` | ||
@@ -135,0 +55,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
628
81109
669