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

akamai-g2o

v2.0.0

Published

Connect/Express/Restify middleware implementing Akamai signature header authentication (G2O).

Downloads

8

Readme

Build Status

Akamai G2O for Node JS

G2O (Ghost to Origin, aka Signature Header Authentication) is an Akamai protocol that provides request authentication between Akamai caching proxies and the origin.

This library provides a simple middleware function that provides compliant G2O validation for applications. The following NodeJS server frameworks are supported:

  • vanilla NodeJS HTTP server
  • Express 4
  • Restify 4

How the protocol works

From the documentation:

This feature configures edge servers to include two special headers in requests to the origin server. One of these headers contains basic information about the specific request. The second header contains similar information encrypted with a shared secret. This allows the origin server to perform several levels of authentication to ensure that the request is coming directly from an edge server without tampering.

What this library does not support

The reference documentation specifies that the X-Akamai-G2O-Auth-Data header should be stored to prevent replay attacks. This is not supported (yet), because the library does not make assumptions about its environment and the storage engines that may be available. It does however provide a way of extending the validation mechanism. See the extraCheck option for more details.

How to use this library

First, install it:

npm install --save akamai-g2o

It is assumed that you are familiar with G2O concepts, which aren't covered in depth here.

This simple example sets up an application to use G2O with default parameters.

const app = require("express")();
const g2o = require("akamai-g2o");

app.use(g2o({
   key: {
    "nonce1": "s3cr3tk3y",
    "nonce2": "s3cr3tk3y2"
   }
}));

// ... setup routes and listen

Requests that fail authentication will result in a 403 response.

Requests that pass authentication will be extended with a g2o attribute with the following structure:

{
    data: {}, // see the Data object description section for details
    signature: "base64 encoded signature generated by the middleware",
    authenticated: true|false,
    message: "present only when authenticated is false"
}

See the options section for more advanced configuration.

Options

key

Mandatory; Object or Function.

When providing an Object, it should map nonces to keys (see the official G2O documentation for more information about nonces).

It is also possible to provide a Function for more flexibility. It should have the following signature:

function (req, data, callback)

req is the request object, typically an instance of http.IncomingMessage.

data is an Object representing the data in the dataString. It is described in more detail in the Data object description.

callback takes an Error or null as its first parameter and the key as its second.

strict

*** NO LONGER SUPPORTED ***

If you want to implement not strict logic see: onUnauthenticated.

dataHeader

Optional; String (default: "X-Akamai-G2O-Auth-Data")

By default, Ghost sends the request data in the X-Akamai-G2O-Auth-Data header. Setting this option instructs the middleware to retrieve a different header.

signHeader

Optional; String (default: "X-Akamai-G2O-Auth-Sign")

By default, Ghost sends the request signature in the X-Akamai-G2O-Auth-Sign header. Setting this option instructs the middleware to retrieve a different header.

signString

Optional; Function (default: req => req.url)

By default, Ghost signs the request URL as represented in the status line of the request (the URL path).

Ghost can be configured to use any part or combination of parts of the request, in which case you should provide a Function with the following signature:

function (req) => String

checkTime

Optional; Boolean (default: true)

If true, the request will fail if the request time is more than 30s distant from the current server time.

timeWindow

Optional; Number (default: 30)

Number of seconds before or after which the difference between the server and request times will trigger an authentication error when checkTime is true.

extraCheck

Optional; Function (default: null)

If provided, the function will be called after all checks have been completed. The signature should be:

function (req, callback)

An example implementation that prevents replay attacks might look like this:

var g2o = require("akamai-g2o");
var app = require("express")();

var previousAuthDataValues = {};

app.use(g2o({
   key: {
    "nonce1": "s3cr3tk3y",
    "nonce2": "s3cr3tk3y2"
   },
   extraCheck: function (req, callback) {
       if (req.g2o.data.raw in previousAuthDataValues) {
           callback(new Error("replayed request"));
       } else {
           callback();
       }
   }
}));

onUnauthenticated

Optional; Function (default:

function (req, res, next) {
    var statusCode = 403;
    if (typeof res.status === "function") {
        // Express has a status() helper function
        res.status(statusCode);
    } else {
        res.statusCode = statusCode;
    }
    res.end();
}

)

If provided, the function will be called after all checks have been completed and found to be unauthenticated. An unauthenticated g2o data will have a message property, that is the failure reason. The signature should be:

function (req, res, next)

An example implementation that:

  • logs out the failed request
  • uses a different status code
  • only fails request if strict
var g2o = require("akamai-g2o");
var app = require("express")();
var strict = true; // strict controlled outside, but maybe some config.

app.use(g2o({
   key: {
    "nonce1": "s3cr3tk3y",
    "nonce2": "s3cr3tk3y2",
   },
   onUnauthenticated: function (req, res, next) {
      var g2oResponse = Object.assign(
         {},
         {
            strict: strict,
            clientIp: req.ip, // for if there are no g2o header fallback to server known ip.
            forwardAddresses: req.forwardAddresses,
            uri: req.originalUrl, // note this is for express 4.0, else it is req.url
         },
         req.g2o
      );

      console.log('g2o unauthenticated', g2oResponse); // logging

      if (strict) { // only fail request if strict
         res.status(407).end(); // different status code
      } else {
         next();
      }
   }
}));

Data object description

Ghost is required to send a header containing authentication information which is used to generate the signature. This library parses the contents of the header and makes it available as an Object with the following structure:

{
    // the value of the raw header
    raw: "1, 1.2.3.4, 2.3.4.5, 123456789, 42314563, nonce1",
    // specifies the hashing function to use
    version: int(1..5),
    // edge server IP address
    edgeIp: String,
    // client IP address
    clientIp: String,
    // request time, as a Date object
    time: Date,
    // request unique identifier
    uniqueId: String,
    // nonce referencing the key to use
    nonce: String
}

Contributing

Don't break the unit tests, be as clean as you can, be nice.

npm run -s test