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

@philschatz/auth

v0.0.3

Published

Decentralized authentication and authorization for team collaboration

Downloads

10

Readme

@localfirst/auth provides decentralized authentication and authorization for team collaboration, using a secure chain of cryptographic signatures.

🚧 This is a work in progress

Why

🤝 You're building a local-first app to enable distributed collaboration without a central server.

🔑 You want to authenticate users and manage their permissions.

🚫 You don't want to depend on a centralized authentication server or a key management service.

💙 You want to provide a easy and seamless experience to users creating and joining teams

🤔 You don't want to expose any of the underlying cryptographic complexity.

How

This library solves the following problems without requiring a server or any other central source of truth:

  • Authorization, using a signature chain
  • Authentication, using signature challenges
  • Invitations, using a Seitan token exchange
  • Multi-reader encryption, using lockboxes
  • Key revocation and rotation, using an acyclic directed graph of keys and lockboxes

Each user is assigned a set of cryptographic keys for signatures, asymmetric encryption, and symmetric encryption. These are stored in their device's secure storage.

When Alice first creates a team, she writes the first link of a signature chain, containing her public keys for signatures and encryption. All subsequent links must be signed by Alice or by another team member with admin permissions.

Subsequent links in the chain can serve to add new team members, authorize new devices, define roles, and assign people to roles.

When roles are changed, members leave, or devices are lost or replaced, keys are rotated and associated data re-encrypted.

👉 Learn more: Internals

What

This library provides a Team class, which wraps the signature chain and encapsulates the team's members, devices, and roles. With this object, you can invite new members and manage their permissions.

This object can also use the public keys embedded in the signature chain, along with the user's own secret keys, to provide encryption and signature verification within the team.

Not included

  • Storage This library does not provide storage for user information (including keys) or the signature chain.
  • Networking This library includes a protocol for synchronizing the team's signature chains, but you need to provide a working socket connecting us to a peer.

Examples

yarn add @localfirst/auth

Alice creates a new team

import { user, team } from '@localfirst/auth'

// 👩🏾 Alice
const alice = user.create('alice')
const alicesTeam = team.create({ name: 'Spies Я Us', context: { user: alice } })

Usernames (alice in the example) identify a person uniquely within the team. You could use existing user IDs or names, or email addresses.

Alice invites Bob

// 👩🏾 Alice
const { secretKey } = alicesTeam.invite('bob')

The invitation key is a single-use secret that only Alice and Bob will ever know. By default, it is a 16-character string like aj7x d2jr 9c8f zrbs, and to make it easier to retype if needed, it is in base-30 format, which omits easily confused characters. It might be typed directly into your application, or appended to a URL that Bob can click to accept:

Alice has invited you to team XYZ. To accept, click: http://xyz.org/accept/aj7x+d2jr+9c8f+zrbs

Alice will send the invitation to Bob via a side channel she already trusts (phone call, email, SMS, WhatsApp, Telegram, etc).

Bob accepts the invitation

Bob uses the secret invitation key to generate proof that he was invited, without divulging the key.

// 👨🏻‍🦲 Bob
import { accept } from 'taco'
const proofOfInvitation = accept('aj7x d2jr 9c8f zrbs')

When Bob shows up to join the team, anyone can validate his proof of invitation to admit him to the team - it doesn't have to be an admin.

// 👳🏽‍♂️ Charlie
team.admit(proofOfInvitation)
const success = team.has('bob') // TRUE

Alice defines a role and adds Bob

// 👩🏾 Alice
team.addRole('managers')
team.addMemberRole('bob', 'managers')

Alice checks Bob's role membership

// 👩🏾 Alice
const isAdmin = team.isAdmin('bob') // TRUE

Alice encrypts a message for managers

// 👩🏾 Alice
const message = 'the condor flies at midnight'
const encrypted = team.encrypt(message, 'managers')

Bob decrypts the message

// 👨🏻‍🦲 Bob
const decrypted = team.decrypt(encrypted) // 'the condor flies at midnight'

👉 Learn more: API documentation.

Prior art

💡 This project is inspired by and borrows heavily from Keybase: The signature chain is inspired by their implementation for Keybase Teams, and the invitation mechanism is based on their Seitan token exchange specification, proposed as a more secure alternative to TOFU, or Trust On First Use.

🌮 This library was originally called taco-js. TACO stands for Trust After Confirmation Of invitation.