any website can ask you to sign-in with authlocal.
manage identities on your device any time at authlocal.org.
Β π cryptographic. passwordless, emailless, provable.
Β π½ user-sovereign. copy your keys as you wish.
Β π‘ local-only. fully clientside, keys live on your device.
Β π₯· pseudonymous. no need for personal information.
Β π free and open-source. protocol, not product.
own your identity.
each identity is recoverable from a permanent seed code.
don't lose it. don't share it. it's yours, forever.
websites never see your seed code.
they only see crypto-proof of the identity you selected.
"keep it secret. keep it safe."
Β Β β gandalf, fellowship of the ring
see the https://authlocal.org/demo/
- install and import
@e280/authlocal.npm install @e280/authlocal
import {Auth} from "@e280/authlocal"
- create the auth facility.
see auth.ts.
see default-auth-options.ts.const auth = new Auth()
- react to user session changes.
see user.ts.
auth.useris compatible with @e280/strata.auth.on(user => console.log( user ? `logged in: ${user.id}` : `logged out` ))
- start by remembering a previous user session.
await auth.remember()
- perform a login flow with authlocal.
call this from a button click, or you'll get popup blocked.
see session-options.ts.await auth.loginViaPopup()
- logout immediately.
await auth.logout()
- the widget has a little login/logout ux, if you like.
it's the widget you see at https://authlocal.org/demo/
@e280/sly view exported asWidget.then you put this html on your page:import {makeAuthWidget} from "@e280/authlocal" customElements.define("auth-widget", makeAuthWidget(auth))
<auth-widget>Sign in</auth-widget>
- encrypt.ts
const original = new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF])
const ciphertext = user.encrypt(original)
- decrypt.ts
const cleartext = user.decrypt(ciphertext)
- sign a claim token, containing any data you like.
see options.ts.
const token = user.signClaim({myAction: "getMyInfo"})
- verify a claim token, on your server or elsewhere. (note the import path)
import {verifyClaim} from "@e280/authlocal/core" // we verify that the data was signed by a valid delegate const {claim, proof} = verifyClaim(token, { // your frontend app origin (required) allowedIssuers: ["https://app.e280.org"], }) console.log(claim) // {myAction: "getMyInfo"} console.log(proof.id) // user id // "efe064a4ed1ec1763293612627424c0721b82acd009fc666e6915d8edcfe89e6"
address(id)-- encode a user id hex into a friendly format.import {address} from "@e280/authlocal"
address("efe064a4ed1ec1763293612627424c0721b82acd009fc666e6915d8edcfe89e6") // "calwak_curlex_H9Nts5YRurzidb8mQHkHH323mMT8d3oReimRzxeLgwRw"
addressId(addr)-- decode an address back into a user id.addressEmoji(id)-- derive a friendly emoji from a user id.addressColor(id)-- derive a css color string from a user id.addressMoniker(id)-- get the first part of the address.
- produce a mock auth facility that generates a random fake user.
import {MockAuth, mockUser, mockOrigin} from "@e280/authlocal"
const auth = new MockAuth() await auth.loginViaPopup()
MockAuthdoesn't touch localstorage etc.mockUsergenerates a fake user.mockOriginis the string"https://e280.org".
- https://authlocal.org/ is a fully-static clientside single-page application that operates without any remote services or databases.
- despite being totally clientside, authlocal acts as a federated identity provider for third-party websites, communicating cross-origin via popup postmessage api.
- authlocal depends on paul miller's noble cryptography libraries.
- every authlocal identity is an ed25519 keypair. we call the private key a
secret, and the public key anid. - third-party websites open a popup to authlocal and ask for "delegates", which are ed25519 keypairs derived from the user's secret key (and also bound to the app origin and provided purpose and scope).
- a delegate comes with a "proof" token signed by the user secret, which includes the user id and proves that the delegate is legitimate.
- a delegate can sign new "claim" tokens on behalf of the user, which include the proof token, and thus have a verifiable chain-of-custody back to the user. claims can contain any arbitrary data (such as a request like "read my private profile"), which a third-party server can verify.
- in the default standard login flow, websites ask for two delegates: one ephemeral "auth" delegate that expires in 30 days, and one stable "crypt" delegate with a secret for end-to-end encryption.
- unlike passkeys, authlocal lets you see your seed. you can put it on paper.
- passkeys have a pairwise design with separate credentials for each app. instead, authlocal lets users carry a stable identity across apps. it's a tradeoff.
- in the future, authlocal might use passkeys as another way to recover identities.
