Token Orchestrator
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
Install me
npm i ms-token -S
API
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.
new TokenManager(args)
args.backend
:name
: supported backends include:redis
connection
: appropriate connector,ioredis
instance forredis
prefix
: optional, used inredis
backend as key prefix
args.encrypt
, used incrypto.createCipher(algorithm, password)
when encoding long tokens:algorithm
: one ofopenssl list-cipher-algorithms
, example:aes192
sharedSecret
: 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'),
},
});
tokenManager.create(args)
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, useemail
as id. If this is going to be a token sent to the phone - use normalized phone number. Combination ofaction
&id
grants access tosecret
, whilesecret
grants access to all associated metadata[args.ttl]
: token expiration, inseconds
[args.throttle]
:true
: would be equal toargs.ttl
, in that casettl
must be definedNumber
: do not allow creating token forargs.{action,id}
combo forNumber
amount 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.stringify
it[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 + id
for 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 inalphabet
mode[length]
: length of generated secret, only used inalphabet
andnumber
mode[encrypt]
: defaults totrue
foruuid
. Iftrue
- then returned token includesaction
,id
& generatedsecret
encrypted in it. That token alone is enough for verification function. Iffalse
- it returns plain text generated secret, you must passaction
,id
andsecret
to verification function in order for it to succeed
[args.regenerate]
: defauls tofalse
. If set totrue
would allow usage of.regenerate()
API by returninguid
of this challenge
Returns Object
:
id
: id fromargs
action
: action fromargs
[uid]
: token unique identificator, whenregenerate
is true[secret]
: send secret to user for completing challenge (for instance via SMS). Secret is not present if was set to false
tokenManager.info(args)
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.action
andargs.id
combo orargs.secret
+args.encrypt
comboargs.uid
:String
args.action
:String
args.id
:String
args.secret
:String
args.encrypt
:Boolean
-true
is secret must be encrypted,false
otherwise. Iffalse
thenid
andaction
must be supplied alongside secret
Response:
Object
: associated metadata with a given input
tokenManager.regenerate(uid)
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)
, whenregenerate
was set totrue
Response:
String
: newly generated secret, either plain-text or encrypted based on what was passed earlier in.create(args)
tokenManager.verify(args, [opts])
Used for completing challenge by verifying user input.
Accepts:
args
asString
, we would attempt to decode & verify in according with encryption settingsargs
asObject
: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 - associatedthrottle
is 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:
id
action
uid
secret
created
settings
metadata
isFirstVerification
- whether this was a first successful verificationverified
- timestamp when it was verified
Otherwise rejects promise with an error
tokenManager.remove(args)
args
asString
, we would attempt to decode & verify in according with encryption settingsargs
asObject
:args.uid
- eitheruid
ORaction
&id
combinationargs.action
- action from.create()
args.id
- id from.create()