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

service2service

v2.2.0

Published

A node module to make service to service communication secure and easy

Downloads

1,141

Readme

service2service

A node module to make service to service communication secure and easy.

Sometimes you have a service that needs to talk to another service, but you don't have the context of a user with which to authenticate with. This module aims to make authentication easy, given that both of your services share a secret.

Installation

npm install --save service2service

Usage

import ServiceAgent from 'service2service'

const agent = new ServiceAgent({
  secret: 'super secret',
  expire: 60, // 1 minute
  header: 'Authorization',
  tokenPrefix: 'Bearer '
})

agent.generate()
  .then((token) => {
    // token that is only valid for 1 minute
    return agent.verify(token)
  })
  .then((payload) => {
    // token is verified, error gets thrown if not verified
  })

// This is an instance of request promise that will automatically add the
// header to every request. This takes care of the `generate` functionality for
// you.

// Note that this is just a wrapper around request promise because we have to
// handle the case of asynchronous secret getting. If you wish to use the raw
// request object, implement the `generate()` method into your workflow
agent
  .request({
    uri: 'http://www.example.com',
    method: 'POST'
    body: {
      some: 'payload'
    },
    resolveWithFullResponse: true,
    json: true
  })
  .then(({ body, statusCode }) => {
    // Successful request!
  })

Consuming a ServiceAgent token

The middleware described below take care of the verify functionality.

Express

import express from 'express'
import service2service from 'service2service/express'

const app = express()

app.get('/only-services-allowed', [
  service2service({
    secret: 'super secret',
    header: 'X-Service-Token'
  }),
  (req, res, next) => {
    // If we made it to this middleware, we can assume that the request came
    // across with a valid token
    res.send('success')
  }
])

Koa

import koa from 'koa'
import service2service from 'service2service/koa'

const app = koa()

app.use(service2service({
  secret: 'super secret',
  header: 'X-Service-Token'
}))

app.use(function *() {
  // If we made it to this middleware, we can assume that the request came
  // across with a valid token
  this.body = 'success'
})

API Documentation

new ServiceAgent(options)

Returns a new "secret service agent"

  • options.secret {(string|string[]|Function)} - The shared secret that both the client and the server should know about. If a function is passed, it can return the value of the secret, or return a promise that resolves to the secret. This should work if you pass in an async function. In the .generate function, it will use the first secret in the array if an array of secrets is passed. .verify will try all of them in turn until one passes validation

    const agent = new ServiceAgent({
      secret: [
        'super secret',
        'super secret2'
      ],
      expire: 60, // 1 minute
      header: 'Authorization'
    })

    Default: null - Note that this is a required option. You must have at least 1 secret or this will throw an error on verification. This is a breaking change as of version 2.x.

  • options.expire - {number} - The number of seconds that the token is valid for. This should be something low, like 1 minute (60).

    Default: 60

  • options.header {string} - The header that will contain the token.

    Default Authorization

  • options.tokenPrefix {string} - The prefix to prepend to the token when the token is sent in a request. This will also be used to strip out the prefix upon verification. If a token is sent without a prefix, it will still verify.

    Default: Bearer (yes, that's a space at the end)

  • options.disableSingleUse {boolean} - By default, service2service will only allow unique tokens. It does this by harboring a cache of used tokens (it cleans up after itself). Setting this to true will disable this caching and checking behavior.

    Default: false

agent.generate([options [, payload]])

Returns a promise that resolves to a generated token, or throws if your secret function generator throws an error.

Note: You shouldn't need to use this directly because agent.request takes care of this for you, but you may need it if you would like to implement it into your own request library.

You can pass options in here that get passed into jwt.sign as the options. Below are ones you should consider using:

  • options.audience {string} - Who the token is intended for
  • options.subject {string} - A description of the action to take place
  • options.issuer {string} - Who is issued the token
  • payload {object} - The payload of the token

Those options may be used on the consuming end to verify a token.

agent.verify(token[, options])

Returns a promise that resolves to the payload of the token. The secret parameter is optional and is only used if you want to override the agent's 'secret' option. The options are the same options in jwt.sign

agent.request(reqOptions[, genOptions [, payload])

This is wrapper around request-promise. It accepts all the same options. Note that this is just a wrapper function and does not provide the sugar methods like request.post() or request.get().

  • reqOptions {Object} - The options you pass into request. You can see all of the available options here
  • genOptions {Object} - The options that get passed into agent.generate()
  • payload {Object} - The payload that gets passed into agent.generate()

middleware

The api for express middleware and koa middleware is the same. It accepts all of the same options as the ServiceAgent constructor, or you may pass in a ServiceAgent instance.

import ServiceAgent from 'service2service'
import expressMiddleware from 'service2service/express'
import koaMiddleware from 'service2service/koa'

const agent = new ServiceAgent({
  secret: 'super secret',
  expire: 60000,
  header: 'X-Service-Token'
})

expressMiddleware(agent)
koaMiddleware(agent)

middleware(agentOptions[, verifyOptions])

  • agentOptions {Object} - The options passed into a service agent constructor
  • verifyOptions {Object} - The options passed into agent.verify(token, options)