Open-source project
keslr/keslr_connect avatar
keslr/keslr_connect

keslr_connect: verified humans and a private network for your service

Connect your service to Keslr: sign in with Keslr and read the verification claim that proves a user is a real, vouched-for human — plus run services reachable only by Keslr members.

1,092 stars107 forksTypeScriptMIT

At a glance

What is it?
keslr_connect is a pre-release TypeScript toolkit that signs members in with Keslr and turns a network address into a verified identity. It is MIT licensed, not on npm, and the README warns the API may change before 1.0.
Who is it for?
Adopt keslr_connect if you are already building for the Keslr network and want the OIDC relying party and address lookup without writing the callback handler yourself. Do not adopt it if your users are on the public internet, if you cannot wait on a reviewed developer application, or if you need a published package with a frozen API.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 43 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What keslr_connect actually gives an application

Keslr is an invite-only network. The README states there is no registration form, no email loop and no captcha: you get in because an existing member vouches for you, and that chain of vouching is recorded as a trust graph. If nobody you know is on Keslr, the Keslr team vouches for you instead, and the README says they will probably call you and ask you to say difficult words or pull faces on video.

The repository packages the two things an application can take from that network. The first is a user who is definitely a person, attested by other people. The second is a place to run where the set of parties who can open a TCP connection is the set of verified humans. Member devices get addresses in 100.64.0.0/10, and services such as nod.app.keslr.com are reachable at those addresses and nowhere else.

The README draws a design consequence from the second point that is worth reading twice: if your service is only reachable on the Keslr network, you may not need accounts at all. A device only gets a Keslr address if the member behind it is verified, so anyone who can reach you is already a verified human, you just do not know which one yet. One lookup call resolves their address to their identity. The README recommends the OIDC login only when you need something an address cannot give you: an explicit consent step, a session that survives a change of device, or profile claims.

Three packages and a guestbook

The repository is a TypeScript workspace with three published-intent packages and one example. @keslr/auth is the OpenID Connect relying party: it signs a member in and reads the claim that says whether they are verified. The README describes it as having zero runtime dependencies. @keslr/express wraps that in Express routes and guards for people who do not want to write the callback handler themselves. @keslr/network turns the Keslr address a request came from into the member who owns that device.

Alongside them sits examples/guestbook, described in the README as a guestbook where every signature is a real human. It has no moderation queue, and the README's position is that it does not need one. That is the clearest statement of the project's thesis in the repository: if reachability is already gated by verification, moderation of who may post becomes a different problem.

The split between @keslr/auth and @keslr/express is deliberate and small. The README says @keslr/express is about a hundred lines of glue over @keslr/auth, and points readers who are not on Express at docs/authentication.md to use the underlying package directly. That is a reasonable shape: the framework binding is thin enough to reimplement, and the protocol work is not.

Installing from source and signing in for the first time

The packages are not on npm yet. The README marks the project as pre-release and states the API may change before 1.0, so installation is from source. Clone the repository, install the workspace dependencies and build:

bash
git clone https://github.com/keslr/keslr_connect.git
cd keslr_connect
npm install
npm run build

The root package.json sets engines.node to >=20.19.0, so check your Node version before the build. After that, the README says to reference the packages from your project with npm link, a workspace, or a file: dependency. The npm install line for the published packages appears in the README but is explicitly marked as not yet available.

Before any code runs, you need credentials. Everything starts at developers.keslr.com: sign in with your Keslr account, apply for developer access, and wait, because applications are reviewed. Once approved you create an app, Keslr allocates it an address on the network and a hostname of the form your-app.app.keslr.com, and then asks you to verify DNS. Register an OIDC client if you want the login flow and a network client if you want address lookups. The README calls these separate credentials and says mixing them up is the most common first-day mistake.

With a client ID in hand, the Express path mounts three routes and puts the member on req.keslr:

ts
import express from 'express';
import session from 'express-session';
import { keslrAuth, requireAuth, requireVerified } from '@keslr/express';

const app = express();

app.use(
  session({
    secret: process.env.SESSION_SECRET!,
    resave: false,
    saveUninitialized: false,
    cookie: { httpOnly: true, sameSite: 'lax', secure: true },
  }),
);

app.use(
  keslrAuth({
    issuer: 'https://api.keslr.com',
    clientId: process.env.KESLR_CLIENT_ID!,
    clientSecret: process.env.KESLR_CLIENT_SECRET,
    redirectUri: 'https://example.com/auth/keslr/callback',
  }),
);

app.get('/profile', requireAuth(), (req, res) => res.json(req.keslr!.user));
app.post('/posts', requireVerified(), createPost);

That mounts GET /auth/keslr/login, GET /auth/keslr/callback and POST /auth/keslr/logout. Two configuration details are called out in the README as afternoon-costing. The session cookie must be sameSite: 'lax' rather than 'strict', because 'strict' withholds the cookie on the redirect back from Keslr, so the callback arrives with no session and every login fails with login_expired, a symptom that looks nothing like its cause. And the redirect URI must match byte for byte: http://localhost:3000/cb and http://localhost:3000/cb/ are different URIs, as are localhost and 127.0.0.1.

The claim itself is the part to get right. The README shows the shape of req.keslr.user with id, keslrId, username, verificationStatus, verificationMethod and isVerified, and states plainly that you should read isVerified rather than comparing the status string. Writing verification_status === 'verified' by hand works until you typo it, and the README's argument is that every way of typoing it fails open, letting people in rather than keeping them out. Unknown statuses normalise to unverified for the same reason.

The verification statuses and why the boolean exists

