npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

paycheck

v0.1.2

Published

JSON payload authorization middleware

Downloads

23

Readme

PayCheck - a JSON payload authorization middleware

Lightweight, low footprint, compatible with any storage and server mechanism, allowing code reuse between frontend and backend.

How does it work

A backend API receives payloads. For example, an express server, websocket server or a worker that consumes a queue.

Different users and/or user roles or groups are authorized to send different types of payloads with different sets of parameters and values. You heard right - this isn't just about routes, it's also about authorizing resources.

As part of the login process, PayCheck can be invoked to generate a JSON object containing templates of expected payloads and the associated routes or JSON RPC methods. This can be stored by the invoking application, for example in a signed JSON Web Token, or redis.

For subsequent requests, PayCheck can be invoked to check the incoming payload against the templates generated earlier. PayCheck either rejects or accepts the payload based on if the template can be matched.

How do the JSON payload templates get specified in the first place?

Payload templates

Payload templates are compiled from 'templates', 'substitutions' and 'contexts' that are all associated with the user who is logging in. Basic templates can be created automatically by PayCheck via the 'listening' mode. After this, specific features can be edited manually.
Templates, substitution and contexts can be stored and retrieved using any kind of datastore. Dynamic substitutions that run code are hard coded by the app.

Simple templates have no variables, only fixed values and wildcards:

{
    myresource: ["a", "b", "c"]       // this means any of these values are accepted
    canBeAnything: "<%= * %>" // this is a wildcard, any value is allowed
}

This would allow the user associated with this template to access resources named "a", "b" and "c". For example the following payloads would be accepted:

{
    myresource: ["b"]
    // canBeAnything is undefined, and that's ok because it can be anything
}

or:

{
    myresource: ["c", "a"]
    canBeAnything: {"a" : "b"}
}

However, resources like this will probably be used again within multiple templates. Hence we support variables within templates:

{
    myresource: "<%= allowed_resources %>",
    myOtherResource: "foo"
}

and:

{
    myresource: "<%= allowed_resources %>",
    myOtherResource: "bar"
}

Templates defined like this require substitutions to be defined:

{
    allowed_resources: ["a", "b", "c"]
}

However, often the situation might require that the resources in the substitution are automatically kept up to date. To solve this, they can be derived by using a query at the point where the JSON payload templates are compiled, IE in the login step.

For example, the template could be:

{
    myresource: "<%= allowed_resources %>",
    myOtherResource: "bar"  //this must match exactly
}

The substitution would be defined in code by the application, eg:

{
    allowed_resources: function () {
        return myDataStore.getDataAndReturnPromise(this.myDataQueryQualifier) 
    }
}

And the context may need to also be provided:

{
    myDataQueryQualifier: "qualifierForCurrentUserOrRole"
}

At the point of login, PayCheck takes a set of templates, substitutions and contexts, and publishes payload templates, which are free from any variables or functions.

Code examples

Compiling payload templates via login step

var paycheck = new (require('../paycheck.js'))({})
paycheck.compile(templates, substitutions, contexts)
.then((payloadTemplates) => {
    storeInJWT(payloadTemplates)
}).catch((err) => {

});

Checking payloads

var paycheck = new (require('../paycheck.js'))({})

function receivePayloads(payload, next) {
    extractJWT(payload)
    .then((payloadTemplates) => {
        var checkedPayload = paycheck.check(payload, payloadTemplates)
        next(checkedPayload)
    }).catch(PayloadDenied, (err) => {
        // payload doesn't match templates
    }).catch((err) => {
        // other errors, eg JWT invalid
    })
}

Listening for payloads, converting them into payload templates.

var paycheck = new (require('../paycheck.js'))({})

paycheck.listenStart()

function receivePayloads(payload, next) {
    
    paycheck.observe(
        payload
    )
    
}

function finish() {
    var resultingTemplates = paycheck.observed; 
    paycheck.listenStop()   
    paycheck.observed = {};
    myDataStore.save(resultingTemplates) // TODO: these need to be converted into an array of payload templates for easier storage
}