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

embassy

v2.0.4

Published

Simple JSON Web Tokens (JWT) with embedded scopes for services

Downloads

117

Readme

Install

npm install --save embassy

or

yarn add embassy

Initialize

import { Embassy } from 'embassy'

const embassy = new Embassy({
  domainScopes: {
    users: {
      readEmail: 0,
      readProfile: 1,
      writeProfile: 2
    },
    store: {
      readPurchaseHistory: 0,
      addToCart: 1,
      submitOrder: 2,
      cancelOrder: 3
    }
  },
  keys: {
    myKey: {
      privateKey: 'shared-secret',
      algorithm: 'HS512'
    }
  },
  issuer: 'api.myapp.com/auth',
  audience: 'api.myapp.com'
})

Embassy can be configured to find public and private keys when an unknown key ID is found, and refresh the scopes when an unknown scope is encountered. Always run smoothly without forced restarts or configuration updates. See the options »

Integrate

Create and sign access tokens

const token = embassy.createToken({
  sub: 'userid',
  email: '[email protected]'
})
const tokenString = await token.sign('myKey')
// Token expires in an hour by default

embassy.createToken docstoken.sign docs

Verify access tokens

const token = embassy.parseToken(bearerToken)
const claims = await token.verify() // Throws if invalid, expired, etc
console.log(`New request from ${claims.email}`)

embassy.parseToken docstoken.verify docs

Create and sign refresh tokens

const token = embassy.createToken({
  sub: 'userid',
  email: '[email protected]'
})
const tokenString = await token.sign('myKey', {
  audience: 'api.myapp.com/auth', // Prevent this from being used as an access token
  expiresInSecs: 3600 * 24 * 365 // Make it last for a year
})

embassy.createToken docstoken.sign docs

Verify refresh tokens

const token = embassy.parseToken(bearerToken)
const claims = await token.verify({
  audience: 'api.myapp.com/auth'
}) // Throws if invalid, expired, wrong audience, etc
console.log(`Checking if ${claims.email} is still in good status...`)

embassy.parseToken docstoken.verify docs

Grant scopes to tokens

// One at a time
await token.grantScope('user|readEmail')
// Many at a time
await token.grantScopes(['user|readProfile', 'user|writeProfile'])
// You can separate the domain
await token.grantScope('store', 'readPurchaseHistory')
// Or pass an entire domain-to-scopes map
await token.grantScopes({
  user: ['readProfile', 'writeProfile'],
  store: ['addToCart', 'submitOrder']
})
// Signing the token will encode these scopes in a binary format, so a
// single token can hold hundreds of scopes and still stay small!

token.grantScope docstoken.grantScopes docs

Tip: Change "grant" to "revoke" and it does exactly what you'd expect!

Query tokens for scopes

// These each resolve with `true` or `false`:
// One at a time
await token.hasScope('user|readEmail')
// Many at a time
await token.hasScopes(['user|readProfile', 'user|writeProfile'])
// You can separate the domain
await token.hasScope('store', 'readPurchaseHistory')
// Or pass an entire domain-to-scopes map
await token.hasScopes({
  user: ['readProfile', 'writeProfile'],
  store: ['addToCart', 'submitOrder']
})

token.hasScope docstoken.hasScopes docs

Read and write claims

console.log(`Request initiated by userId ${token.claims.sub}`)
token.claims.nonce = myNonce
// Token can be signed with no further action

Token docs

Generate keys

HMAC

HMAC is a symmetric signing algorithm, which means the same key is used to sign and verify the token. Embassy supports the following HMAC algorithms: HS256, HS384, HS512. Trying to choose? Higher numbers mean more security, but longer tokens and steeper CPU usage. Use HS256 for access tokens since they're short-lived, and consider higher for refresh tokens.

The "shared secret" for HMAC can be any string -- but you should choose a long one! Be sure to keep it private. Never commit it to git, never send it over Slack, never give your CI/CD access to it.

Asymmetric keys

Embassy supports the following RSA and Elliptic Curve signing algorithms: RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512. The algorithms sign tokens with a private key that must be kept secret, but verify their authenticity with a public key that can be shared openly.

For most use cases, 256-bit Elliptic Curve keys (ES256) are recommended for access tokens due to their low overhead and high security. The following commands will generate a PEM-formatted key pair appropriate for use with Embassy (replace MyKeyPair appropriately):

KEY_ID="MyKeyPair"
# Private key
openssl ecparam -genkey -name secp256k1 -noout -out "${KEY_ID}.priv.pem"
# Public key
openssl ec -in "${KEY_ID}.priv.pem" -pubout -out "${KEY_ID}.pub.pem"

Versions

Embassy is committed to supporting all active LTE versions of Node.js, and strives to stay updated for new non-LTE releases.

License

Embassy is Copyright (c) 2017-2021 Tom Shawver, released under the ultra-permissive ISC license. See LICENSE.txt for details.

Credits

Created by Tom Shawver in 2016 as convenience layer on top of Auth0's fantastic jsonwebtoken Node.js library. Embassy was rewritten in Typescript in 2021.

Originally created for TechnologyAdvice in Nashville, TN.