The README lists four statuses. verified means vouched for through the trust graph. pending_verification means verification is underway but not decided. unverified means registered and never verified. rejected means verification was attempted and refused.

Only one of those should let a request through in most applications, and the package makes that decision once, in one place, and tests it. That is the whole argument for isVerified existing next to verificationStatus. The string is data about what happened; the boolean is the policy decision. If you consume the string in your own route handlers you have copied the policy into every place you check it, and the README's claim is that the copy fails in the permissive direction.

There is a second reason the normalisation matters. The README notes that unknown statuses normalise to unverified, which means a status Keslr adds later does not silently become a pass. That is a conservative default and the right one for an identity check, but it also means a new status that should grant access will be denied until the package is updated. If Keslr ever adds a status that ought to count as verified, your dependency upgrade becomes a functional change, not a maintenance chore.

Where keslr_connect is the wrong tool

The gating is the product, and it is also the constraint. If your users are on the public internet and you cannot route them through the Keslr network, the network lookup half of this repository does nothing for you, and you are left with an OIDC relying party that only authenticates people who already hold a Keslr account. The README is explicit that you cannot sign up: there is no registration form, and access comes through a referral from an existing member or through the Keslr team, who will call you or put you on video. That is a hard ceiling on your addressable user base, and it is not a bug you can work around in your application code.

Provisioning is another gate. Developer access is reviewed and the README says you will wait. You cannot spin this up on a Friday afternoon and have a working integration by evening; you can write the code, but you cannot test the real flow until Keslr has approved you, allocated your app an address, and you have verified DNS. The README also does not document rollback, key rotation or what happens to a member whose verification is later revoked, so if your application needs a defined path for those cases you will be designing it yourself.

The pre-release status is the third constraint. The packages are not on npm, the README states the API may change before 1.0, and installing means cloning the repository and linking it into your project. That is workable for an internal service or an experiment. It is a poor fit for anything where a dependency bump should be boring.

How this compares to a conventional OIDC setup

The obvious alternative is a general-purpose OIDC provider such as Keycloak or Auth0, or a social login provider, wired up with a standard client like openid-client. The difference is not the protocol. Both sides speak OpenID Connect, and the callback handler, the session cookie and the redirect URI matching problem are the same shape everywhere.

The difference is what the claim means. A conventional provider tells you that someone controls an email address or an account at a given service. It does not tell you that a chain of other people has vouched for them, and it does not give you a network on which only those people can open a TCP connection. The README's framing is that Keslr gives you a user who is definitely a person, and a place to run where the reachable set is the verified set. Those two properties are what you are adopting, and they are the reason the account model can be simpler than usual.

If you do not need either property, the conventional stack is the better choice: it is published, it has more than one provider, and you are not waiting on a review. If you do need them, the alternative is to build the trust graph and the network yourself, which is not a realistic option for most teams. The honest comparison is between a small pre-release toolkit and a large mature ecosystem, and the deciding factor is whether the verification claim is load-bearing for your product.

Licence, maintenance and the cost of upgrading

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is permissive and carries no copyleft obligation on your own code. The packages are not yet published to npm, so if you vendor them or link them from source, you are distributing on your own terms rather than through a registry. This is a description of the licence text, not legal advice; check the LICENSE file and your own counsel for anything that matters.

The last push to the default branch was on 2026-08-07, and the repository is not archived. There are no releases retrieved for this repository, and the README states the packages are pre-release with a possible API change before 1.0. The practical consequence is that upgrading means tracking the source rather than bumping a version range, and that a change to the verification status handling is the kind of change that can alter who gets through your guards. The root package.json pins engines.node to >=20.19.0, so a Node downgrade in your environment is a build failure rather than a warning.

The workspace is small, which keeps the review surface manageable: three packages plus an example, with TypeScript, ESLint, Prettier and Vitest configured at the root. If you adopt it, pin a commit rather than following main, and re-read the status table before you take a new one.

Editorial conclusion

Adopt keslr_connect if you are already building for the Keslr network and want the OIDC relying party and address lookup without writing the callback handler yourself. Do not adopt it if your users are on the public internet, if you cannot wait on a reviewed developer application, or if you need a published package with a frozen API. Before you commit, verify that your OIDC client and network client are separate credentials, that your redirect URI matches byte for byte, and that you read isVerified rather than comparing the status string.

Frequently asked questions

What is keslr_connect and who is it for?

It is a TypeScript toolkit that connects a service to the Keslr network: an OpenID Connect relying party for signing members in, Express bindings over it, and a lookup that turns a Keslr address into the member who owns that device. It is for developers building services for verified Keslr members.

How do I install keslr_connect?

The packages are not on npm yet. The README says to clone https://github.com/keslr/keslr_connect.git, run npm install and npm run build, then reference the packages with npm link, a workspace, or a file: dependency.

Why does signing in with Keslr fail with login_expired?

The README attributes this to the session cookie being set with sameSite: 'strict', which withholds the cookie on the redirect back from Keslr so the callback arrives with no session. It says to use sameSite: 'lax' instead.

Should I check verificationStatus or isVerified in keslr_connect?

Read isVerified. The README states that comparing the status string by hand works until you typo it, and that every way of typoing it fails open, letting people in rather than keeping them out. Unknown statuses normalise to unverified.

Do I need accounts if my service runs on the Keslr network?

The README says you may not. A device only gets a Keslr address if the member behind it is verified, so anyone who can reach you is already a verified human, and one lookup call turns their address into their identity.

Official sources

  1. Issues
  2. keslr/keslr_connect on GitHub
  3. License: MIT
  4. README
Community notes

Community notes