Socket
Socket
Sign inDemoInstall

@sapphirecode/auth-server-helper

Package Overview
Dependencies
18
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    @sapphirecode/auth-server-helper

authentication middleware for node http and express


Version published
Weekly downloads
25
decreased by-3.85%
Maintainers
1
Created
Weekly downloads
 

Readme

Source

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.

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 timo@scode.ovh

Keywords

FAQs

Last updated on 09 Feb 2023

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc