There is a common task that requires one to request challenges to be performed for a specific action. Imagine user, who wants to register for you service and you need to validate an email, or you want to issue an invitation and remove the burden of activation from a user, as well as supply extra meta information with that token. Furthermore, you often need to throttle specific requests and make sure they are not performed more than once in a certain time span. All of these tasks are easily handled by this module
npm i ms-token -S
Module API is pretty simple and contains only 4 functions alongside initialization.
When reading docs, keep in mind that anything in [] is an optional prop.
args.backend:name: supported backends include:redisconnection: appropriate connector,ioredisinstance forredisprefix: optional, used inredisbackend as key prefix
args.encrypt, used incrypto.createCipher(algorithm, password)when encoding long tokens:algorithm: one ofopenssl list-cipher-algorithms, example:aes192sharedSecret: The password is used to derive the cipher key and initialization vector (IV). The value must be either a 'binary' encoded string or a Buffer.
const TokenManager = require('ms-token');
const Redis = require('ioredis');
const tokenManager = new TokenManager({
backend: {
name: 'redis',
connection: new Redis(),
prefix: 'ms-token:',
},
encrypt: {
algorithm: 'aes256',
sharedSecret: Buffer.from('incredibly-long-secret-ooooohooo'),
},
});Use this to create challenge token, which should be sent to user for verification purposes.
Accepts:
args.action: unique action name, non-empty stringargs.id: unique request identification. For instance, if you are going to send this to an email, useemailas id. If this is going to be a token sent to the phone - use normalized phone number. Combination ofaction&idgrants access tosecret, whilesecretgrants access to all associated metadata[args.ttl]: token expiration, inseconds[args.throttle]:true: would be equal toargs.ttl, in that casettlmust be definedNumber: do not allow creating token forargs.{action,id}combo forNumberamount ofseconds. Sometimes you want throttle to be small (60 seconds), and ttl to be 15 mins (text messages), or 2 hours and 24 hours (emails)
[args.metadata]: Mixed content, must be able toJSON.stringifyit[args.secret]:true, default. in that case secret would be automatically generated and would include encrypted public data + generated secretfalse, do not generate secret. In that case it would simply useaction + idfor verification/unlockingObject:type: enumerable, acceptable values are:alphabet,number,uuid(defaultuuid)[alphabet]: string containing characters that are allowed to be used in the secret. Only used inalphabetmode[length]: length of generated secret, only used inalphabetandnumbermode[encrypt]: defaults totrueforuuid. Iftrue- then returned token includesaction,id& generatedsecretencrypted in it. That token alone is enough for verification function. Iffalse- it returns plain text generated secret, you must passaction,idandsecretto verification function in order for it to succeed
[args.regenerate]: defauls tofalse. If set totruewould allow usage of.regenerate()API by returninguidof this challenge
Returns Object:
id: id fromargsaction: action fromargs[uid]: token unique identificator, whenregenerateis true[secret]: send secret to user for completing challenge (for instance via SMS). Secret is not present if was set to false
Returns associated data for an already created token. It doesn't perform any verifications. This action should be considered a system action, which could be used for debugging purposes.
Input:
args, must have one ofuid,args.actionandargs.idcombo orargs.secret+args.encryptcomboargs.uid:Stringargs.action:Stringargs.id:Stringargs.secret:Stringargs.encrypt:Boolean-trueis secret must be encrypted,falseotherwise. Iffalsethenidandactionmust be supplied alongside secret
Response:
Object: associated metadata with a given input
Works with both uid OR action& id combo. Sometimes challenge token might not reach the user and the user would want to ask
for another challenge token. Idea of this is to accept public challenge uid, which would use previous data passed in .create(args)
and generate new secret based on this. Can only be used when regenerate was set to true on the .create(args) action
Input:
uid- uid from.create(args), whenregeneratewas set totrue
Response:
String: newly generated secret, either plain-text or encrypted based on what was passed earlier in.create(args)
Used for completing challenge by verifying user input.
Accepts:
argsasString, we would attempt to decode & verify in according with encryption settingsargsasObject:args.action- action from.create()args.id- id from.create()args.token- secret from.crete()return value
[opts]asObject:opts.erase: Defaults totrue. iftrue, when verification succeeds - associatedthrottleis removed, as well as any notion of this tokenopts.log: iftrue, logs attempt time.opts.control: verifies that decrypted args contains same valuesopts.id-> checks idopts.action-> checks action
Response, always Object in case of successful verification:
idactionuidsecretcreatedsettingsmetadataisFirstVerification- whether this was a first successful verificationverified- timestamp when it was verified
Otherwise rejects promise with an error
argsasString, we would attempt to decode & verify in according with encryption settingsargsasObject:args.uid- eitheruidORaction&idcombinationargs.action- action from.create()args.id- id from.create()