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

btrz-auth-api-key

v5.7.0

Published

Betterez api authorization library

Downloads

1,098

Readme

btrz-auth-api-key

This module handles api authentication using an x-api-key parameter, it uses passport with the passport-localapikey strategy. It will accept the parameter in the Header, QS or BODY. The KEY is case sensitive. You can configure the KEY using the authKeyFields options, see below.

Runtimes supported

io.js >= 1.0.3 node >= v0.11.x with the --harmony flag

Slush

If you are using the Slush generator for slush-btrz-service this package will be included and configured by default.

Manual installation and configuration

When creating a new API service you should include this module.

npm install btrz-auth-api-key --save

On your index.js file when creating your application service, hook this package into the middleware:

const Logger = require("btrz-logger").Logger,
  logger = new Logger(),
  Authenticator = require("btrz-auth-api-key").Authenticator,
  options = {
    db: {
      "options": {
          "database": "betterez_core",
          "username": "",
          "password": ""
      },
      "uris": [
        "127.0.0.1:27017"
      ]
    }, 
    collection: "apikeys",
    internalAuthTokenSigningSecrets: {
      main: "TnrRb2IadihO"
      secondary: "HuFDeLoriVp3"
    }
  };

const auth = new Authenticator(options, logger);

app = express();
app.use(auth.initialize());
app.use(auth.authenticate());

auth.initialize()

This method is the same as calling passport.initialize() if you pass an options object it will be used internally when calling passport.initialize().

For example if you want to rename the user property of the request object (where passport will store the authenticated user), you would do this:

auth.initialize({userProperty: "principal"});

After authentication you can just do:

var loggedUser = req.principal;

Options object

The options object for the Authenticator should have the following structure.

Notice that this is a different options object than the one passed to passport.

testKey: "a-key-to-use-during-testing",
testUser: {_id: "fake-id"},
ignoredRoutes: ["/api-docs"],
authKeyFields: {
    header: "X-API-KEY",
    request: "x_api_key"
},
collection: {
    name: "collection_name",
    property: "property_name"
    },
db {
    options:
        database: "database_name",
        username: "username",
        password: "user_password",
    },
    uris: [
        "address:port"
    ]
},
internalAuthTokenSigningSecrets: {
    main: "<some_secret_string>"
    secondary: "<some_other_secret_string>"
}

testKey

This is a key that can be set to use when Unit Testing your services. Using this key avoids the need to setup a key on a test db.

testUser

This is an object with any schema. If testKey is present and testUser is present it will be returned as the authenticated user in req.user. Use this for testing.

ignoredRoutes

An array of strings containing a regular expression to match part of the whole or route. Use this to expose an end point or group of endpoints to the world without the need of an X-API-KEY. Try to make your regexp as restrictive as possible to avoid exposing endpoints by mistake.

Ex:

^/api-docs //will match /api-docs, /api-docs/pets, etc.
^/api-docs$ //will match /api-docs and will not match /api-docs/

To ignore only certain HTTP methods on a route, use this syntax:

{route: "^/api-docs$", methods: ["POST", "PUT"]}

authKeyFields

An object containing the possible keys to look for in the HEADERS or in the request.

The request key will be mapped to a query string or body parameter. If no options is passed the HEADER will default to X-API-KEY and the request will default to x_api_key

db

The db options and uris array will be used to connect to the MongoDb (single server or cluster) to check for the apikey.

The collection.name and collection.property will be used to try to find one record that contains the value provided on X-API-KEY to the service.

internalAuthTokenSigningSecrets

The secret keys that are used to sign the auth tokens used for internal service-to-service calls. Two keys are provided, to allow for key rotation.

auth.tokenSecuredForInternal

This middleware, when used on a route definition, validates the request includes a Bearer Token that is a valid JSON Web Token as issued by an internal Betterez service (not necessarily btrz-api-accounts). This validates that the incoming request is the result of a service-to-service call.

Usage:

app.get("/secured", auth.tokenSecuredForInternal, function (req, res) {
    ...
});

auth.tokenSecuredForAudiences

This middleware, when used on a route definition, validates the request includes a Bearer Token that is a valid JSON Web Token as issued by the authorization endpoint on btrz-api-accounts. The token will be validated as usual, and will be valid if it is issued for at least one of the audiences listed.

In this example, the route will be valid for customers or backoffice users:

app.get("/secured", auth.tokenSecuredForAudiences(["betterez-app", "customer"]), function (req, res) {
    ...
});

req.tokens, req.application, req.user & req.customer

Once passport login is completed the request object is enhanced with three properties for later usage:

  1. req.tokens: { token, jwtToken } the x-api-key and the jsonwebtoken, respectivelly. If any of the values is missing it will get null assigned.
  2. req.application the application record associated to the x-api-key received.
  3. req.user the user from the jwtToken, either the internal account impersonation or the actual login user.
  4. req.customer if the audience for the user on the jwtToken is equal customer.

Authenticating Internal service-to-service calls

The authentication middleware supports secure calls between services using a special "internal" JWT token. This is useful in cases where one services needs to access a secure endpoint belonging to another service, and you do not have a JWT token provided by the user.

The service performing the internal request will generate an "internal" JWT token using the InternalAuthTokenProvider class provided by this module. You must supply a "main" secret signing key to the InternalAuthTokenProvider; this will be used to sign the generated JWT token. This signing key is a secret, and it should never be committed to the codebase: fetch the value at runtime.

When a service receives a request with an authorization token, the authentication middleware will look at the token issuer to determine whether it is a user-provided or internal token. If an internal token is detected, the authentication middleware will attempt to verify the token signature using both the "main" and "secondary" secret signing keys. If the token signature is verified, the authentication middleware will fetch user information using the API key provided in the request's x-api-key header, and populate the req.user object for downstream code to use.

For security reasons, internal authentication tokens are short-lived, and expire soon after they are created. The InternalAuthTokenProvider regenerates the internal auth token periodically, and you should always ask it for a new token every time you make a service-to-service request.

Key rotation

Key rotation can be performed as follows:

  1. Change the value of the secondary signing key to some new random string (ie. using pwgen -s 64 1)
  2. Propagate this configuration change to all services (restart if required)
  3. Wait at least a number of minutes equal to the token expiration time
  4. Swap the value of the main and secondary signing keys
  5. Propagate this configuration change to all services (restart if required).
  6. Wait at least a number of minutes equal to the token expiration time. After this period, all valid internal tokens are guaranteed to be signed using the new signing key.
  7. Change the value of the secondary signing key to some new random string
  8. Propagate this configuration change to all services (restart if required)

At the end of this process, both the main and secondary signing keys have been changed, and there should have been no interruption of service. Tokens that were signed using either one of the old signing keys will no longer be accepted by the authentication middleware.