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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sapphirecode/auth-server-helper

v4.1.1

Published

authentication middleware for node http and express

Downloads

53

Readme

auth-server-helper

version: 4.1.x

customizable and simple authentication

Installation

npm:

npm i --save auth-server-helper

yarn:

yarn add auth-server-helper

Usage

1. put a gateway in front of the routes you want to secure

const {create_gateway} = require('@sapphirecode/auth-server-helper');

const gateway = create_gateway({
  redirect_url: '/auth', // if defined, unauthorized requests will be redirected
  cookie: { name: 'auth_cookie' }, // if defined, access tokens will be read from or written to this cookie,
  refresh_cookie: { name: 'refresh_cookie' }, // if defined, refresh tokens will be read and used to automatically refresh client tokens (requires the refresh_settings attribute)
  refresh_settings: {
    // same as settings for allow_access under section 2
    // the options data, redirect_to and leave_open are not supported here
  }
});

// express
app.use(gateway);

// node http
http.createServer((main_req, main_res) =>
  gateway(main_req, main_res, (req, res) => {
    // your request handler
  });
);

the gateway will forward any authorized requests to the next handler and redirect all others to the specified url

1.1. Creating a gateway for manual processing of requests

const {GatewayClass} = require('@sapphirecode/auth-server-helper');

const gateway = new GatewayClass({ /* options */ }); // options are the same as for create_gateway above

// process a request
if (gateway.authenticate(http_request)) { // returns true if request is valid and sets req.connection.token_id and .token_data
  console.log('access granted');
} else {
  gateway.redirect(response); // redirects the client, triggers deny if no redirect_url was set in options
  // or
  gateway.deny(response); // sends status 403
}

2. creating the auth endpoint

const {create_auth_handler} = require('@sapphirecode/auth-server-helper');

const handler = create_auth_handler(
  async (req) => {
    if (req.user === 'foo' && req.password === 'bar')
      const {access_token_id, refresh_token_id} = await req.allow_access({
        access_token_expires_in: 600, // seconds until access tokens expire
        include_refresh_token: true, // should the answer include a refresh token? default: false
        refresh_token_expires_in: 3600, // seconds until refresh tokens expire (required if refresh tokens are generated)
        data: {user: 'foo'}, // additional custom data to include in the token
      });

    if (req.user === 'part' && req.password === 'baz')
      const part_id = await req.allow_part(
        60, // seconds until part_token expires
        'some_module', // next module handler (defined below)
        {foo: 'bar'} // custom data to attach to the token
      );

    // all allow_ functions return a token id, which can later be used to invalidate specific tokens from the server side

    req.deny();
  },
  {
    refresh: {
      /*...same options as allow_access */
    }, // define the behaviour of refresh tokens. Refresh tokens will not be accepted if this option is undefined
    modules: {
      some_module(req) {
        // request handlers for part_tokens

        // access custom data:
        const auth_data = req.request.connection.auth;
        auth_data.token_id; // token id
        auth_data.token_data; // custom data
        // the same works in handlers after the gateway, information is always stored in request.connection.auth
      },
    },
    cookie: { name: 'auth_cookie' }, // if defined, access tokens will be stored in this cookie,
    refresh_cookie: { name: 'refresh_cookie' }, // if defined, refresh tokens will be stored in this cookie
    parse_body: true // read the request body into a string (default false)
  }
);

// express
app.use(handler);

// node http
// ... create server, on path /auth run the handler
handler(req, res); // the handler will also return true if allow_access or allow_part was called

after the auth handler, the request will be completed, no additional content should be served here. (Read 2.1 for info on disabling this)

2.1. Processing Auth Requests without closing the response object

to prevent the auth handler from closing the response object you can provide additional options on each of the allow/deny functions.

allow_access({leave_open: true, ...});
allow_part(
  60,
  'some_module',
  {foo: 'bar'},
  true // additional flag to leave request open
);
invalid('error description', true);
deny(true);

if this flag is set, no data will be written to the response body and no data will be sent. Status code and Headers will still be set.

Defining Custom Cookie Settings

By default all cookies will be sent with 'Secure; HttpOnly; SameSite=Strict' Attributes

In the appropriate settings object, you can set the following options:

{
  name: 'foo', // name of the cookies
  secure: true, // option to enable or disable the Secure option default: true
  http_only: true, // option to enable or disable HttpOnly default: true
  same_site: 'Strict', // SameSite property (Strict, Lax or None) default: 'Strict'. Set this to null to disable
  expires: 'Mon, 10 Jan 2022 09:28:00 GMT', // Expiry date of the cookie
  max_age: 600, // Maximum age in Seconds
  domain: 'example.com', // Domain property
  path: '/cookies_here' // Path property
}

For Documentation on the different Cookie Attributes see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#creating_cookies

Invalidating tokens after they are delivered to the client

const {blacklist} = require('@sapphirecode/auth-server-helper');

await blacklist.add_signature(token_id); // the token id is returned from any function that creates tokens

Logout function

const {GatewayClass} = require('@sapphirecode/auth-server-helper');

const gateway = new GatewayClass({ /* options */ });

// create a new express route
app.get('logout', (req, res) => {
  // call the gateway's logout function
  gateway.logout(req);

  // respond ok
  res.status(200);
  res.end();
});

Exporting and importing public keys to validate tokens across server instances

const {keystore} = require('@sapphirecode/auth-server-helper');

const export = keystore.export_verification_data();

// second instance

keystore.import_verification_data(export);

These keys can also be live synchronized with redis to allow sessions to be shared between servers

const {keystore} = require('@sapphirecode/auth-server-helper');

keystore.sync_redis('redis://localhost');

Exporting and importing blacklist entries across server instances

const {blacklist} = require('@sapphirecode/auth-server-helper');

const export = blacklist.export_blacklist();

// second instance

blacklist.import_blacklist(export);

Clearing Keystore and Blacklist

Resetting the Keystore instance generates a new instance id and deletes all imported or generated keys.

const {keystore, blacklist} = require('@sapphirecode/auth-server-helper');

// clear keystore
keystore.reset_instance();

// clear blacklist
await blacklist.clear();

// clear blacklist items older than 10 seconds
await blacklist.clear(Date.now() - 10000);

Setting and checking permissions

When allowing access to a client a list of permissions can be added. Permissions are case sensitive.

allow_access({permissions: ['foo','bar'], ...})

The gateway can be told to check those permissions before forwarding a request.

const gateway = new GatewayClass({
  require_permissions: ['foo'], // Only clients with the 'foo' permission will be granted access
});

additional checks can be run later

(req, res) => {
  const has_both = gateway.check_permissions(req, ['foo', 'bar']); // returns true if both permissions are set
  const has_bar = gateway.has_permission(req, 'bar'); // returns true if permission 'bar' is set
};

Reading connection info

Data like the used token id, custom data and permissions can be read from req.connection.auth or using the function gateway.get_info(req)

const info = gateway.get_info(req);

console.log(info);

/*
{
  token_id: 'foo',
  data: {}, // custom data
  permissions: ['foo','bar']
}
*/

License

MIT © Timo Hocker [email protected]