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 🙏

© 2026 – Pkg Stats / Ryan Hefner

draco-auth

v1.0.11

Published

A middleware package to handle authentication and security via a Draco server

Downloads

194

Readme

draco-auth

draco-auth is an Express middleware that seamlessly integrates your application with the Draco authentication and security system. It handles session management, user information injection, permission checks, and provides utility functions for authentication flows.

Features

  • Draco Server Integration: Connects to a Draco server via REST API using an API key.
  • Session Management: Manages user sessions and cookie handling (req.draco).
  • User Injection: Injects user information into req.draco.user and res.locals.user.
  • Authentication Utilities: Provides loginURL and logoutURL functions on req and res.locals.
  • Middleware for Access Control:
    • NeedsAuthentication: Ensures routes are accessed by authenticated users.
    • NeedsPermission: Ensures routes are accessed by users with specific permissions.
    • NeedsOnePermissionOf: Ensures routes are accessed by users with one of the provided permissions.
  • Event Logging: Allows logging of custom events to the Draco server via req.logEvent.
  • Permission Checking: Facilitates checking user permissions with req.hasPermission or req.hasOnePermissionOf.

Installation

Install the package using NPM:

> npm install --save draco-auth

Usage

Prerequisites

Before using draco-auth, ensure the following are set up on the main Draco server:

  • Users: Create users on the Draco server.
  • Applets: Create applets on the Draco server and generate an API key for each applet.
  • Permissions: Assign permissions for the applet to the necessary users on the Draco server.

Configuration

draco-auth requires the Draco server's host and API key to function. These must be provided via environment variables.

