π https://authlocal.org/ π
Authlocal is a free login system for the web.
Any website you visit can request your login by opening an Authlocal popup, but your identity seed files stay safely local on your device. You can go to the authlocal.org website any time to manage your identities.
- π½ User-sovereign β you hold your own seed files
- π Cryptographic β no emails, no passwords
- π₯· Privacy-focused β pseudonymous, device-local, no databases
- π Free and open-source β zero-cost at global scale
Own your identity.
When you create an identity, download the seed and keep it safe. The seed is the identity. Don't lose it. Don't share it. Never give your seed to another person or website. It's yours, forever.
- Install authlocal and friends via npm
npm install @e280/authlocal @e280/stz
- Javascript to install Authlocal on your page
import {install} from "@e280/authlocal" const auth = await install() auth.on(login => { if (login) console.log("logged in", login) else console.log("logged out") })
- Put this stylesheet into your html
<head>
(check the path is valid)<link href="/node_modules/@e280/authlocal/x/themes.css" rel="stylesheet"/>
- Put these new elements in your html
<body>
<auth-user></auth-user> <auth-button></auth-button>
- Take it for a spin!
You should be able to login and logout via Authlocal.
- Never send the login info anywhere. Send claims instead!
- Logins are auto persisted in localStorage for 7 days
- Anatomy of a
login
object:login.sessionId
β id of the login session hex stringlogin.nametag.id
β user identity public key hex stringlogin.nametag.label
β user's chosen nicknamelogin.expiresAt
β js timestamp of when this login expireslogin.isExpired()
β returns true if the login is expired nowlogin.signClaim(options)
β sign a claim
The purpose of a login
, is that it can sign claims on the user's behalf. You can then send those claims to your server and verify them there. A claim contains a cryptographic proof that it stems from a genuine login session signed by the user's seed.
Spritually, a claim is trying to say something like "This user gave permission to this frontend to now say on their behalf:"
- "we want to post this message..."
- "we want to change their avatar..."
- "we want to buy this microtransaction..."
import {Time} from "@e280/stz"
const claimToken = await login.signClaim({
// any json-friendly data you want
claim: {message: "i love ice cream"},
// when should this claim expire?
expiresAt: Time.future.hours(24),
})
import {verifyClaim} from "@e280/authlocal/core"
const {claim, proof} = await verifyClaim({
claimToken,
appOrigins: ["https://e280.org"],
// |
// your website origin goes here
})
proof.sessionId
// id for this login session, looks like:
// "ff730fe2d725aa5210152975212d1068d7fe28ae22b5e62337a4cde42215187a"
proof.nametag.id
// user identity id, looks like:
// "a08263e70a0a48a07e988a7c0931ada6b0a38fa84bf367087b810c614a4c2070"
proof.nametag.label
// user identity nickname, looks like:
// "Michael Scott"
Thumbprint
is an@e280/stz
tool for visualizing 64-char idsimport {Thumbprint} from "@e280/stz"
- id to full thumbprint
Thumbprint.fromHex("005636bab2c73223ccf56f8112432212f57f01ef61452762cd142acd61ed44ed") // "dozmut.winpex.linner.forsep.KgisJ8Pdgey1HC4o8cG59NaLYSoRTiHfA"
- id to short sigil
Thumbprint.sigil.fromHex("005636bab2c73223ccf56f8112432212f57f01ef61452762cd142acd61ed44ed") // "dozmut.winpex"
- thumbprint to id
Thumbprint.toHex("dozmut.winpex.linner.forsep.KgisJ8Pdgey1HC4o8cG59NaLYSoRTiHfA") // "005636bab2c73223ccf56f8112432212f57f01ef61452762cd142acd61ed44ed"
- Authority β the website that provides login sessions (authlocal.org)
authorityOrigin
is the provider's origin, eghttps://authlocal.org
- App β the third party website receiving login sessions (your website)
appOrigin
is your app origin, eghttps://e280.org
- Keypair β an ed25519 keypair
.id
is the public key (64 character hex string).secret
is the private key (64 character hex string)
- Identity β a keypair with a label string
- Seed β text snippet or
.seed
file that stores an identity - Nametag β the public data associated with a user's identity
.id
is the public key (64 character hex string).label
is a nickname (max 32 character string)
- Thumbprint β easier-to-read version of an id
thumbprint
=>dozmut.winpex.linner.forsep.KgisJ8Pdgey1HC4o8cG59NaLYSoRTiHfA
sigil
(first two words) =>dozmut.winpex
preview
(first four words) =>dozmut.winpex.linner.forsep
bulk
(last part) =>KgisJ8Pdgey1HC4o8cG59NaLYSoRTiHfA
- Login β a login session
- is private, should never leave the user's device
.nametag
contains the identity's id and label.expiresAt
js time of the moment this login expires.isExpired()
returns true if the login is now expired.signClaim(options)
sign a claim
- Proof β provenance for login
- is a token signed by an identity
- is public, can be shared around
.nametag
contains the identity's id and label.sessionId
proves a login session is blessed by an identity
- Claim β arbitrary claim your frontend can make
- is a token signed by the login session, verifiable on your server
- is public, can be shared around
- includes the proof token (thus nametag and sessionId)
- includes any arbitrary claim data you want
- verified by
verifyClaim(options)
π§βπ» Authlocal is an e280 project
Open github issues or discussions if you have any questions.
Star us on github, it's the only way we're paid.
Free and open source.