Skip to content

Commit

Permalink
feat(): upgrade speakeasy to maintained version
Browse files Browse the repository at this point in the history
  • Loading branch information
semoal committed Apr 4, 2023
1 parent 0a01afb commit e50b643
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 117 deletions.
43 changes: 12 additions & 31 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"dependencies": {
"fastify-plugin": "^3.0.0",
"qrcode": "^1.4.4",
"speakeasy": "^2.0.0"
"@levminer/speakeasy": "^1.4.2"
},
"tap": {
"check-coverage": false
Expand Down
173 changes: 88 additions & 85 deletions totp.js
Original file line number Diff line number Diff line change
@@ -1,86 +1,89 @@
'use strict'

const fp = require('fastify-plugin')
const speakeasy = require('speakeasy')
const qrcode = require('qrcode')

const DEFAULT_TOTP_SECRET_LENGTH = 20
const DEFAULT_TOTP_LABEL = 'Fastify'
const DEFAULT_TOTP_WINDOW = 1
const DEFAULT_TOTP_ALG = 'sha512'
const DEFAULT_TOTP_STEP = 30

module.exports = fp(function (fastify, opts, next) {
const TOTP_SECRET_LENGHT = opts.secretLength || DEFAULT_TOTP_SECRET_LENGTH
const TOTP_LABEL = opts.totpLabel || DEFAULT_TOTP_LABEL
const TOTP_WINDOW = opts.totpWindow || DEFAULT_TOTP_WINDOW
const TOTP_ALG = opts.totpAlg || DEFAULT_TOTP_ALG
const TOTP_STEP = opts.totpStep || DEFAULT_TOTP_STEP

function generateTOTPSecret (length) {
const secret = speakeasy.generateSecret({
length: length || TOTP_SECRET_LENGHT
})
// WARNING: secret is NOT a string, but an object providing
// the secret key encoded in several ways (ascii, base32, etc.)
return secret
'use strict';

const fp = require('fastify-plugin');
const speakeasy = require('@levminer/speakeasy');
const qrcode = require('qrcode');

const DEFAULT_TOTP_SECRET_LENGTH = 20;
const DEFAULT_TOTP_LABEL = 'Fastify';
const DEFAULT_TOTP_WINDOW = 1;
const DEFAULT_TOTP_ALG = 'sha512';
const DEFAULT_TOTP_STEP = 30;

module.exports = fp(
function (fastify, opts, next) {
const TOTP_SECRET_LENGHT = opts.secretLength || DEFAULT_TOTP_SECRET_LENGTH;
const TOTP_LABEL = opts.totpLabel || DEFAULT_TOTP_LABEL;
const TOTP_WINDOW = opts.totpWindow || DEFAULT_TOTP_WINDOW;
const TOTP_ALG = opts.totpAlg || DEFAULT_TOTP_ALG;
const TOTP_STEP = opts.totpStep || DEFAULT_TOTP_STEP;

function generateTOTPSecret(length) {
const secret = speakeasy.generateSecret({
length: length || TOTP_SECRET_LENGHT,
});
// WARNING: secret is NOT a string, but an object providing
// the secret key encoded in several ways (ascii, base32, etc.)
return secret;
}

function generateTOTPToken(options = {}) {
if (!options.secret) return null;

const token = speakeasy.totp({
encoding: options.encoding || 'ascii',
algorithm: options.algorithm || TOTP_ALG,
step: options.step || TOTP_STEP,
...options,
});

return token;
}

function generateAuthURLFromSecret(options = {}) {
if (!options.secret) return null;

const url = speakeasy.otpauthURL({
label: options.label || TOTP_LABEL,
algorithm: options.algorithm || TOTP_ALG,
...options,
});

return url;
}

async function generateQRCodeFromSecret(secret, label, algorithm) {
const url = fastify.totp.generateAuthURL(secret, label, algorithm);

if (!url) return null;

return qrcode.toDataURL(url);
}

function verifyTOTP(options = {}) {
const result = speakeasy.totp.verifyDelta({
encoding: options.encoding || 'ascii',
window: options.window || TOTP_WINDOW,
step: options.step || TOTP_STEP,
...options,
});
return !!result;
}

fastify.decorate('totp', {
generateSecret: generateTOTPSecret,
generateToken: generateTOTPToken,
generateAuthURL: generateAuthURLFromSecret,
generateQRCode: generateQRCodeFromSecret,
verify: verifyTOTP,
});

fastify.decorateRequest('totpVerify', verifyTOTP);

next();
},
{
fastify: '>=2.x',
name: 'fastify-totp',
}

function generateTOTPToken (options = {}) {
if (!options.secret) return null

const token = speakeasy.totp({
encoding: options.encoding || 'ascii',
algorithm: options.algorithm || TOTP_ALG,
step: options.step || TOTP_STEP,
...options
})

return token
}

function generateAuthURLFromSecret (options = {}) {
if (!options.secret) return null

const url = speakeasy.otpauthURL({
label: options.label || TOTP_LABEL,
algorithm: options.algorithm || TOTP_ALG,
...options
})

return url
}

async function generateQRCodeFromSecret (secret, label, algorithm) {
const url = fastify.totp.generateAuthURL(secret, label, algorithm)

if (!url) return null

return qrcode.toDataURL(url)
}

function verifyTOTP (options = {}) {
const result = speakeasy.totp.verifyDelta({
encoding: options.encoding || 'ascii',
window: options.window || TOTP_WINDOW,
step: options.step || TOTP_STEP,
...options
})
return !!result
}

fastify.decorate('totp', {
generateSecret: generateTOTPSecret,
generateToken: generateTOTPToken,
generateAuthURL: generateAuthURLFromSecret,
generateQRCode: generateQRCodeFromSecret,
verify: verifyTOTP
})

fastify.decorateRequest('totpVerify', verifyTOTP)

next()
}, {
fastify: '>=2.x',
name: 'fastify-totp'
})
);

0 comments on commit e50b643

Please sign in to comment.