The simplest way to set this up is by using a .env file.

  1. Set Up Environment Variables

    Create a .env file in your project root (if you haven't already) and add your Draco host and API key:

    DRACO_HOST=https://DRACO_URL_HERE
    DRACO_API_KEY=your_draco_api_key_here

    Ensure you load environment variables in your application (commonly done using the dotenv package):

    require('dotenv').config();

Integrating draco-auth with Express

Using TypeScript (Recommended)

  1. Define Permissions

    Create a permissions.ts file (or any suitable file) and define your permissions using an enum:

    export enum Permissions {
      PERMISSION_1 = 'permission_1',
      PERMISSION_2 = 'permission_2',
    }
  2. Set Up Express with draco-auth

    In your main Express application file (e.g., index.ts):

    import express from 'express';
    import dracoAuth, { NeedsAuthentication, NeedsPermission, NeedsOnePermissionOf } > from 'draco-auth';
    import { Permissions } from './permissions'; // Adjust the import path as necessary
    import dotenv from 'dotenv';
    
    dotenv.config(); // Load environment variables
    
    const app = express();
    
    // Express setup
    app.set('view engine', 'pug'); // Example setup
    app.use(express.static('public'));
    
    // Integrate draco-auth middleware
    app.use(dracoAuth({
      permissions: Object.values(Permissions)
    }));
    
    // Define routes
    app.get('/', (req, res) => {
      res.send('This is an unprotected route');
    })
    
    app.get('/protected', NeedsAuthentication, (req, res) => {
      res.send('This is a protected route.');
    });
    
    app.get('/privileged', NeedsOnePermissionOf([Permissions.Manager, Permissions.> Admin]), (req, res) => {
      res.send('Privileged page.');
    });
    
    app.get('/admin', NeedsPermission(Permissions.Admin), (req, res) => {
      res.send('Admin dashboard.');
    });
    
    app.listen(3000, () => {
      console.log('⚡ Server is running on port 3000');
    });

Using JavaScript

  1. Set Up Express with draco-auth

    In your main Express application file (e.g., index.js):

    const express = require('express');
    const dracoAuth = require('draco-auth');
    const dotenv = require('dotenv');
    
    dotenv.config(); // Load environment variables
    
    const app = express();
    
    // Express setup
    app.set('view engine', 'pug'); // Example setup
    app.use(express.static('public'));
    
    // Integrate draco-auth middleware
    app.use(dracoAuth.default({
      permissions: [
        'admin',
        'manager',
        'permission_1',
        'permission_2',
        // Add more permissions as needed
      ]
    }));
    
    // Define routes
    app.get('/', (req, res) => {
      res.send('This is an unprotected route.');
    });
    
    app.get('/protected', dracoAuth.NeedsAuthentication, (req, res) => {
      res.send('This is a protected route.');
    });
    
    app.get('/privileged', dracoAuth.NeedsOnePermissionOf(['manager', 'admin']), (req, > res) => {
      res.send('Privileged page.');
    });
    
    app.get('/admin', dracoAuth.NeedsPermission('admin'), (req, res) => {
      res.send('Admin dashboard.');
    });
    
    app.listen(3000, () => {
      console.log('Server is running on port 3000');
    });

API Reference

Middleware Functions

  • dracoAuth(options)

    Initializes the draco-auth middleware.

    Options:

    • permissions: string[]
      An array of permission strings that can be assigned to users.
  • NeedsAuthentication
    Middleware to ensure that a user is authenticated. If not, redirects them to the Draco login screen.

    Usage:

    app.get('/secure', NeedsAuthentication, (req, res) => {
      res.send('Secure Content');
    });
  • NeedsPermission(permission: string, redirect?: string)
    Middleware to ensure that a user is authenticated and possesses a specific permission. If the user lacks the required permission, they are redirected to the specified URL (defaults to /).

    Parameters:

    • permission: string
      The permission required to access the route.
    • redirect?: string
      Optional. The URL to redirect unauthorized users to.

    Usage:

    app.get('/admin', NeedsPermission('admin'), (req, res) => {
      res.send('Admin Content');
    });
  • NeedsOnePermissionOf(permissions: string[], redirect?: string)
    Middleware to ensure that a user is authenticated and possesses at least one permission from the provided array. If the user lacks all the required permission, they are redirected to the specified URL (defaults to /).

    Parameters:

    • permissions: string[] The permissions which are allowed to access the route.
    • redirect?: string
      Optional. The URL to redirect unauthorized users to.

    Usage:

    app.get('/admin', NeedsOnePermissionOf(['admin', 'manager']), (req, res) => {
      res.send('Privileged Content');
    });

Request Object Extensions

The middleware augments the Express req and res objects with additional properties and functions:

  • req.draco
    An object representing the user's session.

  • req.draco.user
    The authenticated user's information, adhering to the following interface:

    interface User {
      name: string;
      surname: string;
      email: string;
      image_path?: string;
      permissions: string[];
    }
  • res.locals.user
    Same as req.draco.user, available for use in front-end templates.

  • req.loginURL(redirect_url: string): string
    Generates a URL that redirects the user to the Draco login screen. After successful login, the user is redirected to redirect_url.

    Usage:

    const loginLink = req.loginURL('/dashboard');

    Available in res.locals.loginURL for use in templates.

  • req.logoutURL(redirect_url: string): string
    Generates a URL that logs the user out by destroying their session and clears local permissions. After logout, the user is redirected to redirect_url.

    Usage:

    const logoutLink = req.logoutURL('/goodbye');

    Available in res.locals.logoutURL for use in templates.

  • req.logEvent(event: string, additional_information?: string): void
    Sends an event to the Draco server for logging. Requires the user to be authenticated.

    Parameters:

    • event: string
      The name of the event (e.g., 'item_deleted').
    • additional_information?: string
      Optional. Additional details about the event.

    Usage:

    req.logEvent('item_deleted', 'Deleted item with ID 123');
  • req.hasPermission(permission: string): boolean
    Checks if the authenticated user has a specific permission.

    Parameters:

    • permission: string
      The permission to check.

    Usage:

    if (req.hasPermission('delete_entries')) {
      // Perform delete operation
    }

    Available in res.locals.can for use in templates. Usage:

    - if (can('delete_entries'))
      // Show delete button
  • req.hasOnePermissionOf(permissions: ...string[]): boolean
    Checks whether the authenticated user has one of the specified permission.

    Parameters:

    • permissions: ...string[]
      The permissions to check.

    Usage:

    if (req.hasOnePermissionOf('delete_entries', 'admin')) {
      // Perform delete operation
    }

    Available in res.locals.can for use in templates. Usage:

    - if (can('delete_entries'))
      // Show delete button
  • res.locals.loginURL
    Same as req.loginURL, available for use in front-end templates.

  • res.locals.logoutURL
    Same as req.logoutURL, available for use in front-end templates.

  • res.locals.user
    The authenticated user's information, available for use in front-end templates.

Additional Information

  • Public Hosting: While draco-auth is intended for private use, it is hosted publicly on NPM for ease of deployment. Ensure that sensitive information, such as API keys, is securely managed.
  • Caching: User information and permissions are cached for 1 minute on the applet. Any changes made on the Draco server may take up to a minute to reflect in the application.

Example

Here's a concise example combining the above concepts in a TypeScript Express application:

import express from 'express';
import dracoAuth, { NeedsAuthentication, NeedsPermission } from 'draco-auth';
import { Permissions } from './permissions';
import dotenv from 'dotenv';

dotenv.config();

const app = express();

app.set('view engine', 'pug');
app.use(express.static('public'));

app.use(dracoAuth({
  permissions: Object.values(Permissions)
}));

app.get('/', NeedsAuthentication, (req, res) => {
  res.render('home');
});

app.get('/dashboard', NeedsAuthentication, (req, res) => {
  res.render('dashboard');
});

app.get('/admin', NeedsPermission('admin'), (req, res) => {
  res.render('admin');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

In your Pug templates, you can access the user, loginURL, and logoutURL via res.locals:

//- home.pug
- if(user)
  h1 Welcome, #{ user.name }!
  a(href=logoutURL('/goodbye')) Logout
- else
  a(href=loginURL('/dashboard')) Login

Development

Building

Before making changes to draco-auth, ensure the following steps have been done:

  • Clone: Clone this repository.
  • Build: Run npm run build to generate the dist folder in the repo directory.
  • Test app: Set up a test application (or clone draco-test if you have access to the company Bitbucket).

Troubleshooting

Problem. Strange Redirects after Login

After being redirected to Draco to sign in to an applet, if you are sent to an unfamiliar URL instead of back to the applet, it is likely an issue with the request headers.

If you are using nginx or another reverse-proxy, ensure you are setting the following header after the proxy pass:

proxy_set_header X-Forwarded-For $remote_addr;

Made with ❤️ using TypeScript and coffee.